diff --git a/CMakeLists.txt b/CMakeLists.txt index 1fb8744..b604920 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.3 FATAL_ERROR) list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) project(tawashi_top) -set(TAWSHI_SOURCE_ROOT "${CMAKE_CURRENT_SOURCE_DIR}") +set(TAWASHI_SOURCE_ROOT "${CMAKE_CURRENT_SOURCE_DIR}") add_subdirectory(lib/incredis) add_subdirectory(src) diff --git a/config/uwsgi/tawashi.ini b/config/uwsgi/tawashi.ini index 7524938..5abf2e7 100644 --- a/config/uwsgi/tawashi.ini +++ b/config/uwsgi/tawashi.ini @@ -3,7 +3,8 @@ processes = 4 master = 1 socket = /run/uwsgi/%n.sock cgi = /srv/http/tawashi/%n.cgi -chmod-socket = 666 +chmod-socket = 664 strict = true gid = http plugins = cgi +chdir = /srv/http/tawashi diff --git a/src/pathname/kakoune/ref_ptr.hh b/lib/kakoune/kakoune/ref_ptr.hh similarity index 70% rename from src/pathname/kakoune/ref_ptr.hh rename to lib/kakoune/kakoune/ref_ptr.hh index 692aa63..5711ced 100644 --- a/src/pathname/kakoune/ref_ptr.hh +++ b/lib/kakoune/kakoune/ref_ptr.hh @@ -3,19 +3,23 @@ #include -#if !defined(NDEBUG) && !defined(KAK_DEBUG) -# define KAK_DEBUG -#endif - namespace Kakoune { -struct WorstMatch { [[gnu::always_inline]] WorstMatch(...) {} }; +struct RefCountable +{ + int refcount = 0; + virtual ~RefCountable() = default; +}; -[[gnu::always_inline]] -inline void ref_ptr_moved(WorstMatch, void*, void*) noexcept {} +struct RefCountablePolicy +{ + static void inc_ref(RefCountable* r, void*) noexcept { ++r->refcount; } + static void dec_ref(RefCountable* r, void*) { if (--r->refcount == 0) delete r; } + static void ptr_moved(RefCountable*, void*, void*) noexcept {} +}; -template +template struct RefPtr { RefPtr() = default; @@ -87,47 +91,25 @@ private: void acquire() { if (m_ptr) - inc_ref_count(static_cast(m_ptr), this); + Policy::inc_ref(m_ptr, this); } [[gnu::always_inline]] void release() { if (m_ptr) - dec_ref_count(static_cast(m_ptr), this); - m_ptr = nullptr; + Policy::dec_ref(m_ptr, this); } [[gnu::always_inline]] void moved(void* from) - noexcept(noexcept(ref_ptr_moved(static_cast(nullptr), nullptr, nullptr))) + noexcept(noexcept(Policy::ptr_moved(nullptr, nullptr, nullptr))) { if (m_ptr) - ref_ptr_moved(static_cast(m_ptr), from, this); - } -}; - -struct RefCountable -{ - int refcount = 0; - virtual ~RefCountable() = default; - - friend void inc_ref_count(RefCountable* r, void*) - { - ++r->refcount; - } - - friend void dec_ref_count(RefCountable* r, void*) - { - if (--r->refcount == 0) - delete r; + Policy::ptr_moved(m_ptr, from, this); } }; } -#if defined(KAK_DEBUG) -# undef KAK_DEBUG -#endif - #endif // ref_ptr_hh_INCLUDED diff --git a/src/pathname/kakoune/safe_ptr.hh b/lib/kakoune/kakoune/safe_ptr.hh similarity index 60% rename from src/pathname/kakoune/safe_ptr.hh rename to lib/kakoune/kakoune/safe_ptr.hh index 3ba71b3..36aa80d 100644 --- a/src/pathname/kakoune/safe_ptr.hh +++ b/lib/kakoune/kakoune/safe_ptr.hh @@ -3,24 +3,22 @@ // #define SAFE_PTR_TRACK_CALLSTACKS +//King_DuckZ: +#include +#define kak_assert(a) assert(a) + +//#include "assert.hh" #include "ref_ptr.hh" #include #include #ifdef SAFE_PTR_TRACK_CALLSTACKS +#include "backtrace.hh" #include "vector.hh" #include #endif -#include - -#define kak_assert assert - -#if !defined(NDEBUG) && !defined(KAK_DEBUG) -# define KAK_DEBUG -#endif - namespace Kakoune { @@ -31,6 +29,7 @@ class SafeCountable public: #ifdef KAK_DEBUG SafeCountable() : m_count(0) {} + SafeCountable (SafeCountable&&) : m_count(0) {} ~SafeCountable() { kak_assert(m_count == 0); @@ -39,37 +38,8 @@ public: #endif } - friend void inc_ref_count(const SafeCountable* sc, void* /*ptr*/) - { - ++sc->m_count; - #ifdef SAFE_PTR_TRACK_CALLSTACKS - sc->m_callstacks.emplace_back(ptr); - #endif - } - - friend void dec_ref_count(const SafeCountable* sc, void* /*ptr*/) - { - --sc->m_count; - kak_assert(sc->m_count >= 0); - #ifdef SAFE_PTR_TRACK_CALLSTACKS - auto it = std::find_if(sc->m_callstacks.begin(), sc->m_callstacks.end(), - [=](const Callstack& cs) { return cs.ptr == ptr; }); - kak_assert(it != sc->m_callstacks.end()); - sc->m_callstacks.erase(it); - #endif - } - - friend void ref_ptr_moved(const SafeCountable* /*sc*/, void* /*from*/, void* /*to*/) - { - #ifdef SAFE_PTR_TRACK_CALLSTACKS - auto it = std::find_if(sc->m_callstacks.begin(), sc->m_callstacks.end(), - [=](const Callstack& cs) { return cs.ptr == from; }); - kak_assert(it != sc->m_callstacks.end()); - it->ptr = to; - #endif - } - private: + friend struct SafeCountablePolicy; #ifdef SAFE_PTR_TRACK_CALLSTACKS struct Callstack { @@ -81,26 +51,59 @@ private: mutable Vector m_callstacks; #endif mutable int m_count; -#else - [[gnu::always_inline]] - friend void inc_ref_count(const SafeCountable* /*sc*/, void* /*ptr*/) {} - - [[gnu::always_inline]] - friend void dec_ref_count(const SafeCountable* /*sc*/, void* /*ptr*/) {} #endif }; -template -using PropagateConst = typename std::conditional::value, const U, U>::type; +struct SafeCountablePolicy +{ +#ifdef KAK_DEBUG + static void inc_ref(const SafeCountable* sc, void* ptr) noexcept + { + ++sc->m_count; + #ifdef SAFE_PTR_TRACK_CALLSTACKS + sc->m_callstacks.emplace_back(ptr); + #else + static_cast(ptr); + #endif + } + + static void dec_ref(const SafeCountable* sc, void* ptr) noexcept + { + --sc->m_count; + kak_assert(sc->m_count >= 0); + #ifdef SAFE_PTR_TRACK_CALLSTACKS + auto it = std::find_if(sc->m_callstacks.begin(), sc->m_callstacks.end(), + [=](const SafeCountable::Callstack& cs) { return cs.ptr == ptr; }); + kak_assert(it != sc->m_callstacks.end()); + sc->m_callstacks.erase(it); + #else + static_cast(ptr); + #endif + } + + static void ptr_moved(const SafeCountable* sc, void* from, void* to) noexcept + { + #ifdef SAFE_PTR_TRACK_CALLSTACKS + auto it = std::find_if(sc->m_callstacks.begin(), sc->m_callstacks.end(), + [=](const SafeCountable::Callstack& cs) { return cs.ptr == from; }); + kak_assert(it != sc->m_callstacks.end()); + it->ptr = to; + #else + static_cast(sc); + static_cast(from); + static_cast(to); + #endif + } +#else + static void inc_ref(const SafeCountable*, void*) noexcept {} + static void dec_ref(const SafeCountable*, void*) noexcept {} + static void ptr_moved(const SafeCountable*, void*, void*) noexcept {} +#endif +}; template -using SafePtr = RefPtr>; +using SafePtr = RefPtr; } -#if defined(KAK_DEBUG) -# undef KAK_DEBUG -#endif -#undef kak_assert - #endif // safe_ptr_hh_INCLUDED diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1dd6395..a975b85 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -25,6 +25,7 @@ add_executable(${PROJECT_NAME} pastie_response.cpp ini_file.cpp pathname/pathname.cpp + response_factory.cpp ) configure_file( @@ -34,10 +35,11 @@ configure_file( target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include + PRIVATE ${TAWASHI_SOURCE_ROOT}/lib/kakoune ) target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE ${Boost_INCLUDE_DIRS} - PRIVATE ${TAWASHI_SOURCE_ROOT}/lib/bette-enums + PRIVATE ${TAWASHI_SOURCE_ROOT}/lib/better-enums PRIVATE ${CURL_INCLUDE_DIR} PRIVATE ${SourceHighlight_INCLUDE_DIR} ) diff --git a/src/index_response.cpp b/src/index_response.cpp index 652d8d5..483f4f5 100644 --- a/src/index_response.cpp +++ b/src/index_response.cpp @@ -19,20 +19,13 @@ #include namespace tawashi { - IndexResponse::IndexResponse (const boost::string_ref& parBaseURI) : - Response(Response::ContentType, "text/html", parBaseURI) + IndexResponse::IndexResponse (const IniFile& parIni) : + Response(Response::ContentType, "text/html", "index", parIni, false) { } void IndexResponse::on_send (std::ostream& parStream) { - std::string html(R"( -
- -
- -
-
-)"); + std::string html(load_mustache()); boost::replace_all(html, "{base_uri}", base_uri()); parStream << html; diff --git a/src/index_response.hpp b/src/index_response.hpp index ea8dede..717e89a 100644 --- a/src/index_response.hpp +++ b/src/index_response.hpp @@ -23,7 +23,7 @@ namespace tawashi { class IndexResponse : public Response { public: - explicit IndexResponse (const boost::string_ref& parBaseURI); + explicit IndexResponse (const IniFile& parIni); private: virtual void on_send (std::ostream& parStream) override; diff --git a/src/ini_file.hpp b/src/ini_file.hpp index dcfb8b8..ec5abcd 100644 --- a/src/ini_file.hpp +++ b/src/ini_file.hpp @@ -17,13 +17,14 @@ #pragma once +#include "kakoune/safe_ptr.hh" #include #include #include #include namespace tawashi { - class IniFile { + class IniFile : public Kakoune::SafeCountable { public: typedef boost::container::flat_map KeyValueMapType; typedef boost::container::flat_map IniMapType; diff --git a/src/main.cpp b/src/main.cpp index 0516188..5266b75 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,13 +15,14 @@ * along with "tawashi". If not, see . */ -#include "incredis/incredis.hpp" #include "tawashiConfig.h" #include "submit_paste_response.hpp" #include "pastie_response.hpp" #include "index_response.hpp" +#include "response_factory.hpp" #include "cgi_env.hpp" #include "ini_file.hpp" +#include "safe_stack_object.hpp" #include "pathname/pathname.hpp" #include "duckhandy/compatibility.h" #include "duckhandy/lexical_cast.hpp" @@ -50,51 +51,36 @@ namespace { return full_path.path(); } - redis::IncRedis make_incredis (const tawashi::IniFile::KeyValueMapType& parSettings) { - using redis::IncRedis; - - if (parSettings.at("redis_mode") == "inet") { - return IncRedis( - std::string(parSettings.at("redis_server")), - dhandy::lexical_cast(parSettings.at("redis_port")) - ); - } - else if (parSettings.at("redis_mode") == "sock") { - return IncRedis(std::string(parSettings.at("redis_sock"))); - } - else { - throw std::runtime_error("Unknown setting for \"redis_mode\", valid settings are \"inet\" or \"sock\""); - } + template + std::unique_ptr make_response (const tawashi::IniFile& parIni) { + return static_cast>(std::make_unique(parIni)); } } //unnamed namespace int main() { + using curry::SafeStackObject; + using tawashi::IndexResponse; + using tawashi::SubmitPasteResponse; + using tawashi::PastieResponse; + using tawashi::Response; + #if !defined(NDEBUG) std::cerr << "Loading config: \"" << config_file_path() << "\"\n"; #endif std::ifstream conf(config_file_path()); conf >> std::noskipws; - tawashi::IniFile ini = tawashi::IniFile(std::istream_iterator(conf), std::istream_iterator()); + auto ini = SafeStackObject(std::istream_iterator(conf), std::istream_iterator()); conf.close(); - const auto& settings = ini.parsed().at("tawashi"); - - auto incredis = make_incredis(settings); - incredis.connect(); tawashi::cgi::Env cgi_env; - const boost::string_ref& base_uri = settings.at("base_uri"); - if (cgi_env.path_info() == "/index.cgi") { - tawashi::IndexResponse resp(base_uri); - resp.send(); - } - else if (cgi_env.path_info() == "/paste.cgi") { - tawashi::SubmitPasteResponse resp(incredis, base_uri); - resp.send(); - } - else { - tawashi::PastieResponse resp(incredis, base_uri); - resp.send(); - } + tawashi::ResponseFactory resp_factory(ini); + resp_factory.register_maker("index.cgi", &make_response); + resp_factory.register_maker("", &make_response); + resp_factory.register_maker("paste.cgi", &make_response); + resp_factory.register_jolly_maker(&make_response); + + std::unique_ptr response = resp_factory.make_response(cgi_env.path_info().substr(1)); + response->send(); return 0; } diff --git a/src/pastie_response.cpp b/src/pastie_response.cpp index 3934ddd..b90df86 100644 --- a/src/pastie_response.cpp +++ b/src/pastie_response.cpp @@ -23,9 +23,8 @@ #include namespace tawashi { - PastieResponse::PastieResponse (redis::IncRedis& parRedis, const boost::string_ref& parBaseURI) : - Response(Response::ContentType, "text/html", parBaseURI), - m_redis(parRedis), + PastieResponse::PastieResponse (const IniFile& parIni) : + Response(Response::ContentType, "text/html", "", parIni, true), m_plain_text(false) { } @@ -54,7 +53,8 @@ namespace tawashi { } auto token = boost::string_ref(cgi_env().path_info()).substr(1); - opt_string pastie = m_redis.get(token); + auto& redis = this->redis(); + opt_string pastie = redis.get(token); if (not pastie) { } diff --git a/src/pastie_response.hpp b/src/pastie_response.hpp index 420b857..64b4f57 100644 --- a/src/pastie_response.hpp +++ b/src/pastie_response.hpp @@ -21,20 +21,15 @@ #include #include -namespace redis { - class IncRedis; -} //namespace redis - namespace tawashi { class PastieResponse : public Response { public: - PastieResponse (redis::IncRedis& parRedis, const boost::string_ref& parBaseURI); + explicit PastieResponse (const IniFile& parIni); private: virtual void on_process() override; virtual void on_send (std::ostream& parStream) override; - redis::IncRedis& m_redis; std::string m_lang_file; bool m_plain_text; }; diff --git a/src/pathname/kakoune/assert.hh b/src/pathname/kakoune/assert.hh deleted file mode 100644 index 87a1da3..0000000 --- a/src/pathname/kakoune/assert.hh +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef assert_hh_INCLUDED -#define assert_hh_INCLUDED - -namespace Kakoune -{ - -class StringView; - -// return true if user asked to ignore the error -bool notify_fatal_error(StringView message); - -void on_assert_failed(const char* message); - -} - -#define STRINGIFY(X) #X -#define TOSTRING(X) STRINGIFY(X) - -#ifdef KAK_DEBUG - #define kak_assert(...) do { \ - if (not (__VA_ARGS__)) \ - on_assert_failed("assert failed \"" #__VA_ARGS__ \ - "\" at " __FILE__ ":" TOSTRING(__LINE__)); \ - } while (false) -#else - #define kak_assert(...) do {} while(false) -#endif - - -#endif // assert_hh_INCLUDED diff --git a/src/response.cpp b/src/response.cpp index 53b8ca2..e78d50c 100644 --- a/src/response.cpp +++ b/src/response.cpp @@ -16,16 +16,57 @@ */ #include "response.hpp" +#include "incredis/incredis.hpp" +#include "ini_file.hpp" #include #include +#include +#include namespace tawashi { - Response::Response (Types parRespType, std::string&& parValue, const boost::string_ref& parBaseURI) : + namespace { + //boost::string_ref fetch_page_basename (const cgi::Env& parEnv) { + // const boost::string_ref& path = parEnv.path_info(); + + // const std::size_t last_slash = path.rfind('/'); + // const std::size_t last_dot = path.rfind('.'); + // const std::size_t start_index = (path.npos == last_slash ? 0 : last_slash + 1); + // const std::size_t substr_len = (path.size() - start_index - (last_dot == path.npos ? 0 : path.size() - last_dot)); + // assert(start_index <= path.size()); + // assert(substr_len < path.size() and substr_len - path.size() - start_index); + // return path.substr(start_index, substr_len); + //} + + redis::IncRedis make_incredis (const tawashi::IniFile::KeyValueMapType& parSettings) { + using redis::IncRedis; + + if (parSettings.at("redis_mode") == "inet") { + return IncRedis( + std::string(parSettings.at("redis_server")), + dhandy::lexical_cast(parSettings.at("redis_port")) + ); + } + else if (parSettings.at("redis_mode") == "sock") { + return IncRedis(std::string(parSettings.at("redis_sock"))); + } + else { + throw std::runtime_error("Unknown setting for \"redis_mode\", valid settings are \"inet\" or \"sock\""); + } + } + } //unnamed namespace + + Response::Response (Types parRespType, std::string&& parValue, std::string&& parPageBaseName, const IniFile& parIni, bool parWantRedis) : m_resp_value(std::move(parValue)), - m_base_uri(parBaseURI), + m_base_uri(parIni.parsed().at("tawashi").at("base_uri")), + //m_page_basename(fetch_page_basename(m_cgi_env)), + m_page_basename(std::move(parPageBaseName)), m_resp_type(parRespType), m_header_sent(false) { + if (parWantRedis) { + m_redis = std::make_unique(make_incredis(parIni.parsed().at("tawashi"))); + m_redis->connect(); + } } Response::~Response() noexcept = default; @@ -34,6 +75,9 @@ namespace tawashi { } void Response::send() { + if (m_redis) + m_redis->wait_for_connect(); + this->on_process(); m_header_sent = true; @@ -65,4 +109,27 @@ namespace tawashi { const boost::string_ref& Response::base_uri() const { return m_base_uri; } + + const std::string& Response::page_basename() const { + return m_page_basename; + } + + std::string Response::load_mustache() const { + std::ostringstream oss; + oss << "html/" << page_basename() << ".html.mstch"; + std::cerr << "Trying to load \"" << oss.str() << "\"\n"; + std::ifstream if_mstch(oss.str(), std::ios::binary | std::ios::in); + + if (!if_mstch) + throw std::runtime_error(std::string("File \"") + oss.str() + "\" not found"); + + std::ostringstream buffer; + buffer << if_mstch.rdbuf(); + return buffer.str(); + } + + redis::IncRedis& Response::redis() const { + assert(m_redis); + return *m_redis; + } } //namespace tawashi diff --git a/src/response.hpp b/src/response.hpp index 3ca25e3..1581279 100644 --- a/src/response.hpp +++ b/src/response.hpp @@ -21,8 +21,15 @@ #include #include #include +#include + +namespace redis { + class IncRedis; +} //namespace redis namespace tawashi { + class IniFile; + class Response { public: virtual ~Response() noexcept; @@ -35,10 +42,13 @@ namespace tawashi { Location }; - Response (Types parRespType, std::string&& parValue, const boost::string_ref& parBaseURI); + Response (Types parRespType, std::string&& parValue, std::string&& parPageBaseName, const IniFile& parIni, bool parWantRedis); const cgi::Env& cgi_env() const; void change_type (Types parRespType, std::string&& parValue); const boost::string_ref& base_uri() const; + const std::string& page_basename() const; + std::string load_mustache() const; + redis::IncRedis& redis() const; private: virtual void on_process(); @@ -47,7 +57,9 @@ namespace tawashi { cgi::Env m_cgi_env; std::string m_resp_value; boost::string_ref m_base_uri; + std::string m_page_basename; Types m_resp_type; + std::unique_ptr m_redis; bool m_header_sent; }; } //namespace tawashi diff --git a/src/response_factory.cpp b/src/response_factory.cpp new file mode 100644 index 0000000..eb8d7b5 --- /dev/null +++ b/src/response_factory.cpp @@ -0,0 +1,63 @@ +/* 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 . + */ + +#include "response_factory.hpp" +#include "ini_file.hpp" +#include +#include + +namespace tawashi { + namespace { + } //unnamed namespace + + struct ResponseFactory::LocalData { + Kakoune::SafePtr settings; + boost::container::flat_map makers; + ResponseMakerFunc jolly_maker; + }; + + ResponseFactory::ResponseFactory (const Kakoune::SafePtr& parSettings) : + m_local_data(std::make_unique()) + { + m_local_data->settings = parSettings; + + } + + ResponseFactory::~ResponseFactory() noexcept = default; + + std::unique_ptr ResponseFactory::make_response (const boost::string_ref& parName) { + auto maker_it = m_local_data->makers.find(std::string(parName.data(), parName.size())); + if (m_local_data->makers.end() != maker_it) { + return maker_it->second(*m_local_data->settings); + } + else if (m_local_data->jolly_maker) { + return m_local_data->jolly_maker(*m_local_data->settings); + } + else { + assert(false); + return std::unique_ptr(); + } + } + + void ResponseFactory::register_maker (std::string&& parName, ResponseMakerFunc parMaker) { + m_local_data->makers[std::move(parName)] = parMaker; + } + + void ResponseFactory::register_jolly_maker (ResponseMakerFunc parMaker) { + m_local_data->jolly_maker = parMaker; + } +} //namespace tawashi diff --git a/src/response_factory.hpp b/src/response_factory.hpp new file mode 100644 index 0000000..7c6db12 --- /dev/null +++ b/src/response_factory.hpp @@ -0,0 +1,43 @@ +/* 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 . + */ + +#pragma once + +#include "response.hpp" +#include "kakoune/safe_ptr.hh" +#include + +namespace tawashi { + class IniFile; + + class ResponseFactory { + public: + typedef std::function(const IniFile&)> ResponseMakerFunc; + + explicit ResponseFactory (const Kakoune::SafePtr& parSettings); + ~ResponseFactory() noexcept; + + std::unique_ptr make_response(const boost::string_ref& parName); + void register_maker (std::string&& parName, ResponseMakerFunc parMaker); + void register_jolly_maker (ResponseMakerFunc parMaker); + + private: + struct LocalData; + + std::unique_ptr m_local_data; + }; +} //namespace tawashi diff --git a/src/safe_stack_object.hpp b/src/safe_stack_object.hpp new file mode 100644 index 0000000..7e6c8cd --- /dev/null +++ b/src/safe_stack_object.hpp @@ -0,0 +1,96 @@ +/* + Copyright 2016, 2017 Michele "King_DuckZ" Santullo + + This file is part of MyCurry. + + MyCurry 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. + + MyCurry 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 MyCurry. If not, see . +*/ + +#pragma once + +#include "kakoune/safe_ptr.hh" +#include + +namespace curry { + template + class SafeStackObject { + public: + typedef Kakoune::SafePtr safe_ptr; + + SafeStackObject(); + SafeStackObject (SafeStackObject&& parOther); + SafeStackObject (const SafeStackObject& parOther) = delete; + template explicit SafeStackObject (Args&&... parArgs); + ~SafeStackObject() noexcept = default; + + SafeStackObject& operator= (SafeStackObject&& parOther) = delete; + SafeStackObject& operator= (const SafeStackObject& parOther) = delete; + + operator Kakoune::SafePtr&(); + safe_ptr& operator*(); + safe_ptr& operator->(); + + private: + T m_obj; + safe_ptr m_obj_ptr; + }; + + template + SafeStackObject::SafeStackObject() : + m_obj(), + m_obj_ptr(&m_obj) + { + } + + template + SafeStackObject::SafeStackObject (SafeStackObject&& parOther) : + m_obj(std::move(parOther.m_obj)), + m_obj_ptr(&m_obj) + { + } + + template + template + SafeStackObject::SafeStackObject (Args&&... parArgs) : + m_obj(std::forward(parArgs)...), + m_obj_ptr(&m_obj) + { + } + + //template + //SafeStackObject& SafeStackObject::operator= (SafeStackObject&& parOther) { + // m_obj = std::move(parOther.m_obj); + // m_obj_ptr = std::move(parOther.m_obj_ptr); + // m_ob + //} + + //template + //SafeStackObject& SafeStackObject::operator= (const SafeStackObject& parOther) { + //} + + template + SafeStackObject::operator Kakoune::SafePtr&() { + return m_obj_ptr; + } + + template + auto SafeStackObject::operator*() -> safe_ptr& { + return m_obj_ptr; + } + + template + auto SafeStackObject::operator->() -> safe_ptr& { + return m_obj_ptr; + } +} //namespace curry diff --git a/src/submit_paste_response.cpp b/src/submit_paste_response.cpp index cc00ec7..a7de0b7 100644 --- a/src/submit_paste_response.cpp +++ b/src/submit_paste_response.cpp @@ -27,9 +27,8 @@ namespace tawashi { const char g_post_key[] = "pastie"; } //unnamed namespace - SubmitPasteResponse::SubmitPasteResponse (redis::IncRedis& parRedis, const boost::string_ref& parBaseURI) : - Response(Response::ContentType, "text/plain", parBaseURI), - m_redis(parRedis) + SubmitPasteResponse::SubmitPasteResponse (const IniFile& parIni) : + Response(Response::ContentType, "text/plain", "paste", parIni, true) { } @@ -56,17 +55,14 @@ namespace tawashi { } boost::optional SubmitPasteResponse::submit_to_redis (const std::string& parText) const { - if (not m_redis.is_connected()) { - m_redis.connect(); - m_redis.wait_for_connect(); - if (not m_redis.is_connected()) - return boost::optional(); - } + auto& redis = this->redis(); + if (not redis.is_connected()) + return boost::optional(); - const auto next_id = m_redis.incr("paste_counter"); + const auto next_id = redis.incr("paste_counter"); const std::string token = num_to_token(next_id); assert(not token.empty()); - if (m_redis.set(token, parText)) { + if (redis.set(token, parText)) { return boost::make_optional(token); } else { diff --git a/src/submit_paste_response.hpp b/src/submit_paste_response.hpp index de491ba..549abfa 100644 --- a/src/submit_paste_response.hpp +++ b/src/submit_paste_response.hpp @@ -21,21 +21,16 @@ #include #include -namespace redis { - class IncRedis; -} //namespace redis - namespace tawashi { class SubmitPasteResponse : public Response { public: - SubmitPasteResponse (redis::IncRedis& parRedis, const boost::string_ref& parBaseURI); + explicit SubmitPasteResponse (const IniFile& parIni); private: virtual void on_process() override; virtual void on_send (std::ostream& parStream) override; boost::optional submit_to_redis (const std::string& parText) const; - redis::IncRedis& m_redis; std::string m_error_message; }; } //namespace tawashi