// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #pragma once #include "types.h" #include #include #include namespace config { /** * To reduce the need for code in autogenerated config classes, these * helper functions exist to help parsing. */ class ConfigParser { public: class Cfg { public: Cfg(const std::vector & v) : _cfg(v.empty() ? nullptr : &v[0]), _sz(v.size()) { } Cfg(const std::vector> & v) : _cfg(v.empty() ? nullptr : &v[0]), _sz(v.size()) { } size_t size() const noexcept { return _sz; } const vespalib::string & operator[] (size_t idx) const noexcept { return _cfg[idx]; } private: const vespalib::string * _cfg; size_t _sz; }; private: static StringVector getLinesForKey(vespalib::stringref key, Cfg config); static std::vector splitArray(Cfg config); static std::map splitMap(Cfg config); static vespalib::string deQuote(const vespalib::string & source); static void throwNoDefaultValue(vespalib::stringref key); template static T convert(const StringVector & config); static vespalib::string arrayToString(Cfg config); template static T parseInternal(vespalib::stringref key, Cfg config); template static T parseInternal(vespalib::stringref key, Cfg config, T defaultValue); template static V parseArrayInternal(vespalib::stringref key, Cfg config); template static std::map parseMapInternal(vespalib::stringref key, Cfg config); template static T parseStructInternal(vespalib::stringref key, Cfg config); public: static void stripLinesForKey(vespalib::stringref key, std::set& config); static std::set getUniqueNonWhiteSpaceLines(Cfg config); static vespalib::string stripWhitespace(vespalib::stringref source); template static T parse(vespalib::stringref key, Cfg config) { return parseInternal(key, config); } template static T parse(vespalib::stringref key, Cfg config, T defaultValue) { return parseInternal(key, config, defaultValue); } template static V parseArray(vespalib::stringref key, Cfg config) { return parseArrayInternal(key, config); } template static std::map parseMap(vespalib::stringref key, Cfg config) { return parseMapInternal(key, config); } template static T parseStruct(vespalib::stringref key, Cfg config) { return parseStructInternal(key, config); } }; template T ConfigParser::parseInternal(vespalib::stringref key, Cfg config) { StringVector lines = getLinesForKey(key, config); if (lines.size() == 0) { throwNoDefaultValue(key); } return convert(lines); } template T ConfigParser::parseInternal(vespalib::stringref key, Cfg config, T defaultValue) { StringVector lines = getLinesForKey(key, config); if (lines.size() == 0) { return defaultValue; } return convert(lines); } template T ConfigParser::convert(const StringVector & lines) { return T(lines); } template std::map ConfigParser::parseMapInternal(vespalib::stringref key, Cfg config) { StringVector lines = getLinesForKey(key, config); using SplittedMap = std::map; SplittedMap s = splitMap(lines); std::map retval; for (const auto & e : s) { retval[e.first] = convert(e.second); } return retval; } template V ConfigParser::parseArrayInternal(vespalib::stringref key, Cfg config) { StringVector lines = getLinesForKey(key, config); std::vector split = splitArray(lines); V retval; retval.reserve(split.size()); for (uint32_t i = 0; i < split.size(); i++) { retval.push_back(convert(split[i])); } return retval; } template T ConfigParser::parseStructInternal(vespalib::stringref key, Cfg config) { StringVector lines = getLinesForKey(key, config); return convert(lines); } template<> bool ConfigParser::convert(const StringVector & config); template<> int32_t ConfigParser::convert(const StringVector & config); template<> int64_t ConfigParser::convert(const StringVector & config); template<> double ConfigParser::convert(const StringVector & config); template<> vespalib::string ConfigParser::convert(const StringVector & config); } // config