From 4fc055e24899a3a05d2212143fabb441b7e2cdf5 Mon Sep 17 00:00:00 2001 From: Ben Barsdell Date: Tue, 30 May 2023 11:00:16 +1000 Subject: [PATCH 1/2] Overhaul options handling - Refactors all options handling to use a single parser implementation and new Options and OptionsVec classes. - This makes the code significantly cleaner and more robust. - Maintains backwards compatibility with string vectors at API boundaries via implicit conversions. --- jitify2.hpp | 905 +++++++++++++++++++++++++++--------------------- jitify2_test.cu | 81 ++++- 2 files changed, 594 insertions(+), 392 deletions(-) diff --git a/jitify2.hpp b/jitify2.hpp index 485fee6..04908da 100644 --- a/jitify2.hpp +++ b/jitify2.hpp @@ -45,7 +45,10 @@ // unnecessary dependencies. #ifdef JITIFY_SERIALIZATION_ONLY +#include +#include #include +#include #include #include #include @@ -100,11 +103,13 @@ #endif #include +#include #include #include #include #include #include +#include #include #include #include @@ -220,6 +225,283 @@ using StringRef = const std::string&; using StringSlice = std::string; #endif +class Option { + public: + Option() = default; + explicit Option(std::string _key, std::string _value = {}, + StringVec _repr = {}) + : key_(std::move(_key)), + value_(std::move(_value)), + repr_(std::move(_repr)) { + if (repr_.empty()) { + repr_ = {key_}; + if (!value_.empty()) { + repr_.front() += "=" + value_; + } + } + // TODO: Consider changing key and value to be views into key_and_value to + // avoid double-storage. + if (value_.empty()) { + key_and_value_ = key_; + } else { + key_and_value_.reserve(key_.size() + 1 + value_.size()); + key_and_value_.append(key_); + key_and_value_.append("="); + key_and_value_.append(value_); + } + } + + const std::string& key() const { return key_; } + const std::string& value() const { return value_; } + const std::string& key_and_value() const { return key_and_value_; } + const StringVec& original_representation() const { return repr_; } + + friend const std::string& to_string(const Option& option) { + return option.key_and_value(); + } + + friend std::ostream& operator<<(std::ostream& os, const Option& option) { + return os << option.key_and_value(); + } + + friend bool operator==(const Option& lhs, const Option& rhs) { + return lhs.key_ == rhs.key_ && lhs.value_ == rhs.value_; + } + friend bool operator!=(const Option& lhs, const Option& rhs) { + return !(lhs == rhs); + } + + private: + std::string key_; + std::string value_; + std::string key_and_value_; + StringVec repr_; +}; + +namespace detail { + +// Strip whitespace from string in-place. +inline void ltrim(std::string* s) { + s->erase(s->begin(), std::find_if(s->begin(), s->end(), [](unsigned char c) { + return !std::isspace(c); + })); +} +inline void rtrim(std::string* s) { + s->erase(std::find_if(s->rbegin(), s->rend(), + [](unsigned char c) { return !std::isspace(c); }) + .base(), + s->end()); +} +inline void trim(std::string* s) { + ltrim(s); + rtrim(s); +} + +// Strip whitespace from a string view. +inline StringSlice ltrim(StringRef s) { + size_t beg = std::find_if(s.begin(), s.end(), + [](unsigned char c) { return !std::isspace(c); }) - + s.begin(); + return s.substr(beg); +} +inline StringSlice rtrim(StringRef s) { + size_t end = std::find_if(s.rbegin(), s.rend(), + [](unsigned char c) { return !std::isspace(c); }) + .base() - + s.begin(); + return s.substr(0, end); +} +inline StringSlice trim(StringRef s) { return rtrim(ltrim(s)); } + +} // namespace detail + +class OptionsVec { + using vec_type = std::vector