1
0
Fork 0
mirror of https://github.com/KingDuckZ/kamokan.git synced 2024-12-27 21:35:41 +00:00

Refactoring.

IncRedis is now held by Response, if requested by the base class.
Response objects know their names, and they use it to load
the html (soon to be mustache) data from disk.
Main only prepares a factory, the factory then instantiates
the actual Response.
The code now correctly serves index.cgi when the request is /.
Remove kakoune's safe_ptr from inside src and put an updated
one in lib/kakoune.
This commit is contained in:
King_DuckZ 2017-04-15 03:18:33 +01:00
parent 4bf8dfc29f
commit 680f13e1f6
19 changed files with 400 additions and 195 deletions

View file

@ -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)

View file

@ -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

View file

@ -3,19 +3,23 @@
#include <utility>
#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<typename T, typename TForOverload = T>
template<typename T, typename Policy = RefCountablePolicy>
struct RefPtr
{
RefPtr() = default;
@ -87,47 +91,25 @@ private:
void acquire()
{
if (m_ptr)
inc_ref_count(static_cast<TForOverload*>(m_ptr), this);
Policy::inc_ref(m_ptr, this);
}
[[gnu::always_inline]]
void release()
{
if (m_ptr)
dec_ref_count(static_cast<TForOverload*>(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<TForOverload*>(nullptr), nullptr, nullptr)))
noexcept(noexcept(Policy::ptr_moved(nullptr, nullptr, nullptr)))
{
if (m_ptr)
ref_ptr_moved(static_cast<TForOverload*>(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

View file

@ -3,24 +3,22 @@
// #define SAFE_PTR_TRACK_CALLSTACKS
//King_DuckZ:
#include <cassert>
#define kak_assert(a) assert(a)
//#include "assert.hh"
#include "ref_ptr.hh"
#include <type_traits>
#include <utility>
#ifdef SAFE_PTR_TRACK_CALLSTACKS
#include "backtrace.hh"
#include "vector.hh"
#include <algorithm>
#endif
#include <cassert>
#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<Callstack> 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<typename T, typename U>
using PropagateConst = typename std::conditional<std::is_const<T>::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<void>(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<void>(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<void>(sc);
static_cast<void>(from);
static_cast<void>(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<typename T>
using SafePtr = RefPtr<T, PropagateConst<T, SafeCountable>>;
using SafePtr = RefPtr<T, SafeCountablePolicy>;
}
#if defined(KAK_DEBUG)
# undef KAK_DEBUG
#endif
#undef kak_assert
#endif // safe_ptr_hh_INCLUDED

View file

@ -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}
)

View file

@ -19,20 +19,13 @@
#include <boost/algorithm/string/replace.hpp>
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"(
<form action="http://127.0.0.1:8080/paste.cgi" method="POST" accept-charset="UTF-8">
<textarea name="pastie" cols="80" rows="24"></textarea>
<br>
<button type="submit">tawashi</button>
</br>
</form>
)");
std::string html(load_mustache());
boost::replace_all(html, "{base_uri}", base_uri());
parStream << html;

View file

@ -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;

View file

@ -17,13 +17,14 @@
#pragma once
#include "kakoune/safe_ptr.hh"
#include <boost/container/flat_map.hpp>
#include <iterator>
#include <boost/utility/string_ref.hpp>
#include <string>
namespace tawashi {
class IniFile {
class IniFile : public Kakoune::SafeCountable {
public:
typedef boost::container::flat_map<boost::string_ref, boost::string_ref> KeyValueMapType;
typedef boost::container::flat_map<boost::string_ref, KeyValueMapType> IniMapType;

View file

@ -15,13 +15,14 @@
* along with "tawashi". If not, see <http://www.gnu.org/licenses/>.
*/
#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<uint16_t>(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 <typename T>
std::unique_ptr<tawashi::Response> make_response (const tawashi::IniFile& parIni) {
return static_cast<std::unique_ptr<tawashi::Response>>(std::make_unique<T>(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<char>(conf), std::istream_iterator<char>());
auto ini = SafeStackObject<tawashi::IniFile>(std::istream_iterator<char>(conf), std::istream_iterator<char>());
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<IndexResponse>);
resp_factory.register_maker("", &make_response<IndexResponse>);
resp_factory.register_maker("paste.cgi", &make_response<SubmitPasteResponse>);
resp_factory.register_jolly_maker(&make_response<PastieResponse>);
std::unique_ptr<Response> response = resp_factory.make_response(cgi_env.path_info().substr(1));
response->send();
return 0;
}

View file

@ -23,9 +23,8 @@
#include <sstream>
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) {
}

View file

@ -21,20 +21,15 @@
#include <string>
#include <boost/utility/string_ref.hpp>
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;
};

View file

@ -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

View file

@ -16,16 +16,57 @@
*/
#include "response.hpp"
#include "incredis/incredis.hpp"
#include "ini_file.hpp"
#include <utility>
#include <cassert>
#include <fstream>
#include <sstream>
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<uint16_t>(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<redis::IncRedis>(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

View file

@ -21,8 +21,15 @@
#include <string>
#include <iostream>
#include <boost/utility/string_ref.hpp>
#include <memory>
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<redis::IncRedis> m_redis;
bool m_header_sent;
};
} //namespace tawashi

63
src/response_factory.cpp Normal file
View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "response_factory.hpp"
#include "ini_file.hpp"
#include <functional>
#include <boost/container/flat_map.hpp>
namespace tawashi {
namespace {
} //unnamed namespace
struct ResponseFactory::LocalData {
Kakoune::SafePtr<IniFile> settings;
boost::container::flat_map<std::string, ResponseMakerFunc> makers;
ResponseMakerFunc jolly_maker;
};
ResponseFactory::ResponseFactory (const Kakoune::SafePtr<IniFile>& parSettings) :
m_local_data(std::make_unique<LocalData>())
{
m_local_data->settings = parSettings;
}
ResponseFactory::~ResponseFactory() noexcept = default;
std::unique_ptr<Response> 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<Response>();
}
}
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

43
src/response_factory.hpp Normal file
View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "response.hpp"
#include "kakoune/safe_ptr.hh"
#include <memory>
namespace tawashi {
class IniFile;
class ResponseFactory {
public:
typedef std::function<std::unique_ptr<Response>(const IniFile&)> ResponseMakerFunc;
explicit ResponseFactory (const Kakoune::SafePtr<IniFile>& parSettings);
~ResponseFactory() noexcept;
std::unique_ptr<Response> 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<LocalData> m_local_data;
};
} //namespace tawashi

96
src/safe_stack_object.hpp Normal file
View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "kakoune/safe_ptr.hh"
#include <utility>
namespace curry {
template <typename T>
class SafeStackObject {
public:
typedef Kakoune::SafePtr<T> safe_ptr;
SafeStackObject();
SafeStackObject (SafeStackObject&& parOther);
SafeStackObject (const SafeStackObject& parOther) = delete;
template <typename... Args> explicit SafeStackObject (Args&&... parArgs);
~SafeStackObject() noexcept = default;
SafeStackObject& operator= (SafeStackObject&& parOther) = delete;
SafeStackObject& operator= (const SafeStackObject& parOther) = delete;
operator Kakoune::SafePtr<T>&();
safe_ptr& operator*();
safe_ptr& operator->();
private:
T m_obj;
safe_ptr m_obj_ptr;
};
template <typename T>
SafeStackObject<T>::SafeStackObject() :
m_obj(),
m_obj_ptr(&m_obj)
{
}
template <typename T>
SafeStackObject<T>::SafeStackObject (SafeStackObject&& parOther) :
m_obj(std::move(parOther.m_obj)),
m_obj_ptr(&m_obj)
{
}
template <typename T>
template <typename... Args>
SafeStackObject<T>::SafeStackObject (Args&&... parArgs) :
m_obj(std::forward<Args>(parArgs)...),
m_obj_ptr(&m_obj)
{
}
//template <typename T>
//SafeStackObject& SafeStackObject<T>::operator= (SafeStackObject&& parOther) {
// m_obj = std::move(parOther.m_obj);
// m_obj_ptr = std::move(parOther.m_obj_ptr);
// m_ob
//}
//template <typename T>
//SafeStackObject& SafeStackObject<T>::operator= (const SafeStackObject& parOther) {
//}
template <typename T>
SafeStackObject<T>::operator Kakoune::SafePtr<T>&() {
return m_obj_ptr;
}
template <typename T>
auto SafeStackObject<T>::operator*() -> safe_ptr& {
return m_obj_ptr;
}
template <typename T>
auto SafeStackObject<T>::operator->() -> safe_ptr& {
return m_obj_ptr;
}
} //namespace curry

View file

@ -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<std::string> 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<std::string>();
}
auto& redis = this->redis();
if (not redis.is_connected())
return boost::optional<std::string>();
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 {

View file

@ -21,21 +21,16 @@
#include <string>
#include <boost/optional.hpp>
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<std::string> submit_to_redis (const std::string& parText) const;
redis::IncRedis& m_redis;
std::string m_error_message;
};
} //namespace tawashi