diff --git a/common/nslog_log.mm b/common/nslog_log.mm index 76f7ac42c..c6ca65d0b 100644 --- a/common/nslog_log.mm +++ b/common/nslog_log.mm @@ -7,7 +7,7 @@ namespace llmr { void NSLogBackend::record(EventSeverity severity, Event event, const std::string &msg) { - NSLog(@"[%s] %s: %@", stringifyEventSeverity(severity), stringifyEvent(event), + NSLog(@"[%s] %s: %@", EventSeverityClass(severity).c_str(), EventClass(event).c_str(), [[NSString alloc] initWithBytes:msg.data() length:msg.size() encoding:NSUTF8StringEncoding]); @@ -23,15 +23,15 @@ void NSLogBackend::record(EventSeverity severity, Event event, const char* forma va_start(args, format); vsnprintf(buffer.get(), len + 1, format, args); va_end(args); - NSLog(@"[%s] %s: %s", stringifyEventSeverity(severity), stringifyEvent(event), buffer.get()); + NSLog(@"[%s] %s: %s", EventSeverityClass(severity).c_str(), EventClass(event).c_str(), buffer.get()); } void NSLogBackend::record(EventSeverity severity, Event event, int64_t code) { - NSLog(@"[%s] %s: (%lld)", stringifyEventSeverity(severity), stringifyEvent(event), code); + NSLog(@"[%s] %s: (%lld)", EventSeverityClass(severity).c_str(), EventClass(event).c_str(), code); } void NSLogBackend::record(EventSeverity severity, Event event, int64_t code, const std::string &msg) { - NSLog(@"[%s] %s: (%lld) %@", stringifyEventSeverity(severity), stringifyEvent(event), code, + NSLog(@"[%s] %s: (%lld) %@", EventSeverityClass(severity).c_str(), EventClass(event).c_str(), code, [[NSString alloc] initWithBytes:msg.data() length:msg.size() encoding:NSUTF8StringEncoding]); diff --git a/common/stderr_log.hpp b/common/stderr_log.hpp index e2492d3af..43d1b41c2 100644 --- a/common/stderr_log.hpp +++ b/common/stderr_log.hpp @@ -9,10 +9,10 @@ class StderrLogBackend : public LogBackend { public: inline ~StderrLogBackend() = default; - void record(EventSeverity severity, Event event, const std::string &msg); - void record(EventSeverity severity, Event event, const char* format, ...); - void record(EventSeverity severity, Event event, int64_t code); - void record(EventSeverity severity, Event event, int64_t code, const std::string &msg); + void record(EventSeverityClass severity, EventClass event, const std::string &msg); + void record(EventSeverityClass severity, EventClass event, const char* format, ...); + void record(EventSeverityClass severity, EventClass event, int64_t code); + void record(EventSeverityClass severity, EventClass event, int64_t code, const std::string &msg); }; diff --git a/include/llmr/platform/event.hpp b/include/llmr/platform/event.hpp index c1552b1c6..133cfc3c5 100644 --- a/include/llmr/platform/event.hpp +++ b/include/llmr/platform/event.hpp @@ -1,8 +1,9 @@ #ifndef LLMR_PLATFORM_EVENT #define LLMR_PLATFORM_EVENT +#include + #include -#include namespace llmr { @@ -14,9 +15,14 @@ enum class EventSeverity : uint8_t { Error, }; -EventSeverity parseEventSeverity(const char *name); -const char *stringifyEventSeverity(EventSeverity eventSeverity); -::std::ostream& operator<<(::std::ostream& os, EventSeverity eventSeverity); +LLMR_DEFINE_ENUM_CLASS(EventSeverityClass, EventSeverity, { + { EventSeverity::Debug, "DEBUG" }, + { EventSeverity::Info, "INFO" }, + { EventSeverity::Test, "TEST" }, + { EventSeverity::Warning, "WARNING" }, + { EventSeverity::Error, "ERROR" }, + { EventSeverity(-1), "UNKNOWN" }, +}); enum class Event : uint8_t { General, @@ -28,9 +34,17 @@ enum class Event : uint8_t { HttpRequest, }; -Event parseEvent(const char *name); -const char *stringifyEvent(Event event); -::std::ostream& operator<<(::std::ostream& os, Event event); +LLMR_DEFINE_ENUM_CLASS(EventClass, Event, { + { Event::General, "General" }, + { Event::Setup, "Setup" }, + { Event::Shader, "Shader" }, + { Event::ParseStyle, "ParseStyle" }, + { Event::ParseTile, "ParseTile" }, + { Event::Render, "Render" }, + { Event::HttpRequest, "HttpRequest" }, + { Event(-1), "Unknown" }, +}); + struct EventPermutation { const EventSeverity severity; diff --git a/include/llmr/style/style_source.hpp b/include/llmr/style/style_source.hpp index a368e4fd7..25a8218df 100644 --- a/include/llmr/style/style_source.hpp +++ b/include/llmr/style/style_source.hpp @@ -9,7 +9,8 @@ namespace llmr { class Source; -struct StyleSource { +class StyleSource { +public: const SourceType type; const std::string url; const uint32_t tile_size; @@ -19,16 +20,10 @@ struct StyleSource { bool enabled = false; std::shared_ptr source; - StyleSource(SourceType type = SourceType::Vector, - const std::string &url = "", - uint32_t tile_size = 512, uint32_t min_zoom = 0, - uint32_t max_zoom = 22) - : type(type), - url(url), - tile_size(tile_size), - min_zoom(min_zoom), - max_zoom(max_zoom) {} - }; + StyleSource(SourceType type = SourceType::Vector, const std::string &url = "", + uint32_t tile_size = 512, uint32_t min_zoom = 0, uint32_t max_zoom = 22) + : type(type), url(url), tile_size(tile_size), min_zoom(min_zoom), max_zoom(max_zoom) {} +}; }; #endif diff --git a/include/llmr/style/types.hpp b/include/llmr/style/types.hpp index fc0cc99ab..82632849a 100644 --- a/include/llmr/style/types.hpp +++ b/include/llmr/style/types.hpp @@ -1,6 +1,8 @@ #ifndef LLMR_STYLE_TYPES #define LLMR_STYLE_TYPES +#include + #include #include @@ -20,9 +22,17 @@ enum class StyleLayerType : uint8_t { Background }; -StyleLayerType parseStyleLayerType(const std::string &type); -const char *stringifyStyleLayerType(StyleLayerType type); -std::ostream& operator<<(std::ostream&, StyleLayerType type); +LLMR_DEFINE_ENUM_CLASS(StyleLayerTypeClass, StyleLayerType, { + { StyleLayerType::Unknown, "unknown" }, + { StyleLayerType::Fill, "fill" }, + { StyleLayerType::Line, "line" }, + { StyleLayerType::Icon, "icon" }, + { StyleLayerType::Text, "text" }, + { StyleLayerType::Raster, "raster" }, + { StyleLayerType::Composite, "composite" }, + { StyleLayerType::Background, "background" }, + { StyleLayerType(-1), "unknown" }, +}); enum class WindingType : uint8_t { diff --git a/include/llmr/util/enum.hpp b/include/llmr/util/enum.hpp new file mode 100644 index 000000000..9f3643b4f --- /dev/null +++ b/include/llmr/util/enum.hpp @@ -0,0 +1,55 @@ +#ifndef LLMR_UTIL_ENUM +#define LLMR_UTIL_ENUM + +#include +#include + +namespace llmr { + +template +struct EnumValue { + const Type value; + const char *name; +}; + +template *names, const size_t length> +struct Enum { + using Type = EnumName; + Type value; + static const constexpr size_t l = length; +private: + static constexpr inline bool compare(const char *a, const char *b) { + return *a == *b && (*a == '\0' || compare(a + 1, b + 1)); + } + static constexpr inline const char *lookup_type(Type e, EnumValue const * const l, size_t r) { + return r == 0 ? "" : l->value == e ? l->name : lookup_type(e, l + 1, r - 1); + } + static constexpr inline Type lookup_name(const char *n, EnumValue const * const l, size_t r) { + return r == 0 ? Type(-1) : compare(l->name, n) ? l->value : lookup_name(n, l + 1, r - 1); + } +public: + inline constexpr Enum(const char *n) : value(lookup_name(n, names, length)) {} + inline constexpr Enum(const std::string &n) : value(lookup_name(n.c_str(), names, length)) {} + inline constexpr Enum(Type t) : value(t) {} + + inline void operator=(const char *n) { value = lookup_name(n, names, length); } + inline void operator=(const std::string &n) { *this = n.c_str(); } + inline void operator=(Type t) { value = t; } + + inline constexpr bool valid() const { return value != Type(-1); } + + inline constexpr const char *c_str() const { return lookup_type(value, names, length); } + inline std::string str() const { return c_str(); } + + inline constexpr operator Type() const { return value; } +}; + +#define LLMR_DEFINE_ENUM_CLASS(name, type, strings...) \ + const constexpr ::llmr::EnumValue type##_names[] = strings; \ + using name = ::llmr::Enum)>; \ + inline std::ostream& operator<<(std::ostream& os, type t) { return os << name(t).str(); } + +} + +#endif + diff --git a/src/platform/event.cpp b/src/platform/event.cpp deleted file mode 100644 index c60faaeba..000000000 --- a/src/platform/event.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include - -#include - -namespace llmr { - -EventSeverity parseEventSeverity(const char *name) { - if (strcmp(name, "DEBUG") == 0) return EventSeverity::Debug; - if (strcmp(name, "INFO") == 0) return EventSeverity::Info; - if (strcmp(name, "TEST") == 0) return EventSeverity::Test; - if (strcmp(name, "WARNING") == 0) return EventSeverity::Warning; - if (strcmp(name, "ERROR") == 0) return EventSeverity::Error; - return EventSeverity(-1); -} - -const char *stringifyEventSeverity(EventSeverity eventSeverity) { - switch (eventSeverity) { - case EventSeverity::Debug: return "DEBUG"; - case EventSeverity::Info: return "INFO"; - case EventSeverity::Test: return "TEST"; - case EventSeverity::Warning: return "WARNING"; - case EventSeverity::Error: return "ERROR"; - default: return "UNKNOWN"; - } -} - -::std::ostream& operator<<(::std::ostream& os, EventSeverity eventSeverity) { - return os << stringifyEventSeverity(eventSeverity); -} - -Event parseEvent(const char *name) { - if (strcmp(name, "General") == 0) return Event::General; - if (strcmp(name, "Setup") == 0) return Event::Setup; - if (strcmp(name, "Shader") == 0) return Event::Shader; - if (strcmp(name, "ParseStyle") == 0) return Event::ParseStyle; - if (strcmp(name, "ParseTile") == 0) return Event::ParseTile; - if (strcmp(name, "Render") == 0) return Event::Render; - if (strcmp(name, "HttpRequest") == 0) return Event::HttpRequest; - return Event(-1); -} - -const char *stringifyEvent(Event event) { - switch (event) { - case Event::General: return "General"; - case Event::Setup: return "Setup"; - case Event::Shader: return "Shader"; - case Event::ParseStyle: return "ParseStyle"; - case Event::ParseTile: return "ParseTile"; - case Event::Render: return "Render"; - case Event::HttpRequest: return "HttpRequest"; - default: return "Unknown"; - } -} - -::std::ostream& operator<<(::std::ostream& os, Event event) { - return os << stringifyEvent(event); -} - - -} diff --git a/src/shader/shader.cpp b/src/shader/shader.cpp index aaf4c2792..aa3e76825 100644 --- a/src/shader/shader.cpp +++ b/src/shader/shader.cpp @@ -4,6 +4,7 @@ #include #include +#include using namespace llmr; diff --git a/src/style/style_parser.cpp b/src/style/style_parser.cpp index 434f07a72..50a078983 100644 --- a/src/style/style_parser.cpp +++ b/src/style/style_parser.cpp @@ -559,7 +559,7 @@ void StyleParser::parseLayer(std::pair> &pair if (!type.IsString()) { fprintf(stderr, "[WARNING] layer type of '%s' must be a string\n", layer->id.c_str()); } else { - layer->type = parseStyleLayerType({ type.GetString(), type.GetStringLength() }); + layer->type = StyleLayerTypeClass(std::string { type.GetString(), type.GetStringLength() }); } } diff --git a/src/style/types.cpp b/src/style/types.cpp index 41a17d0b1..e69de29bb 100644 --- a/src/style/types.cpp +++ b/src/style/types.cpp @@ -1,35 +0,0 @@ -#include - -#include - -namespace llmr { - -StyleLayerType parseStyleLayerType(const std::string &type) { - if (type == "fill") return StyleLayerType::Fill; - if (type == "line") return StyleLayerType::Line; - if (type == "icon") return StyleLayerType::Icon; - if (type == "text") return StyleLayerType::Text; - if (type == "raster") return StyleLayerType::Raster; - if (type == "composite") return StyleLayerType::Composite; - if (type == "background") return StyleLayerType::Background; - return StyleLayerType::Unknown; -} - -const char *stringifyStyleLayerType(StyleLayerType type) { - switch (type) { - case StyleLayerType::Fill: return "fill"; - case StyleLayerType::Line: return "line"; - case StyleLayerType::Icon: return "icon"; - case StyleLayerType::Text: return "text"; - case StyleLayerType::Raster: return "raster"; - case StyleLayerType::Composite: return "composite"; - case StyleLayerType::Background: return "background"; - default: return "unknown"; - } -} - -std::ostream& operator<<(std::ostream& os, StyleLayerType type) { - return os << stringifyStyleLayerType(type); -} - -} diff --git a/test/enums.cpp b/test/enums.cpp new file mode 100644 index 000000000..3df711dd8 --- /dev/null +++ b/test/enums.cpp @@ -0,0 +1,43 @@ +#include +#include "gtest/gtest.h" + +#include + +#include + +using namespace llmr; + +TEST(Enums, StyleLayerType) { + std::cerr << StyleLayerType::Raster; + + ASSERT_EQ(StyleLayerType::Unknown, StyleLayerTypeClass("unknown")); + ASSERT_EQ(StyleLayerType::Fill, StyleLayerTypeClass("fill")); + ASSERT_EQ(StyleLayerType::Line, StyleLayerTypeClass("line")); + ASSERT_EQ(StyleLayerType::Icon, StyleLayerTypeClass("icon")); + ASSERT_EQ(StyleLayerType::Text, StyleLayerTypeClass("text")); + ASSERT_EQ(StyleLayerType::Raster, StyleLayerTypeClass("rastr")); + ASSERT_EQ(StyleLayerType::Composite, StyleLayerTypeClass("composite")); + ASSERT_EQ(StyleLayerType::Background, StyleLayerTypeClass("background")); + + ASSERT_EQ(StyleLayerType::Unknown, StyleLayerTypeClass(StyleLayerType::Unknown)); + ASSERT_EQ(StyleLayerType::Fill, StyleLayerTypeClass(StyleLayerType::Fill)); + ASSERT_EQ(StyleLayerType::Line, StyleLayerTypeClass(StyleLayerType::Line)); + ASSERT_EQ(StyleLayerType::Icon, StyleLayerTypeClass(StyleLayerType::Icon)); + ASSERT_EQ(StyleLayerType::Text, StyleLayerTypeClass(StyleLayerType::Text)); + ASSERT_EQ(StyleLayerType::Raster, StyleLayerTypeClass(StyleLayerType::Raster)); + ASSERT_EQ(StyleLayerType::Composite, StyleLayerTypeClass(StyleLayerType::Composite)); + ASSERT_EQ(StyleLayerType::Background, StyleLayerTypeClass(StyleLayerType::Background)); + + ASSERT_EQ(StyleLayerTypeClass(StyleLayerType::Unknown), StyleLayerTypeClass(StyleLayerType::Unknown)); + ASSERT_EQ(StyleLayerTypeClass(StyleLayerType::Fill), StyleLayerTypeClass(StyleLayerType::Fill)); + ASSERT_EQ(StyleLayerTypeClass(StyleLayerType::Line), StyleLayerTypeClass(StyleLayerType::Line)); + ASSERT_EQ(StyleLayerTypeClass(StyleLayerType::Icon), StyleLayerTypeClass(StyleLayerType::Icon)); + ASSERT_EQ(StyleLayerTypeClass(StyleLayerType::Text), StyleLayerTypeClass(StyleLayerType::Text)); + ASSERT_EQ(StyleLayerTypeClass(StyleLayerType::Raster), StyleLayerTypeClass(StyleLayerType::Raster)); + ASSERT_EQ(StyleLayerTypeClass(StyleLayerType::Composite), StyleLayerTypeClass(StyleLayerType::Composite)); + ASSERT_EQ(StyleLayerTypeClass(StyleLayerType::Background), StyleLayerTypeClass(StyleLayerType::Background)); + + ASSERT_EQ(false, StyleLayerTypeClass("").valid()); + ASSERT_EQ(false, StyleLayerTypeClass("Backgrund").valid()); +} + diff --git a/test/headless.cpp b/test/headless.cpp index 523f66d0d..a7f34b9d4 100644 --- a/test/headless.cpp +++ b/test/headless.cpp @@ -94,8 +94,8 @@ TEST_P(HeadlessTest, render) { if (js_entry.Size() == 5) { const uint32_t count = js_entry[rapidjson::SizeType(0)].GetUint(); const FixtureLogBackend::LogMessage message { - parseEventSeverity(js_entry[rapidjson::SizeType(1)].GetString()), - parseEvent(js_entry[rapidjson::SizeType(2)].GetString()), + EventSeverityClass(js_entry[rapidjson::SizeType(1)].GetString()), + EventClass(js_entry[rapidjson::SizeType(2)].GetString()), js_entry[rapidjson::SizeType(3)].GetInt64(), js_entry[rapidjson::SizeType(4)].GetString() }; @@ -104,15 +104,15 @@ TEST_P(HeadlessTest, render) { const uint32_t count = js_entry[rapidjson::SizeType(0)].GetUint(); if (js_entry[rapidjson::SizeType(3)].IsString()) { const FixtureLogBackend::LogMessage message { - parseEventSeverity(js_entry[rapidjson::SizeType(1)].GetString()), - parseEvent(js_entry[rapidjson::SizeType(2)].GetString()), + EventSeverityClass(js_entry[rapidjson::SizeType(1)].GetString()), + EventClass(js_entry[rapidjson::SizeType(2)].GetString()), js_entry[rapidjson::SizeType(3)].GetString() }; ASSERT_EQ(count, log.count(message)) << "Message: " << message << "Full Log: " << std::endl << log.messages; } else { const FixtureLogBackend::LogMessage message { - parseEventSeverity(js_entry[rapidjson::SizeType(1)].GetString()), - parseEvent(js_entry[rapidjson::SizeType(2)].GetString()), + EventSeverityClass(js_entry[rapidjson::SizeType(1)].GetString()), + EventClass(js_entry[rapidjson::SizeType(2)].GetString()), js_entry[rapidjson::SizeType(3)].GetInt64() }; ASSERT_EQ(count, log.count(message)) << "Message: " << message << "Full Log: " << std::endl << log.messages; @@ -120,8 +120,8 @@ TEST_P(HeadlessTest, render) { } else if (js_entry.Size() == 3) { const uint32_t count = js_entry[rapidjson::SizeType(0)].GetUint(); const FixtureLogBackend::LogMessage message { - parseEventSeverity(js_entry[rapidjson::SizeType(1)].GetString()), - parseEvent(js_entry[rapidjson::SizeType(2)].GetString()) + EventSeverityClass(js_entry[rapidjson::SizeType(1)].GetString()), + EventClass(js_entry[rapidjson::SizeType(2)].GetString()) }; ASSERT_EQ(count, log.count(message)) << "Message: " << message << "Full Log: " << std::endl << log.messages; } else { diff --git a/test/test.gyp b/test/test.gyp index c6869fd47..95f22c257 100644 --- a/test/test.gyp +++ b/test/test.gyp @@ -90,6 +90,22 @@ "../llmr.gyp:llmr-x86" ] }, + { + "target_name": "enums", + "product_name": "test_enums", + "type": "executable", + "libraries": [ + "-lpthread", + ], + "sources": [ + "./main.cpp", + "./enums.cpp", + ], + "dependencies": [ + "../deps/gtest/gtest.gyp:gtest", + "../llmr.gyp:llmr-x86" + ] + }, { "target_name": "variant", "product_name": "test_variant", @@ -167,6 +183,7 @@ "dependencies": [ "rotation_range", "clip_ids", + "enums", "variant", "tile", "functions",