/** * * HttpViewData.h * An Tao * * Copyright 2018, An Tao. All rights reserved. * https://github.com/an-tao/drogon * Use of this source code is governed by a MIT license * that can be found in the License file. * * Drogon * */ #pragma once #include #include #include #include #include #include #include #include #include namespace drogon { /// This class represents the data set displayed in views. class HttpViewData { public: /// The function template is used to get an item in the data set by the key /// parameter. template const T &get(const std::string &key) const { const static T nullVal = T(); auto it = viewData_.find(key); if (it != viewData_.end()) { if (typeid(T) == it->second.type()) { return *(any_cast(&(it->second))); } else { LOG_ERROR << "Bad type"; } } return nullVal; } /// Insert an item identified by the key parameter into the data set; void insert(const std::string &key, any &&obj) { viewData_[key] = std::move(obj); } void insert(const std::string &key, const any &obj) { viewData_[key] = obj; } /// Insert an item identified by the key parameter into the data set; The /// item is converted to a string. template void insertAsString(const std::string &key, T &&val) { std::stringstream ss; ss << val; viewData_[key] = ss.str(); } /// Insert a formated string identified by the key parameter. void insertFormattedString(const std::string &key, const char *format, ...) { std::string strBuffer; strBuffer.resize(128); va_list ap, backup_ap; va_start(ap, format); va_copy(backup_ap, ap); auto result = vsnprintf((char *)strBuffer.data(), strBuffer.size(), format, backup_ap); va_end(backup_ap); if ((result >= 0) && ((std::string::size_type)result < strBuffer.size())) { strBuffer.resize(result); } else { while (true) { if (result < 0) { // Older snprintf() behavior. Just try doubling the buffer // size strBuffer.resize(strBuffer.size() * 2); } else { strBuffer.resize(result + 1); } va_copy(backup_ap, ap); auto result = vsnprintf((char *)strBuffer.data(), strBuffer.size(), format, backup_ap); va_end(backup_ap); if ((result >= 0) && ((std::string::size_type)result < strBuffer.size())) { strBuffer.resize(result); break; } } } va_end(ap); viewData_[key] = std::move(strBuffer); } /// Get the 'any' object by the key parameter. any &operator[](const std::string &key) const { return viewData_[key]; } /// Translate some special characters to HTML format /** * such as: * @code " --> " & --> & < --> < > --> > @endcode */ static std::string htmlTranslate(const char *str, size_t length); static std::string htmlTranslate(const std::string &str) { return htmlTranslate(str.data(), str.length()); } static std::string htmlTranslate(const string_view &str) { return htmlTranslate(str.data(), str.length()); } static bool needTranslation(const std::string &str) { for (auto const &c : str) { switch (c) { case '"': case '&': case '<': case '>': return true; default: continue; } } return false; } static bool needTranslation(const string_view &str) { for (auto const &c : str) { switch (c) { case '"': case '&': case '<': case '>': return true; default: continue; } } return false; } protected: using ViewDataMap = std::unordered_map; mutable ViewDataMap viewData_; }; } // namespace drogon