From 911da7b5784b395357180c60f346938e49a111da Mon Sep 17 00:00:00 2001 From: smatsuodev Date: Mon, 18 Aug 2025 19:52:27 +0900 Subject: [PATCH 01/19] =?UTF-8?q?Makefile=E3=82=92=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 ++ Makefile | 23 +++++++++++++++++++++-- src/lib/utils/types/try.hpp | 17 +++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) 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..6625f5f6 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,23 @@ -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) $(NAME) 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 format \ No newline at end of file diff --git a/src/lib/utils/types/try.hpp b/src/lib/utils/types/try.hpp index a3d969f2..082f1e42 100644 --- a/src/lib/utils/types/try.hpp +++ b/src/lib/utils/types/try.hpp @@ -14,7 +14,22 @@ types::None tryDefault(const Option &) { return None; } +#ifdef __clang__ // typeof(expr) は式を評価しないので、全体として一回だけ expr が評価される +#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(); \ + }) +#else #define TRY(expr) \ ({ \ typeof(expr) e = (expr); /* NOLINT(*-unnecessary-copy-initialization) */ \ @@ -28,5 +43,7 @@ types::None tryDefault(const Option &) { if (!(e).canUnwrap()) return defaultValue; \ (e).unwrap(); \ }) +#endif + #endif From 17f2b1a04a09db7c938a2a247501abcfc2b31adb Mon Sep 17 00:00:00 2001 From: smatsuodev Date: Mon, 18 Aug 2025 20:38:33 +0900 Subject: [PATCH 02/19] =?UTF-8?q?C++11=E3=82=92=E3=82=84=E3=82=81=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 2 +- Makefile | 2 +- src/CMakeLists.txt | 2 +- src/lib/config/config.cpp | 2 +- src/lib/config/toml/parser.cpp | 16 ++--- src/lib/config/toml/value.cpp | 6 +- src/lib/core/action/run_cgi_action.cpp | 4 +- src/lib/core/action/serve_http_action.cpp | 2 +- src/lib/core/child_reaper.cpp | 3 +- .../handler/read_cgi_response_handler.cpp | 2 +- src/lib/core/server.cpp | 4 +- src/lib/core/virtual_server_resolver.cpp | 2 +- src/lib/http/handler/upload_file_handler.cpp | 69 +++++++++++-------- .../request/reader/reading_body_state.cpp | 4 +- .../reader/reading_chunked_body_state.cpp | 4 +- .../request/reader/reading_headers_state.cpp | 8 +-- .../reader/reading_request_line_state.cpp | 4 +- .../http/request/reader/request_reader.cpp | 7 +- .../http/request/reader/request_reader.hpp | 2 +- src/lib/transport/address.hpp | 2 +- src/lib/utils/auto_deleter.hpp | 2 +- src/lib/utils/ref.hpp | 10 ++- src/lib/utils/types/either.hpp | 12 ++-- src/lib/utils/types/option.hpp | 4 +- src/lib/utils/types/result.hpp | 9 +-- 25 files changed, 97 insertions(+), 87 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 70e09434..0e0c2b83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ project(webserv) # 指定したバージョンが使用できなければエラー set(CMAKE_CXX_STANDARD_REQUIRED ON) -add_compile_options(-Wall -Wextra) +add_compile_options(-Wall -Wextra -Werror) if (CMAKE_BUILD_TYPE STREQUAL "Debug") add_compile_options(-fno-omit-frame-pointer -fsanitize=address,undefined) add_link_options(-fsanitize=address,undefined) diff --git a/Makefile b/Makefile index 6625f5f6..9d6cf5c1 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ $(NAME): $(OBJS) $(BUILD_DIR)/%.o: %.cpp @mkdir -p $(dir $@) - $(CXX) $(CXXFLAGS) -c $< -o $@ + -$(CXX) $(CXXFLAGS) -c $< -o $@ clean: rm -rf $(BUILD_DIR) $(NAME) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 91e05b7d..c70747cc 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/lib/config/config.cpp b/src/lib/config/config.cpp index dc8a1aa4..041c27e9 100644 --- a/src/lib/config/config.cpp +++ b/src/lib/config/config.cpp @@ -242,7 +242,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..d70eb738 100644 --- a/src/lib/config/toml/parser.cpp +++ b/src/lib/config/toml/parser.cpp @@ -34,7 +34,7 @@ namespace toml { return Ok(t); } - return Err(error::AppError::kParseUnknown); + return Err(error::kParseUnknown); } void TomlParser::consumeNewlines() { @@ -80,7 +80,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 +93,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 +116,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 +124,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 +140,7 @@ namespace toml { Value val = TRY(parseVal()); if (keys.empty()) { - return Err(error::AppError::kParseUnknown); + return Err(error::kParseUnknown); } if (keys.size() == 1) { @@ -246,7 +246,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 cb675768..d6d58550 100644 --- a/src/lib/core/action/run_cgi_action.cpp +++ b/src/lib/core/action/run_cgi_action.cpp @@ -134,5 +134,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); - ctx.getState().getCgiProcessRepository().set(childPid, {clientFd_, socketFd}); + + CgiProcessRepository::Data data = {clientFd_, socketFd}; + 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..a32b9fdd 100644 --- a/src/lib/core/child_reaper.cpp +++ b/src/lib/core/child_reaper.cpp @@ -12,7 +12,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)}); + 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..e51e3aeb 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) { diff --git a/src/lib/core/server.cpp b/src/lib/core/server.cpp index c2bab85c..a2e2e9fe 100644 --- a/src/lib/core/server.cpp +++ b/src/lib/core/server.cpp @@ -115,7 +115,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/http/handler/upload_file_handler.cpp b/src/lib/http/handler/upload_file_handler.cpp index 3c3a586f..13f4e1e4 100644 --- a/src/lib/http/handler/upload_file_handler.cpp +++ b/src/lib/http/handler/upload_file_handler.cpp @@ -17,10 +17,12 @@ Either http::UploadFileHandler::serve(const RequestCo const Request &req = ctx.getRequest(); const Option contentTypeOpt = req.getHeader("Content-Type"); if (contentTypeOpt.isNone()) { - return Right(ResponseBuilder() - .status(kStatusUnsupportedMediaType) - .text("Content-Type must be multipart/form-data") - .build()); + return Right( + ResponseBuilder() + .status(kStatusUnsupportedMediaType) + .text("Content-Type must be multipart/form-data") + .build() + ); } // Content-Typeをセミコロン区切りでパース @@ -29,10 +31,12 @@ Either http::UploadFileHandler::serve(const RequestCo // 最初の部分がmultipart/form-dataであるか確認 if (contentTypeParams.empty() || utils::trim(contentTypeParams[0]) != kContentTypeMultipartFormData) { - return Right(ResponseBuilder() - .status(kStatusUnsupportedMediaType) - .text("Content-Type must be multipart/form-data") - .build()); + return Right( + ResponseBuilder() + .status(kStatusUnsupportedMediaType) + .text("Content-Type must be multipart/form-data") + .build() + ); } // boundaryパラメータを探す @@ -49,7 +53,8 @@ Either http::UploadFileHandler::serve(const RequestCo // key=valueの形式を確認 const std::string::size_type eqPos = param.find('='); if (eqPos == std::string::npos) { - return Right(ResponseBuilder().status(kStatusBadRequest).text("Invalid parameter format: " + param).build() + return Right( + ResponseBuilder().status(kStatusBadRequest).text("Invalid parameter format: " + param).build() ); } @@ -77,10 +82,12 @@ Either http::UploadFileHandler::serve(const RequestCo // RFC 1341に基づく境界値の検証 if (boundary.length() > 70) { - return Right(ResponseBuilder() - .status(kStatusBadRequest) - .text("Boundary parameter too long (max 70 characters)") - .build()); + return Right( + ResponseBuilder() + .status(kStatusBadRequest) + .text("Boundary parameter too long (max 70 characters)") + .build() + ); } for (size_t j = 0; j < boundary.length(); j++) { @@ -156,10 +163,12 @@ http::UploadFileHandler::findInitialBoundary(const std::string &body, const std: if (pos + 1 < body.length() && body[pos] == '\r' && body[pos + 1] == '\n') { pos += 2; } else { - return Err(ResponseBuilder() - .status(kStatusBadRequest) - .text("Invalid multipart format: expected CRLF after boundary") - .build()); + return Err( + ResponseBuilder() + .status(kStatusBadRequest) + .text("Invalid multipart format: expected CRLF after boundary") + .build() + ); } return Ok(pos); @@ -170,10 +179,12 @@ Result http::UploadFileHandler::extractA ) const { std::string::size_type nextPos = body.find(delimiter, pos); if (nextPos == std::string::npos) { - return Err(ResponseBuilder() - .status(kStatusBadRequest) - .text("Invalid multipart format: closing boundary not found") - .build()); + return Err( + ResponseBuilder() + .status(kStatusBadRequest) + .text("Invalid multipart format: closing boundary not found") + .build() + ); } std::string part = body.substr(pos, nextPos - pos); @@ -219,10 +230,12 @@ http::UploadFileHandler::checkBoundaryEnd(const std::string &body, std::string:: return Ok(false); // 通常のバウンダリ(続きがある) } - return Err(ResponseBuilder() - .status(kStatusBadRequest) - .text("Invalid multipart format: expected -- or CRLF after boundary") - .build()); + return Err( + ResponseBuilder() + .status(kStatusBadRequest) + .text("Invalid multipart format: expected -- or CRLF after boundary") + .build() + ); } Result @@ -230,7 +243,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 +300,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属性の処理 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..9abee6a4 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 33a7c3a4..e5b27a64 100644 --- a/src/lib/http/request/reader/reading_headers_state.cpp +++ b/src/lib/http/request/reader/reading_headers_state.cpp @@ -8,13 +8,13 @@ http::ReadingHeadersState::ReadingHeadersState(RequestReader::ReadContext &ctx) : ctx_(ctx) {} -Result http::ReadingHeadersState::handle(ReadBuffer &readBuf -) { +Result +http::ReadingHeadersState::handle(ReadBuffer &readBuf) { while (true) { 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 1939b62e..6ed4b500 100644 --- a/src/lib/http/request/reader/request_reader.cpp +++ b/src/lib/http/request/reader/request_reader.cpp @@ -32,8 +32,9 @@ http::RequestReader::ReadRequestResult http::RequestReader::readRequest(ReadBuff } } - return Ok(Some(TRY(RequestParser::parseRequest(readCtx_.getRequestLine(), readCtx_.getHeaders(), readCtx_.getBody()) - ))); + return Ok( + Some(TRY(RequestParser::parseRequest(readCtx_.getRequestLine(), readCtx_.getHeaders(), readCtx_.getBody()))) + ); } http::IConfigResolver::~IConfigResolver() {} @@ -51,7 +52,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/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..dab5f324 100644 --- a/src/lib/utils/ref.hpp +++ b/src/lib/utils/ref.hpp @@ -15,12 +15,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 +40,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..41aac13a 100644 --- a/src/lib/utils/types/either.hpp +++ b/src/lib/utils/types/either.hpp @@ -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()) { From 9c35d3be70ae7e030514731be11083d019c4b1ed Mon Sep 17 00:00:00 2001 From: smatsuodev Date: Mon, 18 Aug 2025 20:39:14 +0900 Subject: [PATCH 03/19] =?UTF-8?q?fclean=E3=81=A8re=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 9d6cf5c1..b1988b6f 100644 --- a/Makefile +++ b/Makefile @@ -12,12 +12,17 @@ $(NAME): $(OBJS) $(BUILD_DIR)/%.o: %.cpp @mkdir -p $(dir $@) - -$(CXX) $(CXXFLAGS) -c $< -o $@ + $(CXX) $(CXXFLAGS) -c $< -o $@ clean: - rm -rf $(BUILD_DIR) $(NAME) + rm -rf $(BUILD_DIR) + +fclean: clean + rm -rf $(NAME) + +re: fclean all format: clang-format -i $$(git ls-files '*.cpp' '*.hpp') -.PHONY: all clean format \ No newline at end of file +.PHONY: all clean fclean re format \ No newline at end of file From e5ab787357dba974015d446de0a9ac647bf777e5 Mon Sep 17 00:00:00 2001 From: smatsuodev Date: Mon, 18 Aug 2025 20:45:44 +0900 Subject: [PATCH 04/19] =?UTF-8?q?=E3=81=AEinclude=E3=82=92?= =?UTF-8?q?=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/http/handler/upload_file_handler.cpp | 63 ++++++++----------- .../request/reader/reading_headers_state.cpp | 4 +- .../http/request/reader/request_reader.cpp | 5 +- src/lib/utils/ref.hpp | 1 - src/lib/utils/types/either.hpp | 2 +- 5 files changed, 30 insertions(+), 45 deletions(-) diff --git a/src/lib/http/handler/upload_file_handler.cpp b/src/lib/http/handler/upload_file_handler.cpp index 13f4e1e4..1f76498d 100644 --- a/src/lib/http/handler/upload_file_handler.cpp +++ b/src/lib/http/handler/upload_file_handler.cpp @@ -17,12 +17,10 @@ Either http::UploadFileHandler::serve(const RequestCo const Request &req = ctx.getRequest(); const Option contentTypeOpt = req.getHeader("Content-Type"); if (contentTypeOpt.isNone()) { - return Right( - ResponseBuilder() - .status(kStatusUnsupportedMediaType) - .text("Content-Type must be multipart/form-data") - .build() - ); + return Right(ResponseBuilder() + .status(kStatusUnsupportedMediaType) + .text("Content-Type must be multipart/form-data") + .build()); } // Content-Typeをセミコロン区切りでパース @@ -31,12 +29,10 @@ Either http::UploadFileHandler::serve(const RequestCo // 最初の部分がmultipart/form-dataであるか確認 if (contentTypeParams.empty() || utils::trim(contentTypeParams[0]) != kContentTypeMultipartFormData) { - return Right( - ResponseBuilder() - .status(kStatusUnsupportedMediaType) - .text("Content-Type must be multipart/form-data") - .build() - ); + return Right(ResponseBuilder() + .status(kStatusUnsupportedMediaType) + .text("Content-Type must be multipart/form-data") + .build()); } // boundaryパラメータを探す @@ -53,8 +49,7 @@ Either http::UploadFileHandler::serve(const RequestCo // key=valueの形式を確認 const std::string::size_type eqPos = param.find('='); if (eqPos == std::string::npos) { - return Right( - ResponseBuilder().status(kStatusBadRequest).text("Invalid parameter format: " + param).build() + return Right(ResponseBuilder().status(kStatusBadRequest).text("Invalid parameter format: " + param).build() ); } @@ -82,12 +77,10 @@ Either http::UploadFileHandler::serve(const RequestCo // RFC 1341に基づく境界値の検証 if (boundary.length() > 70) { - return Right( - ResponseBuilder() - .status(kStatusBadRequest) - .text("Boundary parameter too long (max 70 characters)") - .build() - ); + return Right(ResponseBuilder() + .status(kStatusBadRequest) + .text("Boundary parameter too long (max 70 characters)") + .build()); } for (size_t j = 0; j < boundary.length(); j++) { @@ -163,12 +156,10 @@ http::UploadFileHandler::findInitialBoundary(const std::string &body, const std: if (pos + 1 < body.length() && body[pos] == '\r' && body[pos + 1] == '\n') { pos += 2; } else { - return Err( - ResponseBuilder() - .status(kStatusBadRequest) - .text("Invalid multipart format: expected CRLF after boundary") - .build() - ); + return Err(ResponseBuilder() + .status(kStatusBadRequest) + .text("Invalid multipart format: expected CRLF after boundary") + .build()); } return Ok(pos); @@ -179,12 +170,10 @@ Result http::UploadFileHandler::extractA ) const { std::string::size_type nextPos = body.find(delimiter, pos); if (nextPos == std::string::npos) { - return Err( - ResponseBuilder() - .status(kStatusBadRequest) - .text("Invalid multipart format: closing boundary not found") - .build() - ); + return Err(ResponseBuilder() + .status(kStatusBadRequest) + .text("Invalid multipart format: closing boundary not found") + .build()); } std::string part = body.substr(pos, nextPos - pos); @@ -230,12 +219,10 @@ http::UploadFileHandler::checkBoundaryEnd(const std::string &body, std::string:: return Ok(false); // 通常のバウンダリ(続きがある) } - return Err( - ResponseBuilder() - .status(kStatusBadRequest) - .text("Invalid multipart format: expected -- or CRLF after boundary") - .build() - ); + return Err(ResponseBuilder() + .status(kStatusBadRequest) + .text("Invalid multipart format: expected -- or CRLF after boundary") + .build()); } Result diff --git a/src/lib/http/request/reader/reading_headers_state.cpp b/src/lib/http/request/reader/reading_headers_state.cpp index e5b27a64..356e945e 100644 --- a/src/lib/http/request/reader/reading_headers_state.cpp +++ b/src/lib/http/request/reader/reading_headers_state.cpp @@ -8,8 +8,8 @@ http::ReadingHeadersState::ReadingHeadersState(RequestReader::ReadContext &ctx) : ctx_(ctx) {} -Result -http::ReadingHeadersState::handle(ReadBuffer &readBuf) { +Result http::ReadingHeadersState::handle(ReadBuffer &readBuf +) { while (true) { const Option line = TRY(getLine(readBuf)); if (line.isNone()) { diff --git a/src/lib/http/request/reader/request_reader.cpp b/src/lib/http/request/reader/request_reader.cpp index 6ed4b500..430785d7 100644 --- a/src/lib/http/request/reader/request_reader.cpp +++ b/src/lib/http/request/reader/request_reader.cpp @@ -32,9 +32,8 @@ http::RequestReader::ReadRequestResult http::RequestReader::readRequest(ReadBuff } } - return Ok( - Some(TRY(RequestParser::parseRequest(readCtx_.getRequestLine(), readCtx_.getHeaders(), readCtx_.getBody()))) - ); + return Ok(Some(TRY(RequestParser::parseRequest(readCtx_.getRequestLine(), readCtx_.getHeaders(), readCtx_.getBody()) + ))); } http::IConfigResolver::~IConfigResolver() {} diff --git a/src/lib/utils/ref.hpp b/src/lib/utils/ref.hpp index dab5f324..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 diff --git a/src/lib/utils/types/either.hpp b/src/lib/utils/types/either.hpp index 41aac13a..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 From 5f9e0fff66235c8ee69c8a93ff50dc7b81b441f5 Mon Sep 17 00:00:00 2001 From: smatsuodev Date: Mon, 18 Aug 2025 20:48:51 +0900 Subject: [PATCH 05/19] include --- src/lib/core/server.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/core/server.cpp b/src/lib/core/server.cpp index a2e2e9fe..7f4a1356 100644 --- a/src/lib/core/server.cpp +++ b/src/lib/core/server.cpp @@ -7,6 +7,7 @@ #include "transport/listener.hpp" #include "utils/logger.hpp" #include +#include Server::Server(const config::Config &config) : config_(config) { const config::ServerContextList &servers = config_.getServers(); From 256f4e072ffe79d54ee6287d493d91062e603c83 Mon Sep 17 00:00:00 2001 From: smatsuodev Date: Mon, 18 Aug 2025 12:57:50 +0000 Subject: [PATCH 06/19] =?UTF-8?q?error=E3=81=AA=E3=81=8A=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/cgi/factory.cpp | 2 +- src/lib/config/config.cpp | 8 +- src/lib/config/toml/parser.cpp | 7 +- src/lib/core/action/run_cgi_action.cpp | 1 + src/lib/core/child_reaper.cpp | 1 + .../handler/read_cgi_response_handler.cpp | 4 +- .../handler/write_cgi_request_handler.cpp | 1 + src/lib/http/handler/cgi_handler.cpp | 2 +- src/lib/http/handler/delete_file_handler.cpp | 2 + .../http/handler/middleware/error_page.cpp | 2 +- src/lib/http/handler/upload_file_handler.cpp | 2 +- src/lib/http/response/response_builder.cpp | 2 +- tests/toml_parser_test.cpp | 4 +- tests/toml_tokenizer_test.cpp | 102 +++++++++--------- 14 files changed, 76 insertions(+), 64 deletions(-) diff --git a/src/lib/cgi/factory.cpp b/src/lib/cgi/factory.cpp index 30ab5c87..cb0f954a 100644 --- a/src/lib/cgi/factory.cpp +++ b/src/lib/cgi/factory.cpp @@ -60,7 +60,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 041c27e9..cdd3f780 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 = std::atoi(keys[j].c_str()); Option httpStatusCode = http::httpStatusCodeFromInt(statusCode); if (httpStatusCode.isNone()) { LOG_WARNF("invalid HTTP status code: %d", statusCode); diff --git a/src/lib/config/toml/parser.cpp b/src/lib/config/toml/parser.cpp index d70eb738..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, "") { @@ -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(); diff --git a/src/lib/core/action/run_cgi_action.cpp b/src/lib/core/action/run_cgi_action.cpp index d6d58550..44f7ede7 100644 --- a/src/lib/core/action/run_cgi_action.cpp +++ b/src/lib/core/action/run_cgi_action.cpp @@ -9,6 +9,7 @@ #include "../../cgi/meta_variable.hpp" #include "utils/fd.hpp" #include "utils/logger.hpp" +#include void RunCgiAction::execute(ActionContext &ctx) { int pair[2]; diff --git a/src/lib/core/child_reaper.cpp b/src/lib/core/child_reaper.cpp index a32b9fdd..c459a99c 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); diff --git a/src/lib/core/handler/read_cgi_response_handler.cpp b/src/lib/core/handler/read_cgi_response_handler.cpp index e51e3aeb..a5773ced 100644 --- a/src/lib/core/handler/read_cgi_response_handler.cpp +++ b/src/lib/core/handler/read_cgi_response_handler.cpp @@ -115,8 +115,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/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/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 1f76498d..a283d3b3 100644 --- a/src/lib/http/handler/upload_file_handler.cpp +++ b/src/lib/http/handler/upload_file_handler.cpp @@ -319,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/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/tests/toml_parser_test.cpp b/tests/toml_parser_test.cpp index 04b1b17e..206b46bd 100644 --- a/tests/toml_parser_test.cpp +++ b/tests/toml_parser_test.cpp @@ -110,11 +110,11 @@ TEST(ParserOkDiscouraged, messyDottedKey) { const auto text = R"( fruit.count = 2 - # fruit.*.color を代入 +#fruit.*.color を代入 fruit.apple.color = "red" fruit.orange.color = "orange" - # fruit.*.price を代入 +#fruit.*.price を代入 fruit.apple.price = 100 fruit.orange.price = 200 )"; diff --git a/tests/toml_tokenizer_test.cpp b/tests/toml_tokenizer_test.cpp index 21a791fa..8c9e7483 100644 --- a/tests/toml_tokenizer_test.cpp +++ b/tests/toml_tokenizer_test.cpp @@ -15,52 +15,51 @@ void testErr(const std::string &text) { } TEST(TokenizerOk, empty) { - const auto text = R"()"; + const auto text = R "()"; testOk(text, {Token(kEof, "")}); } TEST(TokenizerOk, comment) { - const auto text = R"(# comment)"; + const auto text = R "(# comment)"; testOk(text, {Token(kEof, "")}); } TEST(TokenizerOk, integer) { - const auto text = R"(42)"; + const auto text = R "(42)"; testOk(text, {Token(kNum, "42"), Token(kEof, "")}); } TEST(TokenizerOk, key) { - const auto text = R"(key)"; + const auto text = R "(key)"; testOk(text, {Token(kKey, "key"), Token(kEof, "")}); } TEST(TokenizerOk, keyStartWithNumberEndWithAlphabet) { - const auto text = R"(42key)"; + const auto text = R "(42key)"; testOk(text, {Token(kKey, "42key"), Token(kEof, "")}); } TEST(TokenizerOk, keyStartWithAlphabetEndWithNumber) { - const auto text = R"(key42)"; + const auto text = R "(key42)"; testOk(text, {Token(kKey, "key42"), Token(kEof, "")}); } TEST(TokenizerOk, keyWithUnderscore) { - const auto text = R"(_key_42_)"; + const auto text = R "(_key_42_)"; testOk(text, {Token(kKey, "_key_42_"), Token(kEof, "")}); } -TEST(TokenizerOk, singleQuotedString) { - const auto text = R"('ke"y')"; - testOk(text, {Token(kString, "ke\"y"), Token(kEof, "")}); +TEST(TokenizerOk, singleQuotedString){ + const auto text = R "('ke" y')"; testOk(text, {Token(kString, "ke\"y"), Token(kEof, "")}); } -TEST(TokenizerOk, doubleQuotedString) { - const auto text = R"("ke'y")"; - testOk(text, {Token(kString, "ke'y"), Token(kEof, "")}); +TEST(TokenizerOk, doubleQuotedString){ + const auto text = R "(" ke 'y")"; testOk(text, {Token(kString, "ke' y "), Token(kEof, " + ")}); } TEST(TokenizerOk, commentAfterValue) { - const auto text = R"(key = "value" # comment)"; + const auto text = R "(key = " value " # comment)"; testOk( text, { @@ -73,7 +72,7 @@ TEST(TokenizerOk, commentAfterValue) { } TEST(TokenizerOk, notComment) { - const auto text = R"(key = "# this is not comment")"; + const auto text = R "(key = " #this is not comment ")"; testOk( text, { @@ -86,7 +85,7 @@ TEST(TokenizerOk, notComment) { } TEST(TokenizerOk, keyValue) { - const auto text = R"(key = 0)"; + const auto text = R "(key = 0)"; testOk( text, { @@ -99,7 +98,7 @@ TEST(TokenizerOk, keyValue) { } TEST(TokenizerOk, intKey) { - const auto text = R"(123 = 0)"; + const auto text = R "(123 = 0)"; testOk( text, { @@ -112,7 +111,7 @@ TEST(TokenizerOk, intKey) { } TEST(TokenizerOk, quotedKey) { - const auto text = R"("127.0.0.1" = 0)"; + const auto text = R "(" 127.0.0.1 " = 0)"; testOk( text, { @@ -125,7 +124,7 @@ TEST(TokenizerOk, quotedKey) { } TEST(TokenizerOk, keyContainsEq) { - const auto text = R"("a=b" = 0)"; + const auto text = R "(" a = b " = 0)"; testOk( text, { @@ -138,7 +137,7 @@ TEST(TokenizerOk, keyContainsEq) { } TEST(TokenizerOk, unicodeKey) { - const auto text = R"("ʎǝʞ" = 0)"; + const auto text = R "("ʎ ǝʞ " = 0)"; testOk( text, { @@ -151,7 +150,7 @@ TEST(TokenizerOk, unicodeKey) { } TEST(TokenizerOk, singleQuotedKey) { - const auto text = R"('key' = 0)"; + const auto text = R "('key' = 0)"; testOk( text, { @@ -164,11 +163,11 @@ TEST(TokenizerOk, singleQuotedKey) { } TEST(TokenizerOk, quotedQuoteKey) { - const auto text = R"('"quoted key"' = 0)"; + const auto text = R "('" quoted key "' = 0)"; testOk( text, { - Token(kString, R"("quoted key")"), + Token(kString, R "(" quoted key ")"), Token(kAssignment, "="), Token(kNum, "0"), Token(kEof, ""), @@ -178,7 +177,8 @@ TEST(TokenizerOk, quotedQuoteKey) { // 有効だが非推奨 TEST(TokenizerOkDiscouraged, emptyKey) { - const auto text = R"("" = 0)"; + const auto text = R "(" + " = 0)"; testOk( text, { @@ -192,7 +192,7 @@ TEST(TokenizerOkDiscouraged, emptyKey) { // // 有効だが非推奨 TEST(TokenizerOkDiscouraged, emptyKeySingle) { - const auto text = R"('' = 0)"; + const auto text = R "('' = 0)"; testOk( text, { @@ -205,7 +205,7 @@ TEST(TokenizerOkDiscouraged, emptyKeySingle) { } TEST(TokenizerOk, dottedKey) { - const auto text = R"(k1.k2 = 0)"; + const auto text = R "(k1.k2 = 0)"; testOk( text, { @@ -220,7 +220,7 @@ TEST(TokenizerOk, dottedKey) { } TEST(TokenizerOk, dottedQuotedKey) { - const auto text = R"(k1."k2.k3".k4 = 0)"; + const auto text = R "(k1." k2.k3 ".k4 = 0)"; testOk( text, {Token(kKey, "k1"), @@ -235,7 +235,7 @@ TEST(TokenizerOk, dottedQuotedKey) { } TEST(TokenizerOk, spaceAroudDot) { - const auto text = R"(k1 . k2 = 0)"; + const auto text = R "(k1 . k2 = 0)"; testOk( text, { @@ -250,7 +250,7 @@ TEST(TokenizerOk, spaceAroudDot) { } TEST(TokenizerOk, notFloat) { - const auto text = R"(3 . 14 = "pi")"; + const auto text = R "(3 . 14 = " pi ")"; testOk( text, { @@ -265,22 +265,22 @@ TEST(TokenizerOk, notFloat) { } TEST(TokenizerOk, plusInteger) { - const auto text = R"(+99)"; + const auto text = R "(+99)"; testOk(text, {Token(kNum, "+99"), Token(kEof, "")}); } TEST(TokenizerOk, minusInteger) { - const auto text = R"(-17)"; + const auto text = R "(-17)"; testOk(text, {Token(kNum, "-17"), Token(kEof, "")}); } TEST(TokenizerOk, emptyArray) { - const auto text = R"([])"; + const auto text = R "([])"; testOk(text, {Token(kLBracket, "["), Token(kRBracket, "]"), Token(kEof, "")}); } TEST(TokenizerOk, intArray) { - const auto text = R"([1, 2])"; + const auto text = R "([1, 2])"; testOk( text, { @@ -295,7 +295,7 @@ TEST(TokenizerOk, intArray) { } TEST(TokenizerOk, stringArray) { - const auto text = R"(["foo", 'bar'])"; + const auto text = R "([" foo ", 'bar'])"; testOk( text, { @@ -311,7 +311,7 @@ TEST(TokenizerOk, stringArray) { TEST(TokenizerOk, nestedArray) { - const auto text = R"([[1, 2], [3, 4]])"; + const auto text = R "([[1, 2], [3, 4]])"; testOk( text, { @@ -334,7 +334,7 @@ TEST(TokenizerOk, nestedArray) { } TEST(TokenizerOk, nestedMixedArray) { - const auto text = R"([[1, 2], ["a", "b"]])"; + const auto text = R "([[1, 2], [" a ", " b "]])"; testOk( text, { @@ -357,7 +357,7 @@ TEST(TokenizerOk, nestedMixedArray) { } TEST(TokenizerOk, mixedArray) { - const auto text = R"(k = [1, "value", [1], { key = "value" }, ])"; + const auto text = R "(k = [1, " value ", [1], { key = " value " }, ])"; testOk( text, {Token(kKey, "k"), @@ -383,7 +383,10 @@ TEST(TokenizerOk, mixedArray) { } TEST(TokenizerOk, justStringArray) { - const auto text = R"(k1.k2 = ["[1]", "{a.b=0}"])"; + const auto text = R "(k1.k2 = ["[1] ", " { + a.b = 0 + } + "])"; testOk( text, { @@ -402,7 +405,7 @@ TEST(TokenizerOk, justStringArray) { } TEST(TokenizerOk, table) { - const auto text = R"([table])"; + const auto text = R "([table])"; testOk( text, { @@ -415,7 +418,7 @@ TEST(TokenizerOk, table) { } TEST(TokenizerOk, dottedTable) { - const auto text = R"([a.b.c])"; + const auto text = R "([a.b.c])"; testOk( text, { @@ -432,7 +435,7 @@ TEST(TokenizerOk, dottedTable) { } TEST(TokenizerOk, dottedSpaceTable) { - const auto text = R"([ a.b.c ])"; + const auto text = R "([ a.b.c ])"; testOk( text, { @@ -449,7 +452,7 @@ TEST(TokenizerOk, dottedSpaceTable) { } TEST(TokenizerOk, dottedSpaceTable2) { - const auto text = R"([ a . b . c ])"; + const auto text = R "([ a . b . c ])"; testOk( text, { @@ -466,7 +469,8 @@ TEST(TokenizerOk, dottedSpaceTable2) { } TEST(TokenizerOk, dottedSpaceTable3) { - const auto text = R"([ j . "ʞ" . 'l' ])"; + const auto text = R "([ j . "ʞ + " . 'l' ])"; testOk( text, { @@ -483,7 +487,7 @@ TEST(TokenizerOk, dottedSpaceTable3) { } TEST(TokenizerOk, inlineTable) { - const auto text = R"({x=0, y=1})"; + const auto text = R "({x=0, y=1})"; testOk( text, { @@ -502,7 +506,7 @@ TEST(TokenizerOk, inlineTable) { } TEST(TokenizerOk, dottedKeyInInlineTable) { - const auto text = R"({ a.b = 0 })"; + const auto text = R "({ a.b = 0 })"; testOk( text, { @@ -519,7 +523,7 @@ TEST(TokenizerOk, dottedKeyInInlineTable) { } TEST(TokenizerOk, arrayOfTable) { - const auto text = R"([[array]])"; + const auto text = R "([[array]])"; testOk( text, { @@ -534,7 +538,7 @@ TEST(TokenizerOk, arrayOfTable) { } TEST(TokenizerOk, dottedArrayOfTable) { - const auto text = R"([[a.b]])"; + const auto text = R "([[a.b]])"; testOk( text, { @@ -576,7 +580,7 @@ key = 0)"; } TEST(TokenizerOk, boolean) { - const auto text = R"(true false)"; + const auto text = R "(true false)"; testOk( text, { @@ -588,7 +592,7 @@ TEST(TokenizerOk, boolean) { } TEST(TokenizerErr, invalidChar) { - const auto text = R"(%)"; + const auto text = R "(%)"; testErr(text); } From 182ca6a766f630f26def6bb31a414c70b2728aa8 Mon Sep 17 00:00:00 2001 From: smatsuodev Date: Mon, 18 Aug 2025 21:59:59 +0900 Subject: [PATCH 07/19] format --- tests/toml_tokenizer_test.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/toml_tokenizer_test.cpp b/tests/toml_tokenizer_test.cpp index 8c9e7483..766f1fb4 100644 --- a/tests/toml_tokenizer_test.cpp +++ b/tests/toml_tokenizer_test.cpp @@ -383,10 +383,7 @@ TEST(TokenizerOk, mixedArray) { } TEST(TokenizerOk, justStringArray) { - const auto text = R "(k1.k2 = ["[1] ", " { - a.b = 0 - } - "])"; + const auto text = R "(k1.k2 = ["[1] ", " {a.b = 0} "])"; testOk( text, { From 4572e48547f57f7b4ceb4bc36dca7899280e739b Mon Sep 17 00:00:00 2001 From: smatsuodev Date: Mon, 18 Aug 2025 13:03:44 +0000 Subject: [PATCH 08/19] =?UTF-8?q?format=E6=88=BB=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/toml_parser_test.cpp | 4 +- tests/toml_tokenizer_test.cpp | 99 +++++++++++++++++------------------ 2 files changed, 51 insertions(+), 52 deletions(-) diff --git a/tests/toml_parser_test.cpp b/tests/toml_parser_test.cpp index 206b46bd..04b1b17e 100644 --- a/tests/toml_parser_test.cpp +++ b/tests/toml_parser_test.cpp @@ -110,11 +110,11 @@ TEST(ParserOkDiscouraged, messyDottedKey) { const auto text = R"( fruit.count = 2 -#fruit.*.color を代入 + # fruit.*.color を代入 fruit.apple.color = "red" fruit.orange.color = "orange" -#fruit.*.price を代入 + # fruit.*.price を代入 fruit.apple.price = 100 fruit.orange.price = 200 )"; diff --git a/tests/toml_tokenizer_test.cpp b/tests/toml_tokenizer_test.cpp index 766f1fb4..21a791fa 100644 --- a/tests/toml_tokenizer_test.cpp +++ b/tests/toml_tokenizer_test.cpp @@ -15,51 +15,52 @@ void testErr(const std::string &text) { } TEST(TokenizerOk, empty) { - const auto text = R "()"; + const auto text = R"()"; testOk(text, {Token(kEof, "")}); } TEST(TokenizerOk, comment) { - const auto text = R "(# comment)"; + const auto text = R"(# comment)"; testOk(text, {Token(kEof, "")}); } TEST(TokenizerOk, integer) { - const auto text = R "(42)"; + const auto text = R"(42)"; testOk(text, {Token(kNum, "42"), Token(kEof, "")}); } TEST(TokenizerOk, key) { - const auto text = R "(key)"; + const auto text = R"(key)"; testOk(text, {Token(kKey, "key"), Token(kEof, "")}); } TEST(TokenizerOk, keyStartWithNumberEndWithAlphabet) { - const auto text = R "(42key)"; + const auto text = R"(42key)"; testOk(text, {Token(kKey, "42key"), Token(kEof, "")}); } TEST(TokenizerOk, keyStartWithAlphabetEndWithNumber) { - const auto text = R "(key42)"; + const auto text = R"(key42)"; testOk(text, {Token(kKey, "key42"), Token(kEof, "")}); } TEST(TokenizerOk, keyWithUnderscore) { - const auto text = R "(_key_42_)"; + const auto text = R"(_key_42_)"; testOk(text, {Token(kKey, "_key_42_"), Token(kEof, "")}); } -TEST(TokenizerOk, singleQuotedString){ - const auto text = R "('ke" y')"; testOk(text, {Token(kString, "ke\"y"), Token(kEof, "")}); +TEST(TokenizerOk, singleQuotedString) { + const auto text = R"('ke"y')"; + testOk(text, {Token(kString, "ke\"y"), Token(kEof, "")}); } -TEST(TokenizerOk, doubleQuotedString){ - const auto text = R "(" ke 'y")"; testOk(text, {Token(kString, "ke' y "), Token(kEof, " - ")}); +TEST(TokenizerOk, doubleQuotedString) { + const auto text = R"("ke'y")"; + testOk(text, {Token(kString, "ke'y"), Token(kEof, "")}); } TEST(TokenizerOk, commentAfterValue) { - const auto text = R "(key = " value " # comment)"; + const auto text = R"(key = "value" # comment)"; testOk( text, { @@ -72,7 +73,7 @@ TEST(TokenizerOk, commentAfterValue) { } TEST(TokenizerOk, notComment) { - const auto text = R "(key = " #this is not comment ")"; + const auto text = R"(key = "# this is not comment")"; testOk( text, { @@ -85,7 +86,7 @@ TEST(TokenizerOk, notComment) { } TEST(TokenizerOk, keyValue) { - const auto text = R "(key = 0)"; + const auto text = R"(key = 0)"; testOk( text, { @@ -98,7 +99,7 @@ TEST(TokenizerOk, keyValue) { } TEST(TokenizerOk, intKey) { - const auto text = R "(123 = 0)"; + const auto text = R"(123 = 0)"; testOk( text, { @@ -111,7 +112,7 @@ TEST(TokenizerOk, intKey) { } TEST(TokenizerOk, quotedKey) { - const auto text = R "(" 127.0.0.1 " = 0)"; + const auto text = R"("127.0.0.1" = 0)"; testOk( text, { @@ -124,7 +125,7 @@ TEST(TokenizerOk, quotedKey) { } TEST(TokenizerOk, keyContainsEq) { - const auto text = R "(" a = b " = 0)"; + const auto text = R"("a=b" = 0)"; testOk( text, { @@ -137,7 +138,7 @@ TEST(TokenizerOk, keyContainsEq) { } TEST(TokenizerOk, unicodeKey) { - const auto text = R "("ʎ ǝʞ " = 0)"; + const auto text = R"("ʎǝʞ" = 0)"; testOk( text, { @@ -150,7 +151,7 @@ TEST(TokenizerOk, unicodeKey) { } TEST(TokenizerOk, singleQuotedKey) { - const auto text = R "('key' = 0)"; + const auto text = R"('key' = 0)"; testOk( text, { @@ -163,11 +164,11 @@ TEST(TokenizerOk, singleQuotedKey) { } TEST(TokenizerOk, quotedQuoteKey) { - const auto text = R "('" quoted key "' = 0)"; + const auto text = R"('"quoted key"' = 0)"; testOk( text, { - Token(kString, R "(" quoted key ")"), + Token(kString, R"("quoted key")"), Token(kAssignment, "="), Token(kNum, "0"), Token(kEof, ""), @@ -177,8 +178,7 @@ TEST(TokenizerOk, quotedQuoteKey) { // 有効だが非推奨 TEST(TokenizerOkDiscouraged, emptyKey) { - const auto text = R "(" - " = 0)"; + const auto text = R"("" = 0)"; testOk( text, { @@ -192,7 +192,7 @@ TEST(TokenizerOkDiscouraged, emptyKey) { // // 有効だが非推奨 TEST(TokenizerOkDiscouraged, emptyKeySingle) { - const auto text = R "('' = 0)"; + const auto text = R"('' = 0)"; testOk( text, { @@ -205,7 +205,7 @@ TEST(TokenizerOkDiscouraged, emptyKeySingle) { } TEST(TokenizerOk, dottedKey) { - const auto text = R "(k1.k2 = 0)"; + const auto text = R"(k1.k2 = 0)"; testOk( text, { @@ -220,7 +220,7 @@ TEST(TokenizerOk, dottedKey) { } TEST(TokenizerOk, dottedQuotedKey) { - const auto text = R "(k1." k2.k3 ".k4 = 0)"; + const auto text = R"(k1."k2.k3".k4 = 0)"; testOk( text, {Token(kKey, "k1"), @@ -235,7 +235,7 @@ TEST(TokenizerOk, dottedQuotedKey) { } TEST(TokenizerOk, spaceAroudDot) { - const auto text = R "(k1 . k2 = 0)"; + const auto text = R"(k1 . k2 = 0)"; testOk( text, { @@ -250,7 +250,7 @@ TEST(TokenizerOk, spaceAroudDot) { } TEST(TokenizerOk, notFloat) { - const auto text = R "(3 . 14 = " pi ")"; + const auto text = R"(3 . 14 = "pi")"; testOk( text, { @@ -265,22 +265,22 @@ TEST(TokenizerOk, notFloat) { } TEST(TokenizerOk, plusInteger) { - const auto text = R "(+99)"; + const auto text = R"(+99)"; testOk(text, {Token(kNum, "+99"), Token(kEof, "")}); } TEST(TokenizerOk, minusInteger) { - const auto text = R "(-17)"; + const auto text = R"(-17)"; testOk(text, {Token(kNum, "-17"), Token(kEof, "")}); } TEST(TokenizerOk, emptyArray) { - const auto text = R "([])"; + const auto text = R"([])"; testOk(text, {Token(kLBracket, "["), Token(kRBracket, "]"), Token(kEof, "")}); } TEST(TokenizerOk, intArray) { - const auto text = R "([1, 2])"; + const auto text = R"([1, 2])"; testOk( text, { @@ -295,7 +295,7 @@ TEST(TokenizerOk, intArray) { } TEST(TokenizerOk, stringArray) { - const auto text = R "([" foo ", 'bar'])"; + const auto text = R"(["foo", 'bar'])"; testOk( text, { @@ -311,7 +311,7 @@ TEST(TokenizerOk, stringArray) { TEST(TokenizerOk, nestedArray) { - const auto text = R "([[1, 2], [3, 4]])"; + const auto text = R"([[1, 2], [3, 4]])"; testOk( text, { @@ -334,7 +334,7 @@ TEST(TokenizerOk, nestedArray) { } TEST(TokenizerOk, nestedMixedArray) { - const auto text = R "([[1, 2], [" a ", " b "]])"; + const auto text = R"([[1, 2], ["a", "b"]])"; testOk( text, { @@ -357,7 +357,7 @@ TEST(TokenizerOk, nestedMixedArray) { } TEST(TokenizerOk, mixedArray) { - const auto text = R "(k = [1, " value ", [1], { key = " value " }, ])"; + const auto text = R"(k = [1, "value", [1], { key = "value" }, ])"; testOk( text, {Token(kKey, "k"), @@ -383,7 +383,7 @@ TEST(TokenizerOk, mixedArray) { } TEST(TokenizerOk, justStringArray) { - const auto text = R "(k1.k2 = ["[1] ", " {a.b = 0} "])"; + const auto text = R"(k1.k2 = ["[1]", "{a.b=0}"])"; testOk( text, { @@ -402,7 +402,7 @@ TEST(TokenizerOk, justStringArray) { } TEST(TokenizerOk, table) { - const auto text = R "([table])"; + const auto text = R"([table])"; testOk( text, { @@ -415,7 +415,7 @@ TEST(TokenizerOk, table) { } TEST(TokenizerOk, dottedTable) { - const auto text = R "([a.b.c])"; + const auto text = R"([a.b.c])"; testOk( text, { @@ -432,7 +432,7 @@ TEST(TokenizerOk, dottedTable) { } TEST(TokenizerOk, dottedSpaceTable) { - const auto text = R "([ a.b.c ])"; + const auto text = R"([ a.b.c ])"; testOk( text, { @@ -449,7 +449,7 @@ TEST(TokenizerOk, dottedSpaceTable) { } TEST(TokenizerOk, dottedSpaceTable2) { - const auto text = R "([ a . b . c ])"; + const auto text = R"([ a . b . c ])"; testOk( text, { @@ -466,8 +466,7 @@ TEST(TokenizerOk, dottedSpaceTable2) { } TEST(TokenizerOk, dottedSpaceTable3) { - const auto text = R "([ j . "ʞ - " . 'l' ])"; + const auto text = R"([ j . "ʞ" . 'l' ])"; testOk( text, { @@ -484,7 +483,7 @@ TEST(TokenizerOk, dottedSpaceTable3) { } TEST(TokenizerOk, inlineTable) { - const auto text = R "({x=0, y=1})"; + const auto text = R"({x=0, y=1})"; testOk( text, { @@ -503,7 +502,7 @@ TEST(TokenizerOk, inlineTable) { } TEST(TokenizerOk, dottedKeyInInlineTable) { - const auto text = R "({ a.b = 0 })"; + const auto text = R"({ a.b = 0 })"; testOk( text, { @@ -520,7 +519,7 @@ TEST(TokenizerOk, dottedKeyInInlineTable) { } TEST(TokenizerOk, arrayOfTable) { - const auto text = R "([[array]])"; + const auto text = R"([[array]])"; testOk( text, { @@ -535,7 +534,7 @@ TEST(TokenizerOk, arrayOfTable) { } TEST(TokenizerOk, dottedArrayOfTable) { - const auto text = R "([[a.b]])"; + const auto text = R"([[a.b]])"; testOk( text, { @@ -577,7 +576,7 @@ key = 0)"; } TEST(TokenizerOk, boolean) { - const auto text = R "(true false)"; + const auto text = R"(true false)"; testOk( text, { @@ -589,7 +588,7 @@ TEST(TokenizerOk, boolean) { } TEST(TokenizerErr, invalidChar) { - const auto text = R "(%)"; + const auto text = R"(%)"; testErr(text); } From d497eb4428654982901028b402760223ed80a2a3 Mon Sep 17 00:00:00 2001 From: smatsuodev Date: Mon, 18 Aug 2025 13:08:49 +0000 Subject: [PATCH 09/19] =?UTF-8?q?atoi=E3=82=92strtol=E3=81=AB=E7=9B=B4?= =?UTF-8?q?=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/config/config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/config/config.cpp b/src/lib/config/config.cpp index cdd3f780..8560bab4 100644 --- a/src/lib/config/config.cpp +++ b/src/lib/config/config.cpp @@ -115,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::atoi(keys[j].c_str()); + int statusCode = std::strtol(keys[j].c_str(), NULL, 10); Option httpStatusCode = http::httpStatusCodeFromInt(statusCode); if (httpStatusCode.isNone()) { LOG_WARNF("invalid HTTP status code: %d", statusCode); From 6198919df9bff6aa9d505372a8d917fb96d8bde2 Mon Sep 17 00:00:00 2001 From: smatsuodev Date: Mon, 18 Aug 2025 13:09:47 +0000 Subject: [PATCH 10/19] =?UTF-8?q?static=5Fcast=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/config/config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/config/config.cpp b/src/lib/config/config.cpp index 8560bab4..9f665619 100644 --- a/src/lib/config/config.cpp +++ b/src/lib/config/config.cpp @@ -115,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::strtol(keys[j].c_str(), NULL, 10); + 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); From a38a65cfb69a2e645e00758526b7469fcc75faf2 Mon Sep 17 00:00:00 2001 From: smatsuodev Date: Mon, 18 Aug 2025 13:12:53 +0000 Subject: [PATCH 11/19] =?UTF-8?q?lint=E7=84=A1=E8=A6=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/utils/types/option.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/utils/types/option.hpp b/src/lib/utils/types/option.hpp index 1ffa14c1..6b2e7f2d 100644 --- a/src/lib/utils/types/option.hpp +++ b/src/lib/utils/types/option.hpp @@ -87,6 +87,7 @@ types::Some Some(T val) { } // ReSharper disable once CppInconsistentNaming +// NOLINTNEXTLINE(clang-diagnostic-unneeded-internal-declaration) const types::None None = types::None(); template From 0648c6d4607a67022411b95efb202712ec7a7ab0 Mon Sep 17 00:00:00 2001 From: smatsuodev Date: Mon, 18 Aug 2025 13:16:14 +0000 Subject: [PATCH 12/19] =?UTF-8?q?lint=E7=84=A1=E8=A6=962?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/utils/types/option.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/utils/types/option.hpp b/src/lib/utils/types/option.hpp index 6b2e7f2d..e3e86dd1 100644 --- a/src/lib/utils/types/option.hpp +++ b/src/lib/utils/types/option.hpp @@ -87,7 +87,7 @@ types::Some Some(T val) { } // ReSharper disable once CppInconsistentNaming -// NOLINTNEXTLINE(clang-diagnostic-unneeded-internal-declaration) +// NOLINTNEXTLINE const types::None None = types::None(); template From 00f2c89532dbd97a82d998782ffed8d00ab4d843 Mon Sep 17 00:00:00 2001 From: smatsuodev Date: Mon, 18 Aug 2025 13:19:57 +0000 Subject: [PATCH 13/19] NOLINT --- src/lib/utils/types/option.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib/utils/types/option.hpp b/src/lib/utils/types/option.hpp index e3e86dd1..d271e181 100644 --- a/src/lib/utils/types/option.hpp +++ b/src/lib/utils/types/option.hpp @@ -87,8 +87,7 @@ types::Some Some(T val) { } // ReSharper disable once CppInconsistentNaming -// NOLINTNEXTLINE -const types::None None = types::None(); +const types::None None = types::None(); // NOLINT template class Option { From 9e1977a63ebbb031e6cdf55e38c48de1cb3de974 Mon Sep 17 00:00:00 2001 From: smatsuodev Date: Mon, 18 Aug 2025 13:37:13 +0000 Subject: [PATCH 14/19] =?UTF-8?q?=5F=5Ftypeof=E3=81=AB=E5=A4=89=E3=81=88?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/utils/types/try.hpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/lib/utils/types/try.hpp b/src/lib/utils/types/try.hpp index 082f1e42..9d86832b 100644 --- a/src/lib/utils/types/try.hpp +++ b/src/lib/utils/types/try.hpp @@ -14,8 +14,6 @@ types::None tryDefault(const Option &) { return None; } -#ifdef __clang__ -// typeof(expr) は式を評価しないので、全体として一回だけ expr が評価される #define TRY(expr) \ ({ \ __typeof(expr) e = (expr); /* NOLINT(*-unnecessary-copy-initialization) */ \ @@ -29,21 +27,5 @@ types::None tryDefault(const Option &) { if (!(e).canUnwrap()) return defaultValue; \ (e).unwrap(); \ }) -#else -#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(); \ - }) -#endif - #endif From 5858db074f2245953814f3c43d40fa9e06d3fae1 Mon Sep 17 00:00:00 2001 From: smatsuodev Date: Mon, 18 Aug 2025 13:39:05 +0000 Subject: [PATCH 15/19] remove -Werror from cmake --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e0c2b83..70e09434 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ project(webserv) # 指定したバージョンが使用できなければエラー set(CMAKE_CXX_STANDARD_REQUIRED ON) -add_compile_options(-Wall -Wextra -Werror) +add_compile_options(-Wall -Wextra) if (CMAKE_BUILD_TYPE STREQUAL "Debug") add_compile_options(-fno-omit-frame-pointer -fsanitize=address,undefined) add_link_options(-fsanitize=address,undefined) From c9f7355eaa78c408eda2a95742160eb0ae80a67c Mon Sep 17 00:00:00 2001 From: Kentaro Mizuki <66548698+harsssh@users.noreply.github.com> Date: Mon, 18 Aug 2025 23:10:17 +0900 Subject: [PATCH 16/19] chore --- src/lib/core/action/run_cgi_action.cpp | 2 +- src/lib/core/child_reaper.cpp | 2 +- src/lib/http/request/reader/reading_chunked_body_state.cpp | 2 +- src/lib/utils/types/option.hpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/core/action/run_cgi_action.cpp b/src/lib/core/action/run_cgi_action.cpp index 44f7ede7..17019e09 100644 --- a/src/lib/core/action/run_cgi_action.cpp +++ b/src/lib/core/action/run_cgi_action.cpp @@ -136,6 +136,6 @@ void RunCgiAction::parentRoutine(const ActionContext &ctx, const int socketFd, c ctx.getState().getEventHandlerRepository().remove(clientFd_, Event::kRead); ctx.getState().getEventHandlerRepository().remove(clientFd_, Event::kWrite); - CgiProcessRepository::Data data = {clientFd_, socketFd}; + const CgiProcessRepository::Data data = {clientFd_, socketFd}; ctx.getState().getCgiProcessRepository().set(childPid, data); } diff --git a/src/lib/core/child_reaper.cpp b/src/lib/core/child_reaper.cpp index c459a99c..322e3455 100644 --- a/src/lib/core/child_reaper.cpp +++ b/src/lib/core/child_reaper.cpp @@ -13,7 +13,7 @@ std::vector ChildReaper::onSignalEvent() const { while (true) { int status = 0; const pid_t pid = waitpid(-1, &status, WNOHANG); - ReapedProcess rp = {pid, WEXITSTATUS(status)}; + const ReapedProcess rp = {pid, WEXITSTATUS(status)}; result.push_back(rp); if (pid > 0) { 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 9abee6a4..c48d7e82 100644 --- a/src/lib/http/request/reader/reading_chunked_body_state.cpp +++ b/src/lib/http/request/reader/reading_chunked_body_state.cpp @@ -78,7 +78,7 @@ namespace http { ctx_.setBody(body_); ctx_.changeState(NULL); - return Ok(kHandleDone); + return Ok(kHandleDone); } Result ReadingChunkedBodyState::parseChunkSizeLine(const std::string &line) { diff --git a/src/lib/utils/types/option.hpp b/src/lib/utils/types/option.hpp index d271e181..1ffa14c1 100644 --- a/src/lib/utils/types/option.hpp +++ b/src/lib/utils/types/option.hpp @@ -87,7 +87,7 @@ types::Some Some(T val) { } // ReSharper disable once CppInconsistentNaming -const types::None None = types::None(); // NOLINT +const types::None None = types::None(); template class Option { From 00262020eb233248c7317c5123074409a5bc51de Mon Sep 17 00:00:00 2001 From: Kentaro Mizuki <66548698+harsssh@users.noreply.github.com> Date: Sun, 24 Aug 2025 15:25:15 +0900 Subject: [PATCH 17/19] =?UTF-8?q?auto=20=E4=BD=BF=E3=81=86=E3=81=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/core/handler/read_request_handler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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(); From 09f6eb837a79ef168c3a939d1e5c7940b1edfe16 Mon Sep 17 00:00:00 2001 From: Kentaro Mizuki <66548698+harsssh@users.noreply.github.com> Date: Sun, 24 Aug 2025 15:26:10 +0900 Subject: [PATCH 18/19] =?UTF-8?q?log=20level=20=E3=82=92=E9=AB=98=E3=82=81?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cmd/main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cmd/main.cpp b/src/cmd/main.cpp index 3e2c5fbb..6792bd98 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::kWarn); + const Option config = Config::loadConfigFromFile(argv[1]); if (config.isNone()) { return 1; From 83ee89b385200009504fd4afb1b343d8d5dd9740 Mon Sep 17 00:00:00 2001 From: Kentaro Mizuki <66548698+harsssh@users.noreply.github.com> Date: Sun, 24 Aug 2025 15:30:01 +0900 Subject: [PATCH 19/19] =?UTF-8?q?log=20level=20=E3=82=92=E8=AA=BF=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cmd/main.cpp | 2 +- src/lib/core/handler/read_cgi_response_handler.cpp | 3 ++- src/lib/event/event_notifier.cpp | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/cmd/main.cpp b/src/cmd/main.cpp index 6792bd98..0a5d8bb9 100644 --- a/src/cmd/main.cpp +++ b/src/cmd/main.cpp @@ -10,7 +10,7 @@ int main(const int argc, char *argv[]) { return 1; } - SET_LOG_LEVEL(Logger::kWarn); + SET_LOG_LEVEL(Logger::kInfo); const Option config = Config::loadConfigFromFile(argv[1]); if (config.isNone()) { diff --git a/src/lib/core/handler/read_cgi_response_handler.cpp b/src/lib/core/handler/read_cgi_response_handler.cpp index a5773ced..fe0c9b32 100644 --- a/src/lib/core/handler/read_cgi_response_handler.cpp +++ b/src/lib/core/handler/read_cgi_response_handler.cpp @@ -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()); 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); }