1
0
Fork 0
mirror of https://github.com/KingDuckZ/kamokan.git synced 2024-11-27 00:43:47 +00:00

Make a SettingsBag class that wraps the ini settings.

Easily allows to have default values for options
that are not specified in the loaded ini file.
This commit is contained in:
King_DuckZ 2017-04-21 23:10:16 +01:00
parent 34b4588481
commit b03c3198b8
14 changed files with 134 additions and 37 deletions

View file

@ -27,6 +27,7 @@ add_executable(${PROJECT_NAME}
pathname/pathname.cpp pathname/pathname.cpp
response_factory.cpp response_factory.cpp
list_highlight_langs.cpp list_highlight_langs.cpp
settings_bag.cpp
) )
configure_file( configure_file(

View file

@ -19,8 +19,8 @@
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
namespace tawashi { namespace tawashi {
IndexResponse::IndexResponse (const IniFile& parIni) : IndexResponse::IndexResponse (const SettingsBag& parSettings) :
Response(Response::ContentType, "text/html", "index", parIni, false) Response(Response::ContentType, "text/html", "index", parSettings, false)
{ {
} }
} //namespace tawashi } //namespace tawashi

View file

@ -23,7 +23,7 @@
namespace tawashi { namespace tawashi {
class IndexResponse : public Response { class IndexResponse : public Response {
public: public:
explicit IndexResponse (const IniFile& parIni); explicit IndexResponse (const SettingsBag& parSettings);
private: private:
}; };

View file

@ -25,7 +25,7 @@
#include "safe_stack_object.hpp" #include "safe_stack_object.hpp"
#include "pathname/pathname.hpp" #include "pathname/pathname.hpp"
#include "duckhandy/compatibility.h" #include "duckhandy/compatibility.h"
#include "duckhandy/lexical_cast.hpp" #include "settings_bag.hpp"
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <fstream> #include <fstream>
@ -52,8 +52,17 @@ namespace {
} }
template <typename T> template <typename T>
std::unique_ptr<tawashi::Response> make_response (const tawashi::IniFile& parIni) { std::unique_ptr<tawashi::Response> make_response (const tawashi::SettingsBag& parSettings) {
return static_cast<std::unique_ptr<tawashi::Response>>(std::make_unique<T>(parIni)); return static_cast<std::unique_ptr<tawashi::Response>>(std::make_unique<T>(parSettings));
}
void fill_defaults (tawashi::SettingsBag& parSettings) {
parSettings.add_default("redis_server", "127.0.0.1");
parSettings.add_default("redis_port", "6379");
parSettings.add_default("redis_mode", "sock");
parSettings.add_default("redis_sock", "/tmp/redis.sock");
parSettings.add_default("base_uri", "http://127.0.0.1");
parSettings.add_default("website_root", "html");
} }
} //unnamed namespace } //unnamed namespace
@ -72,8 +81,11 @@ int main() {
auto ini = SafeStackObject<tawashi::IniFile>(std::istream_iterator<char>(conf), std::istream_iterator<char>()); auto ini = SafeStackObject<tawashi::IniFile>(std::istream_iterator<char>(conf), std::istream_iterator<char>());
conf.close(); conf.close();
auto settings = SafeStackObject<tawashi::SettingsBag>(ini);
fill_defaults(*settings);
tawashi::cgi::Env cgi_env; tawashi::cgi::Env cgi_env;
tawashi::ResponseFactory resp_factory(ini); tawashi::ResponseFactory resp_factory(settings);
resp_factory.register_maker("index.cgi", &make_response<IndexResponse>); resp_factory.register_maker("index.cgi", &make_response<IndexResponse>);
resp_factory.register_maker("", &make_response<IndexResponse>); resp_factory.register_maker("", &make_response<IndexResponse>);
resp_factory.register_maker("paste.cgi", &make_response<SubmitPasteResponse>); resp_factory.register_maker("paste.cgi", &make_response<SubmitPasteResponse>);

View file

@ -23,8 +23,8 @@
#include <sstream> #include <sstream>
namespace tawashi { namespace tawashi {
PastieResponse::PastieResponse (const IniFile& parIni) : PastieResponse::PastieResponse (const SettingsBag& parSettings) :
Response(Response::ContentType, "text/html", "", parIni, true), Response(Response::ContentType, "text/html", "", parSettings, true),
m_plain_text(false) m_plain_text(false)
{ {
} }

View file

@ -24,7 +24,7 @@
namespace tawashi { namespace tawashi {
class PastieResponse : public Response { class PastieResponse : public Response {
public: public:
explicit PastieResponse (const IniFile& parIni); explicit PastieResponse (const SettingsBag& parSettings);
private: private:
virtual void on_process() override; virtual void on_process() override;

View file

@ -17,7 +17,7 @@
#include "response.hpp" #include "response.hpp"
#include "incredis/incredis.hpp" #include "incredis/incredis.hpp"
#include "ini_file.hpp" #include "settings_bag.hpp"
#include "tawashiConfig.h" #include "tawashiConfig.h"
#include "duckhandy/stringize.h" #include "duckhandy/stringize.h"
#include "pathname/pathname.hpp" #include "pathname/pathname.hpp"
@ -43,28 +43,27 @@ namespace tawashi {
// return path.substr(start_index, substr_len); // return path.substr(start_index, substr_len);
//} //}
std::string make_root_path (const IniFile::KeyValueMapType& parSettings) { std::string make_root_path (const SettingsBag& parSettings) {
const auto it_found = parSettings.find("website_root"); auto retval = parSettings["website_root"];
if (parSettings.end() == it_found) { if (retval.empty()) {
return ""; return "";
} }
else { else {
mchlib::PathName retval(it_found->second); return mchlib::PathName(retval).path() + '/';
return retval.path() + '/';
} }
} }
redis::IncRedis make_incredis (const tawashi::IniFile::KeyValueMapType& parSettings) { redis::IncRedis make_incredis (const tawashi::SettingsBag& parSettings) {
using redis::IncRedis; using redis::IncRedis;
if (parSettings.at("redis_mode") == "inet") { if (parSettings["redis_mode"] == "inet") {
return IncRedis( return IncRedis(
std::string(parSettings.at("redis_server")), std::string(parSettings["redis_server"]),
dhandy::lexical_cast<uint16_t>(parSettings.at("redis_port")) dhandy::lexical_cast<uint16_t>(parSettings["redis_port"])
); );
} }
else if (parSettings.at("redis_mode") == "sock") { else if (parSettings["redis_mode"] == "sock") {
return IncRedis(std::string(parSettings.at("redis_sock"))); return IncRedis(std::string(parSettings["redis_sock"]));
} }
else { else {
throw std::runtime_error("Unknown setting for \"redis_mode\", valid settings are \"inet\" or \"sock\""); throw std::runtime_error("Unknown setting for \"redis_mode\", valid settings are \"inet\" or \"sock\"");
@ -99,17 +98,17 @@ namespace tawashi {
} }
} //unnamed namespace } //unnamed namespace
Response::Response (Types parRespType, std::string&& parValue, std::string&& parPageBaseName, const IniFile& parIni, bool parWantRedis) : Response::Response (Types parRespType, std::string&& parValue, std::string&& parPageBaseName, const SettingsBag& parSettings, bool parWantRedis) :
m_resp_value(std::move(parValue)), m_resp_value(std::move(parValue)),
m_base_uri(parIni.parsed().at("tawashi").at("base_uri")), m_base_uri(parSettings["base_uri"]),
//m_page_basename(fetch_page_basename(m_cgi_env)), //m_page_basename(fetch_page_basename(m_cgi_env)),
m_website_root(make_root_path(parIni.parsed().at("tawashi"))), m_website_root(make_root_path(parSettings)),
m_page_basename(std::move(parPageBaseName)), m_page_basename(std::move(parPageBaseName)),
m_resp_type(parRespType), m_resp_type(parRespType),
m_header_sent(false) m_header_sent(false)
{ {
if (parWantRedis) { if (parWantRedis) {
m_redis = std::make_unique<redis::IncRedis>(make_incredis(parIni.parsed().at("tawashi"))); m_redis = std::make_unique<redis::IncRedis>(make_incredis(parSettings));
m_redis->connect(); m_redis->connect();
} }
} }

View file

@ -29,7 +29,7 @@ namespace redis {
} //namespace redis } //namespace redis
namespace tawashi { namespace tawashi {
class IniFile; class SettingsBag;
class Response { class Response {
public: public:
@ -43,7 +43,7 @@ namespace tawashi {
Location Location
}; };
Response (Types parRespType, std::string&& parValue, std::string&& parPageBaseName, const IniFile& parIni, bool parWantRedis); Response (Types parRespType, std::string&& parValue, std::string&& parPageBaseName, const SettingsBag& parSettings, bool parWantRedis);
const cgi::Env& cgi_env() const; const cgi::Env& cgi_env() const;
void change_type (Types parRespType, std::string&& parValue); void change_type (Types parRespType, std::string&& parValue);
const boost::string_ref& base_uri() const; const boost::string_ref& base_uri() const;

View file

@ -16,7 +16,7 @@
*/ */
#include "response_factory.hpp" #include "response_factory.hpp"
#include "ini_file.hpp" #include "settings_bag.hpp"
#include <functional> #include <functional>
#include <boost/container/flat_map.hpp> #include <boost/container/flat_map.hpp>
@ -25,12 +25,12 @@ namespace tawashi {
} //unnamed namespace } //unnamed namespace
struct ResponseFactory::LocalData { struct ResponseFactory::LocalData {
Kakoune::SafePtr<IniFile> settings; Kakoune::SafePtr<SettingsBag> settings;
boost::container::flat_map<std::string, ResponseMakerFunc> makers; boost::container::flat_map<std::string, ResponseMakerFunc> makers;
ResponseMakerFunc jolly_maker; ResponseMakerFunc jolly_maker;
}; };
ResponseFactory::ResponseFactory (const Kakoune::SafePtr<IniFile>& parSettings) : ResponseFactory::ResponseFactory (const Kakoune::SafePtr<SettingsBag>& parSettings) :
m_local_data(std::make_unique<LocalData>()) m_local_data(std::make_unique<LocalData>())
{ {
m_local_data->settings = parSettings; m_local_data->settings = parSettings;

View file

@ -22,13 +22,13 @@
#include <memory> #include <memory>
namespace tawashi { namespace tawashi {
class IniFile; class SettingsBag;
class ResponseFactory { class ResponseFactory {
public: public:
typedef std::function<std::unique_ptr<Response>(const IniFile&)> ResponseMakerFunc; typedef std::function<std::unique_ptr<Response>(const SettingsBag&)> ResponseMakerFunc;
explicit ResponseFactory (const Kakoune::SafePtr<IniFile>& parSettings); explicit ResponseFactory (const Kakoune::SafePtr<SettingsBag>& parSettings);
~ResponseFactory() noexcept; ~ResponseFactory() noexcept;
std::unique_ptr<Response> make_response(const boost::string_ref& parName); std::unique_ptr<Response> make_response(const boost::string_ref& parName);

44
src/settings_bag.cpp Normal file
View file

@ -0,0 +1,44 @@
/* Copyright 2017, Michele Santullo
* This file is part of "tawashi".
*
* "tawashi" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "tawashi" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "tawashi". If not, see <http://www.gnu.org/licenses/>.
*/
#include "settings_bag.hpp"
#include <cassert>
namespace tawashi {
SettingsBag::SettingsBag (const Kakoune::SafePtr<IniFile>& parIni) :
m_ini(parIni),
m_values(&parIni->parsed().at("tawashi"))
{
assert(m_values);
}
SettingsBag::~SettingsBag() noexcept = default;
const boost::string_ref& SettingsBag::operator[] (boost::string_ref parIndex) const {
auto it_found = m_values->find(parIndex);
if (m_values->end() != it_found)
return it_found->second;
else
return m_defaults.at(parIndex);
}
void SettingsBag::add_default (boost::string_ref parKey, boost::string_ref parValue) {
assert(m_defaults.find(parKey) == m_defaults.end());
m_defaults[parKey] = parValue;
}
} //namespace tawashi

41
src/settings_bag.hpp Normal file
View file

@ -0,0 +1,41 @@
/* Copyright 2017, Michele Santullo
* This file is part of "tawashi".
*
* "tawashi" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "tawashi" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "tawashi". If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "ini_file.hpp"
#include "kakoune/safe_ptr.hh"
#include <map>
#include <boost/utility/string_ref.hpp>
#include <functional>
namespace tawashi {
class SettingsBag : public Kakoune::SafeCountable {
typedef std::map<boost::string_ref, boost::string_ref> MapType;
public:
explicit SettingsBag (const Kakoune::SafePtr<IniFile>& parIni);
~SettingsBag() noexcept;
const boost::string_ref& operator[] (boost::string_ref parIndex) const;
void add_default (boost::string_ref parKey, boost::string_ref parValue);
private:
MapType m_defaults;
Kakoune::SafePtr<IniFile> m_ini;
const IniFile::KeyValueMapType* m_values;
};
} //namespace tawashi

View file

@ -27,8 +27,8 @@ namespace tawashi {
const char g_post_key[] = "pastie"; const char g_post_key[] = "pastie";
} //unnamed namespace } //unnamed namespace
SubmitPasteResponse::SubmitPasteResponse (const IniFile& parIni) : SubmitPasteResponse::SubmitPasteResponse (const SettingsBag& parSettings) :
Response(Response::ContentType, "text/plain", "paste", parIni, true) Response(Response::ContentType, "text/plain", "paste", parSettings, true)
{ {
} }

View file

@ -24,7 +24,7 @@
namespace tawashi { namespace tawashi {
class SubmitPasteResponse : public Response { class SubmitPasteResponse : public Response {
public: public:
explicit SubmitPasteResponse (const IniFile& parIni); explicit SubmitPasteResponse (const SettingsBag& parSettings);
private: private:
virtual void on_process() override; virtual void on_process() override;