diff --git a/.gitignore b/.gitignore index 7477ecc4..f289fea6 100644 --- a/.gitignore +++ b/.gitignore @@ -111,3 +111,5 @@ fabric.properties # Android studio 3.1+ serialized cache file .idea/caches/build_file_checksums.ser + +webserv \ No newline at end of file diff --git a/Makefile b/Makefile index ec6c3e12..b1988b6f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,28 @@ -all: +NAME := webserv +SRC_DIR := src +SRCS := $(shell find $(SRC_DIR) -name '*.cpp') +BUILD_DIR := dist +OBJS := $(addprefix $(BUILD_DIR)/,$(SRCS:.cpp=.o)) +CXXFLAGS := -std=c++98 -I$(SRC_DIR)/lib -Wall -Wextra -Werror + +all: $(NAME) + +$(NAME): $(OBJS) + $(CXX) $(CXXFLAGS) -o $(NAME) $(OBJS) + +$(BUILD_DIR)/%.o: %.cpp + @mkdir -p $(dir $@) + $(CXX) $(CXXFLAGS) -c $< -o $@ + +clean: + rm -rf $(BUILD_DIR) + +fclean: clean + rm -rf $(NAME) + +re: fclean all format: - clang-format -i $$(git ls-files '*.cpp' '*.hpp') \ No newline at end of file + clang-format -i $$(git ls-files '*.cpp' '*.hpp') + +.PHONY: all clean fclean re format \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ea8788b7..4913b605 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -set(CMAKE_CXX_STANDARD 11) # TODO: C++98 にする +set(CMAKE_CXX_STANDARD 98) # TODO: C++98 にする # 実行ファイルを /bin に出力 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) diff --git a/src/cmd/main.cpp b/src/cmd/main.cpp index 3e2c5fbb..0a5d8bb9 100644 --- a/src/cmd/main.cpp +++ b/src/cmd/main.cpp @@ -10,6 +10,8 @@ int main(const int argc, char *argv[]) { return 1; } + SET_LOG_LEVEL(Logger::kInfo); + const Option config = Config::loadConfigFromFile(argv[1]); if (config.isNone()) { return 1; diff --git a/src/lib/cgi/factory.cpp b/src/lib/cgi/factory.cpp index 885dec5a..ab3a90f5 100644 --- a/src/lib/cgi/factory.cpp +++ b/src/lib/cgi/factory.cpp @@ -68,7 +68,7 @@ namespace cgi { http::Headers headers(res.getHeaders()); // 200 がデフォルト、Status ヘッダーがあればそれを使う - const http::Headers::const_iterator statusHeader = headers.find("Status"); + const http::Headers::iterator statusHeader = headers.find("Status"); http::HttpStatusCode status = http::kStatusOk; if (statusHeader != headers.end()) { status = TRY(HttpResponseFactory::statusFromHeader(statusHeader->second)).unwrapOr(http::kStatusOk); diff --git a/src/lib/config/config.cpp b/src/lib/config/config.cpp index dc8a1aa4..9f665619 100644 --- a/src/lib/config/config.cpp +++ b/src/lib/config/config.cpp @@ -1,12 +1,10 @@ #include "config.hpp" - #include "http/handler/middleware/logger.hpp" #include "toml/parser.hpp" #include "toml/value.hpp" #include "utils/logger.hpp" - +#include #include -#include namespace config { /* Config */ @@ -27,7 +25,7 @@ namespace config { Option Config::loadConfigFromFile(const std::string &path) { try { - std::ifstream configFile(path); + std::ifstream configFile(path.c_str()); if (!configFile.is_open()) { LOG_ERRORF("cannot open config file: %s", path.c_str()); return None; @@ -117,7 +115,7 @@ namespace config { toml::Table errorPageTable = serverTable.getValue("error_page").unwrap().getTable().unwrap(); std::vector keys = errorPageTable.getKeys(); for (size_t j = 0; j < keys.size(); ++j) { - int statusCode = std::stoi(keys[j]); + int statusCode = static_cast(std::strtol(keys[j].c_str(), NULL, 10)); Option httpStatusCode = http::httpStatusCodeFromInt(statusCode); if (httpStatusCode.isNone()) { LOG_WARNF("invalid HTTP status code: %d", statusCode); @@ -242,7 +240,7 @@ namespace config { for (size_t k = 0; k < methodValues.size(); ++k) { std::string methodStr = methodValues[k].getString().unwrap(); http::HttpMethod method = http::httpMethodFromString(methodStr); - if (method == http::HttpMethod::kMethodUnknown) { + if (method == http::kMethodUnknown) { LOG_ERRORF("unknown http method: %s", methodStr.c_str()); throw std::runtime_error("unknown method: " + methodStr); } diff --git a/src/lib/config/toml/parser.cpp b/src/lib/config/toml/parser.cpp index 60a3fc77..7ca891f6 100644 --- a/src/lib/config/toml/parser.cpp +++ b/src/lib/config/toml/parser.cpp @@ -1,6 +1,11 @@ #include "parser.hpp" + +#include "utils/fd.hpp" +#include "utils/string.hpp" #include "utils/types/try.hpp" +#include + namespace toml { TomlParser::TomlParser(const Tokenizer::Tokens &tokens) : tokens_(tokens), pos_(0), nextPos_(0), token_(kUnknown, "") { @@ -34,7 +39,7 @@ namespace toml { return Ok(t); } - return Err(error::AppError::kParseUnknown); + return Err(error::kParseUnknown); } void TomlParser::consumeNewlines() { @@ -80,7 +85,7 @@ namespace toml { TRY(expect(kRBracket)); if (keys.empty()) { - return Err(error::AppError::kParseUnknown); + return Err(error::kParseUnknown); } Table *currentTable = TRY(table.findOrCreateTablePath(keys)); @@ -93,12 +98,12 @@ namespace toml { if (value.getType() == Value::kArray) { Array &array = value.getArrayRef(); if (array.size() == 0) { - return Err(error::AppError::kParseUnknown); + return Err(error::kParseUnknown); } array.addElement(Value(newTable)); currentTable = &array.getElementRef(array.size() - 1).getTableRef(); } else { - return Err(error::AppError::kParseUnknown); + return Err(error::kParseUnknown); } } else { Array array; @@ -116,7 +121,7 @@ namespace toml { TRY(expect(kRBracket)); if (keys.empty()) { - return Err(error::AppError::kParseUnknown); + return Err(error::kParseUnknown); } Table *currentTable = TRY(table.findOrCreateTablePath(keys)); @@ -124,7 +129,7 @@ namespace toml { const Table newTable; if (currentTable->getValue(lastKey).isSome()) { - return Err(error::AppError::kParseUnknown); + return Err(error::kParseUnknown); } currentTable->setValue(lastKey, Value(newTable)); @@ -140,7 +145,7 @@ namespace toml { Value val = TRY(parseVal()); if (keys.empty()) { - return Err(error::AppError::kParseUnknown); + return Err(error::kParseUnknown); } if (keys.size() == 1) { @@ -200,7 +205,7 @@ namespace toml { value = Value(token_.getValue()); nextToken(); } else if (peek(kNum)) { - value = Value(std::stol(token_.getValue())); + value = Value(std::strtol(token_.getValue().c_str(), NULL, 10)); nextToken(); } else if (peek(kLBracket)) { nextToken(); @@ -246,7 +251,7 @@ namespace toml { table = table.readOnly(); value = Value(table); } else { - return Err(error::AppError::kParseUnknown); + return Err(error::kParseUnknown); } return Ok(value); diff --git a/src/lib/config/toml/value.cpp b/src/lib/config/toml/value.cpp index 3a8e2d4d..b302337f 100644 --- a/src/lib/config/toml/value.cpp +++ b/src/lib/config/toml/value.cpp @@ -246,7 +246,7 @@ namespace toml { Result Table::findOrCreateTablePath(const std::vector &keys) { if (keys.empty()) { - return Err(error::AppError::kParseUnknown); + return Err(error::kParseUnknown); } const size_t endIndex = keys.size() - 1; @@ -271,11 +271,11 @@ namespace toml { if (lastElement.getType() == Value::kTable) { currentTable = &lastElement.getTableRef(); } else { - return Err(error::AppError::kParseUnknown); + return Err(error::kParseUnknown); } } } else { - return Err(error::AppError::kParseUnknown); + return Err(error::kParseUnknown); } } else { Table newTable; diff --git a/src/lib/core/action/run_cgi_action.cpp b/src/lib/core/action/run_cgi_action.cpp index 8c8dbc2a..d561ac0a 100644 --- a/src/lib/core/action/run_cgi_action.cpp +++ b/src/lib/core/action/run_cgi_action.cpp @@ -10,6 +10,7 @@ #include "utils/fd.hpp" #include "utils/time.hpp" #include "utils/logger.hpp" +#include void RunCgiAction::execute(ActionContext &ctx) { int pair[2]; @@ -135,6 +136,7 @@ void RunCgiAction::parentRoutine(const ActionContext &ctx, const int socketFd, c ctx.getState().getEventNotifier().unregisterEvent(Event(clientFd_, Event::kWrite)); ctx.getState().getEventHandlerRepository().remove(clientFd_, Event::kRead); ctx.getState().getEventHandlerRepository().remove(clientFd_, Event::kWrite); - CgiProcessRepository::Data data = {clientFd_, socketFd, utils::Time::getCurrentTime()}; + + const CgiProcessRepository::Data data = {clientFd_, socketFd, utils::Time::getCurrentTime()}; ctx.getState().getCgiProcessRepository().set(childPid, data); } diff --git a/src/lib/core/action/serve_http_action.cpp b/src/lib/core/action/serve_http_action.cpp index 9a5b328a..f29960c6 100644 --- a/src/lib/core/action/serve_http_action.cpp +++ b/src/lib/core/action/serve_http_action.cpp @@ -9,7 +9,7 @@ void ServeHttpAction::execute(ActionContext &actionCtx) { const Option > vs = eventCtx_.getResolver().unwrap().resolve(hostHeader); // accept したので Connection, VirtualServer は存在するはず - const http::RequestContext reqContext(req_, eventCtx_.getConnection().unwrap()); + const http::RequestContext reqContext(req_, eventCtx_.getConnection().unwrap().toConst()); const Either resOrAction = vs.unwrap().get().getRouter().serve(reqContext); if (resOrAction.isLeft()) { LOG_DEBUG("ServeHttpAction: action is returned"); diff --git a/src/lib/core/child_reaper.cpp b/src/lib/core/child_reaper.cpp index 57fe71cc..322e3455 100644 --- a/src/lib/core/child_reaper.cpp +++ b/src/lib/core/child_reaper.cpp @@ -1,5 +1,6 @@ #include "child_reaper.hpp" #include +#include void ChildReaper::attachToEventNotifier(IEventNotifier *notifier) const { selfPipe_.registerWithEventNotifier(notifier); @@ -12,7 +13,8 @@ std::vector ChildReaper::onSignalEvent() const { while (true) { int status = 0; const pid_t pid = waitpid(-1, &status, WNOHANG); - result.push_back({pid, WEXITSTATUS(status)}); + const ReapedProcess rp = {pid, WEXITSTATUS(status)}; + result.push_back(rp); if (pid > 0) { continue; diff --git a/src/lib/core/handler/read_cgi_response_handler.cpp b/src/lib/core/handler/read_cgi_response_handler.cpp index c3189bf7..fe0c9b32 100644 --- a/src/lib/core/handler/read_cgi_response_handler.cpp +++ b/src/lib/core/handler/read_cgi_response_handler.cpp @@ -20,7 +20,7 @@ IEventHandler::InvokeResult ReadCgiResponseHandler::invoke(const Context &ctx) { const ssize_t bytesRead = read(conn.getFd(), buffer, sizeof(buffer)); if (bytesRead == -1) { LOG_WARN("failed to read CGI response"); - return Err(error::AppError::kUnknown); + return Err(error::kUnknown); } if (bytesRead != 0) { @@ -36,7 +36,8 @@ IEventHandler::InvokeResult ReadCgiResponseHandler::invoke(const Context &ctx) { } IEventHandler::ErrorHandleResult ReadCgiResponseHandler::onErrorEvent(const Context &, const Event &event) { - LOG_WARNF("ReadCgiResponseHandler received an error event %d", event.getTypeFlags()); + // 結構うるさいので debug にする + LOG_DEBUGF("ReadCgiResponseHandler received an error event %d", event.getTypeFlags()); if (event.getTypeFlags() & Event::kHangUp) { return ErrorHandleResult(false, std::vector()); @@ -115,8 +116,8 @@ Result ReadCgiResponseHandler::createCgiResponse std::istringstream headerStream(headerPart); std::string line; while (std::getline(headerStream, line)) { - if (!line.empty() && line.back() == '\r') { - line.pop_back(); + if (!line.empty() && line[line.length() - 1] == '\r') { + line = line.substr(0, line.length() - 1); } const http::RequestParser::ParseHeaderFieldLineResult result = http::RequestParser::parseHeaderFieldLine(line); if (result.isOk()) { diff --git a/src/lib/core/handler/read_request_handler.cpp b/src/lib/core/handler/read_request_handler.cpp index c635870d..288c44c6 100644 --- a/src/lib/core/handler/read_request_handler.cpp +++ b/src/lib/core/handler/read_request_handler.cpp @@ -15,7 +15,7 @@ ReadRequestHandler::ReadRequestHandler(const VirtualServerResolver &vsResolver) IEventHandler::InvokeResult ReadRequestHandler::invoke(const Context &ctx) { LOG_DEBUG("start ReadRequestHandler"); - const auto conn = ctx.getConnection().unwrap(); + const Ref conn = ctx.getConnection().unwrap(); // アクティビティを更新 ctx.getConnection().unwrap().get().updateActivity(); diff --git a/src/lib/core/handler/write_cgi_request_handler.cpp b/src/lib/core/handler/write_cgi_request_handler.cpp index 9c55b8a0..627b136a 100644 --- a/src/lib/core/handler/write_cgi_request_handler.cpp +++ b/src/lib/core/handler/write_cgi_request_handler.cpp @@ -1,3 +1,4 @@ +#include #include #include #include "write_cgi_request_handler.hpp" diff --git a/src/lib/core/server.cpp b/src/lib/core/server.cpp index 594d0eaa..314be65e 100644 --- a/src/lib/core/server.cpp +++ b/src/lib/core/server.cpp @@ -10,6 +10,7 @@ #include #include #include +#include Server::Server(const config::Config &config) : config_(config) { const config::ServerContextList &servers = config_.getServers(); @@ -125,7 +126,9 @@ void Server::start() { void Server::invokeHandlers(const Context &ctx) { const Event &event = ctx.getEvent(); - const std::vector types = {Event::kRead, Event::kWrite}; + std::vector types; + types.push_back(Event::kRead); + types.push_back(Event::kWrite); // TODO: handler の呼び方が壊れてる for (std::vector::const_iterator it = types.begin(); it != types.end(); ++it) { const Event::EventType type = *it; diff --git a/src/lib/core/virtual_server_resolver.cpp b/src/lib/core/virtual_server_resolver.cpp index 50007569..9fae2a42 100644 --- a/src/lib/core/virtual_server_resolver.cpp +++ b/src/lib/core/virtual_server_resolver.cpp @@ -51,5 +51,5 @@ VirtualServerResolverFactory::VirtualServerResolverFactory(const VirtualServerLi : virtualServers_(virtualServers) {} VirtualServerResolver VirtualServerResolverFactory::create(const Ref &conn) { - return VirtualServerResolver(virtualServers_, conn); + return VirtualServerResolver(virtualServers_, conn.toConst()); } diff --git a/src/lib/event/event_notifier.cpp b/src/lib/event/event_notifier.cpp index 5049f301..ca37ca0d 100644 --- a/src/lib/event/event_notifier.cpp +++ b/src/lib/event/event_notifier.cpp @@ -171,7 +171,8 @@ IEventNotifier::WaitEventsResult PollEventNotifier::waitEvents(int timeoutMs) { const int result = poll(fds.data(), fds.size(), timeoutMs); if (result == -1) { - LOG_ERRORF("poll failed: %s", std::strerror(errno)); + // EINTR が起こりがちなので、debug にしておく + LOG_DEBUGF("poll failed: %s", std::strerror(errno)); return Err(error::kUnknown); } diff --git a/src/lib/http/handler/cgi_handler.cpp b/src/lib/http/handler/cgi_handler.cpp index 9d19e37a..4df9608a 100644 --- a/src/lib/http/handler/cgi_handler.cpp +++ b/src/lib/http/handler/cgi_handler.cpp @@ -10,7 +10,7 @@ // めんどくさくてメソッドにしてない static bool fileExistsUnderRoot(const std::string &docRoot, const std::string &urlPath) { std::string fsPath = docRoot; - if (!fsPath.empty() && fsPath.back() != '/') fsPath += '/'; + if (!fsPath.empty() && fsPath[fsPath.length() - 1] != '/') fsPath += '/'; if (!urlPath.empty() && urlPath[0] == '/') fsPath += urlPath.substr(1); else diff --git a/src/lib/http/handler/delete_file_handler.cpp b/src/lib/http/handler/delete_file_handler.cpp index 31786785..f102e6a4 100644 --- a/src/lib/http/handler/delete_file_handler.cpp +++ b/src/lib/http/handler/delete_file_handler.cpp @@ -2,6 +2,8 @@ #include "http/response/response_builder.hpp" #include "utils/logger.hpp" #include +#include +#include namespace http { DeleteFileHandler::DeleteFileHandler(const config::LocationContext::DocumentRootConfig &docRootConfig) diff --git a/src/lib/http/handler/middleware/error_page.cpp b/src/lib/http/handler/middleware/error_page.cpp index d550f6eb..26cb782b 100644 --- a/src/lib/http/handler/middleware/error_page.cpp +++ b/src/lib/http/handler/middleware/error_page.cpp @@ -23,7 +23,7 @@ Either http::ErrorPage::intercept(const RequestContex config::ServerContext::ErrorPageMap::iterator customErrorPage = errorPage_.find(status); if (customErrorPage != errorPage_.end()) { - std::ifstream file(customErrorPage->second); + std::ifstream file(customErrorPage->second.c_str()); std::stringstream buf; buf << file.rdbuf(); body = buf.str(); diff --git a/src/lib/http/handler/upload_file_handler.cpp b/src/lib/http/handler/upload_file_handler.cpp index 3c3a586f..a283d3b3 100644 --- a/src/lib/http/handler/upload_file_handler.cpp +++ b/src/lib/http/handler/upload_file_handler.cpp @@ -230,7 +230,8 @@ http::UploadFileHandler::processMultipartPart(const std::string &headers, std::s // ヘッダーをCRLFで分割 const std::vector headerLines = splitHeadersByNewline(headers); - for (const std::string &headerLine : headerLines) { + for (size_t i = 0; i < headerLines.size(); i++) { + const std::string &headerLine = headerLines[i]; // 空行や不正な形式の行はスキップ if (headerLine.empty()) { continue; @@ -286,7 +287,8 @@ void http::UploadFileHandler::processContentDispositionHeader( // 各パラメータをセミコロンで分割 const std::vector params = utils::split(headerValue, ';'); - for (const std::string ¶m : params) { + for (size_t i = 0; i < params.size(); i++) { + const std::string ¶m = params[i]; std::string trimmedParam = utils::trim(param); // name属性の処理 @@ -317,7 +319,7 @@ http::Response http::UploadFileHandler::saveUploadedFile(const std::string &filename, const std::string &content) const { const std::string filePath = docConfig_.getRoot() + "/" + filename; - std::ofstream outFile(filePath, std::ios::binary); + std::ofstream outFile(filePath.c_str(), std::ios::binary); if (!outFile) { return ResponseBuilder().status(kStatusConflict).text("Failed to open file for writing: " + filename).build(); } diff --git a/src/lib/http/request/reader/reading_body_state.cpp b/src/lib/http/request/reader/reading_body_state.cpp index f828c627..79f619fe 100644 --- a/src/lib/http/request/reader/reading_body_state.cpp +++ b/src/lib/http/request/reader/reading_body_state.cpp @@ -11,7 +11,7 @@ Result http::Reading const std::size_t want = contentLength_ - body_.size(); const std::string chunk = readBuf.consume(want); if (chunk.empty()) { - return Ok(HandleStatus::kSuspend); + return Ok(kSuspend); } body_ += chunk; } @@ -19,5 +19,5 @@ Result http::Reading ctx_.setBody(body_); ctx_.changeState(NULL); - return Ok(HandleStatus::kDone); + return Ok(kHandleDone); } diff --git a/src/lib/http/request/reader/reading_chunked_body_state.cpp b/src/lib/http/request/reader/reading_chunked_body_state.cpp index abebfc3f..c48d7e82 100644 --- a/src/lib/http/request/reader/reading_chunked_body_state.cpp +++ b/src/lib/http/request/reader/reading_chunked_body_state.cpp @@ -30,7 +30,7 @@ namespace http { while (state_ != kDone) { const Option maybeLine = TRY(getLine(readBuf)); if (maybeLine.isNone()) { - return Ok(HandleStatus::kSuspend); + return Ok(kSuspend); } const std::string &line = maybeLine.unwrap(); @@ -78,7 +78,7 @@ namespace http { ctx_.setBody(body_); ctx_.changeState(NULL); - return Ok(HandleStatus::kDone); + return Ok(kHandleDone); } Result ReadingChunkedBodyState::parseChunkSizeLine(const std::string &line) { diff --git a/src/lib/http/request/reader/reading_headers_state.cpp b/src/lib/http/request/reader/reading_headers_state.cpp index 53c3c591..546c7aba 100644 --- a/src/lib/http/request/reader/reading_headers_state.cpp +++ b/src/lib/http/request/reader/reading_headers_state.cpp @@ -14,7 +14,7 @@ Result http::Reading const Option line = TRY(getLine(readBuf)); if (line.isNone()) { // バッファが足りない - return Ok(HandleStatus::kSuspend); + return Ok(kSuspend); } /** @@ -31,7 +31,7 @@ Result http::Reading ctx_.setHeaders(headers_); ctx_.changeState(TRY(this->nextState())); - return Ok(HandleStatus::kDone); + return Ok(kHandleDone); } Result http::ReadingHeadersState::nextState() const { diff --git a/src/lib/http/request/reader/reading_request_line_state.cpp b/src/lib/http/request/reader/reading_request_line_state.cpp index ccd801d4..4b8e8cce 100644 --- a/src/lib/http/request/reader/reading_request_line_state.cpp +++ b/src/lib/http/request/reader/reading_request_line_state.cpp @@ -9,11 +9,11 @@ Result http::ReadingRequestLineState::handle(ReadBuffer &readBuf) { const Option reqLine = TRY(getLine(readBuf)); if (reqLine.isNone()) { - return Ok(HandleStatus::kSuspend); + return Ok(kSuspend); } ctx_.setRequestLine(reqLine.unwrap()); ctx_.changeState(new ReadingHeadersState(ctx_)); - return Ok(HandleStatus::kDone); + return Ok(kHandleDone); } diff --git a/src/lib/http/request/reader/request_reader.cpp b/src/lib/http/request/reader/request_reader.cpp index 527fc517..0994d808 100644 --- a/src/lib/http/request/reader/request_reader.cpp +++ b/src/lib/http/request/reader/request_reader.cpp @@ -46,7 +46,7 @@ Result http::RequestReader::ReadContext::handle(ReadBuffer &readBuf) const { if (state_ == NULL) { // 終了状態で呼び出したら、何もしない - return Ok(IState::kDone); + return Ok(IState::kHandleDone); } return state_->handle(readBuf); } diff --git a/src/lib/http/request/reader/request_reader.hpp b/src/lib/http/request/reader/request_reader.hpp index 9e9f4eda..4dedc8e4 100644 --- a/src/lib/http/request/reader/request_reader.hpp +++ b/src/lib/http/request/reader/request_reader.hpp @@ -26,7 +26,7 @@ namespace http { public: class IState { public: - enum HandleStatus { kSuspend, kDone }; + enum HandleStatus { kSuspend, kHandleDone }; virtual ~IState(); virtual Result handle(ReadBuffer &readBuf) = 0; }; diff --git a/src/lib/http/response/response_builder.cpp b/src/lib/http/response/response_builder.cpp index 2573ebe7..c7edfba5 100644 --- a/src/lib/http/response/response_builder.cpp +++ b/src/lib/http/response/response_builder.cpp @@ -45,7 +45,7 @@ namespace http { } ResponseBuilder &ResponseBuilder::file(const std::string &path, HttpStatusCode status) { - std::ifstream ifs(path); + std::ifstream ifs(path.c_str()); if (!ifs.is_open()) { return this->status(kStatusNotFound); } diff --git a/src/lib/transport/address.hpp b/src/lib/transport/address.hpp index 47d94e5f..18bfa464 100644 --- a/src/lib/transport/address.hpp +++ b/src/lib/transport/address.hpp @@ -14,7 +14,7 @@ class Address { private: std::string ip_; - unsigned short port_{}; + unsigned short port_; }; #endif diff --git a/src/lib/utils/auto_deleter.hpp b/src/lib/utils/auto_deleter.hpp index 08b4eacf..f4499979 100644 --- a/src/lib/utils/auto_deleter.hpp +++ b/src/lib/utils/auto_deleter.hpp @@ -9,7 +9,7 @@ template class AutoDeleter : public NonCopyable { public: - using Deleter = void (*)(T *); + typedef void (*Deleter)(T *); explicit AutoDeleter(T *ptr = NULL, const Deleter deleter = NULL) : ptr_(ptr), deleter_(deleter) {} diff --git a/src/lib/utils/ref.hpp b/src/lib/utils/ref.hpp index a8d6422d..f39b18bc 100644 --- a/src/lib/utils/ref.hpp +++ b/src/lib/utils/ref.hpp @@ -1,7 +1,6 @@ #ifndef SRC_LIB_UTILS_REF_HPP #define SRC_LIB_UTILS_REF_HPP -#include // C++11 の std::reference_wrapper を再現 template @@ -15,12 +14,6 @@ class Ref { Ref(const Ref &ref) : ptr_(ref.ptr_) {} - // Ref -> Ref を可能にする - // TODO: C++11 の機能を使っているので、提出時に修正 - template - // ReSharper disable once CppNonExplicitConvertingConstructor - Ref(const Ref::type> &ref) : ptr_(&ref.get()) {} // NOLINT(*-explicit-constructor) - ~Ref() { // あくまで reference なので、delete しない } @@ -46,6 +39,10 @@ class Ref { return *ptr_; } + Ref toConst() const { + return Ref(*ptr_); + } + private: T *ptr_; }; diff --git a/src/lib/utils/types/either.hpp b/src/lib/utils/types/either.hpp index 6fe10d39..d829f9bd 100644 --- a/src/lib/utils/types/either.hpp +++ b/src/lib/utils/types/either.hpp @@ -2,7 +2,7 @@ #define EITHER_HPP #include -#include + namespace types { template @@ -12,8 +12,7 @@ namespace types { // コピーコンストラクタではない // Either(Left) のコンストラクタで Left -> Left に変換するために必要 - // TODO: 提出時に消す - template ::value>::type> + template explicit Left(Left &other) : val_(other.val()) {} Left(const Left &other) : val_(other.val_) {} @@ -50,8 +49,7 @@ namespace types { // コピーコンストラクタではない // Either(Right) のコンストラクタで Right -> Right に変換するために必要 - // TODO: 提出時に消す - template ::value>::type> + template explicit Right(Right &other) : val_(other.val()) {} Right(const Right &other) : val_(other.val_) {} @@ -114,14 +112,12 @@ class Either { * Either r2 = Left("hello"); */ // U -> T に変換可能であるという制約を付けないと、IDE 上でエラーが出ない (コンパイル時に出る) - // TODO: std::is_convertible などは C++11 以降なので、提出時に消す - template ::value>::type> + template // NOLINTNEXTLINE(google-explicit-constructor) Either(types::Left left) : left_(new types::Left(left)), right_(NULL) {} // either.map(Some) の型 Either, E> から Either, E> に変換するために必要 - // TODO: 提出時に消す - template ::value>::type> + template // NOLINTNEXTLINE(google-explicit-constructor) Either(const Either &other) { if (other.isLeft()) { diff --git a/src/lib/utils/types/option.hpp b/src/lib/utils/types/option.hpp index 4991f3c1..1ffa14c1 100644 --- a/src/lib/utils/types/option.hpp +++ b/src/lib/utils/types/option.hpp @@ -95,9 +95,7 @@ class Option { explicit Option(types::Some *some) : some_(some) {} // Option op = Some("hello"); のように注釈を不要にするために必要 - // TODO: 提出時に消す - // ReSharper disable once CppUseTypeTraitAlias - template ::value>::type> + template // NOLINTNEXTLINE(google-explicit-constructor) Option(types::Some some) : some_(new types::Some(some.val())) {} diff --git a/src/lib/utils/types/result.hpp b/src/lib/utils/types/result.hpp index 6e38e2dc..1d817bae 100644 --- a/src/lib/utils/types/result.hpp +++ b/src/lib/utils/types/result.hpp @@ -30,8 +30,7 @@ namespace types { // コピーコンストラクタではない // Result(Ok) のコンストラクタで Ok -> Ok に変換するために必要 - // TODO: 提出時に消す - template ::value>::type> + template explicit Ok(Ok &other) : val_(other.val()) {} Ok(const Ok &other) : val_(other.val_) {} @@ -154,14 +153,12 @@ class Result { * Result r2 = Ok("hello"); */ // U -> T に変換可能であるという制約を付けないと、IDE 上でエラーが出ない (コンパイル時に出る) - // TODO: std::is_convertible などは C++11 以降なので、提出時に消す - template ::value>::type> + template // NOLINTNEXTLINE(google-explicit-constructor) Result(types::Ok ok) : ok_(new types::Ok(ok)), err_(NULL) {} // result.map(Some) の型 Result, E> から Result, E> に変換するために必要 - // TODO: 提出時に消す - template ::value>::type> + template // NOLINTNEXTLINE(google-explicit-constructor) Result(const Result &other) { if (other.isOk()) { diff --git a/src/lib/utils/types/try.hpp b/src/lib/utils/types/try.hpp index a3d969f2..9d86832b 100644 --- a/src/lib/utils/types/try.hpp +++ b/src/lib/utils/types/try.hpp @@ -14,19 +14,18 @@ types::None tryDefault(const Option &) { return None; } -// typeof(expr) は式を評価しないので、全体として一回だけ expr が評価される -#define TRY(expr) \ - ({ \ - typeof(expr) e = (expr); /* NOLINT(*-unnecessary-copy-initialization) */ \ - if (!(e).canUnwrap()) return tryDefault(e); \ - (e).unwrap(); \ +#define TRY(expr) \ + ({ \ + __typeof(expr) e = (expr); /* NOLINT(*-unnecessary-copy-initialization) */ \ + if (!(e).canUnwrap()) return tryDefault(e); \ + (e).unwrap(); \ }) -#define TRY_OR(expr, defaultValue) \ - ({ \ - typeof(expr) e = (expr); /* NOLINT(*-unnecessary-copy-initialization) */ \ - if (!(e).canUnwrap()) return defaultValue; \ - (e).unwrap(); \ +#define TRY_OR(expr, defaultValue) \ + ({ \ + __typeof(expr) e = (expr); /* NOLINT(*-unnecessary-copy-initialization) */ \ + if (!(e).canUnwrap()) return defaultValue; \ + (e).unwrap(); \ }) #endif