From 84476f75f7efa7f46b0c1e521bc9856d9cb95ef9 Mon Sep 17 00:00:00 2001 From: Chunting Gu Date: Mon, 7 Sep 2020 19:01:31 +0800 Subject: [PATCH] switch back to boost::filesystem to avoid the requirement of c++17 --- CMakeLists.txt | 4 +-- README.md | 2 +- autotest/client_autotest.cc | 35 +++++++++++++------------- autotest/main.cc | 2 -- doc/Build-Instructions.md | 2 +- doc/Build-on-Linux.md | 29 +++++---------------- doc/Build-on-Mac.md | 39 ++++------------------------- doc/Build-on-Windows.md | 4 +-- examples/book_client/book_client.cc | 15 +++++------ examples/book_client/book_client.h | 9 ++++--- examples/book_client/main.cc | 10 +++++--- examples/book_server/main.cc | 16 ++++++------ examples/book_server/views.cc | 20 +++++++++------ examples/book_server/views.h | 10 ++++---- examples/form_client.cc | 9 ++++--- webcc/body.cc | 18 +++++++------ webcc/body.h | 18 +++++++------ webcc/common.cc | 5 ++-- webcc/common.h | 7 +++--- webcc/logger.cc | 23 +++++++++-------- webcc/logger.h | 9 ++----- webcc/parser.cc | 8 ++++-- webcc/parser.h | 8 +++--- webcc/request_builder.cc | 6 +++-- webcc/request_builder.h | 7 +++--- webcc/response_builder.cc | 4 ++- webcc/response_builder.h | 4 ++- webcc/server.cc | 12 +++++---- webcc/server.h | 7 +++--- webcc/utility.cc | 13 ++++++---- webcc/utility.h | 12 +++------ 31 files changed, 175 insertions(+), 192 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c30af6d..d2f92d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,14 +41,14 @@ if(WIN32) endif() # C++ standard requirements. -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) # Boost set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) -find_package(Boost 1.66.0 REQUIRED COMPONENTS system date_time) +find_package(Boost 1.66.0 REQUIRED COMPONENTS system date_time filesystem) if(Boost_FOUND) message(STATUS "Boost version: ${Boost_VERSION}") include_directories(${Boost_INCLUDE_DIRS}) diff --git a/README.md b/README.md index 02ab738..37022ae 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [__中文版 README__](README_zh_CN.md) -Lightweight C++ HTTP __client and server__ library based on [Asio](https://www.boost.org/doc/libs/release/libs/asio/) for __embedding__ purpose. +Lightweight C++ HTTP __client and server__ library based on [Boost Asio](https://www.boost.org/doc/libs/release/libs/asio/) for __embedding__ purpose. => [Build Instructions](doc/Build-Instructions.md) diff --git a/autotest/client_autotest.cc b/autotest/client_autotest.cc index 16ca404..62a89fa 100644 --- a/autotest/client_autotest.cc +++ b/autotest/client_autotest.cc @@ -1,7 +1,9 @@ -#include #include #include +#include "boost/filesystem/fstream.hpp" +#include "boost/filesystem/operations.hpp" + #include "gtest/gtest.h" #include "json/json.h" @@ -9,7 +11,7 @@ #include "webcc/client_session.h" #include "webcc/string.h" -namespace sfs = std::filesystem; +namespace bfs = boost::filesystem; // ----------------------------------------------------------------------------- @@ -194,15 +196,15 @@ TEST(ClientTest, Get_Jpeg_Stream) { EXPECT_TRUE(!file_body->path().empty()); // Backup the path of the temp file. - const sfs::path ori_path = file_body->path(); + const bfs::path ori_path = file_body->path(); - const sfs::path new_path("./wolf.jpeg"); + const bfs::path new_path("./wolf.jpeg"); bool moved = file_body->Move(new_path); EXPECT_TRUE(moved); - EXPECT_TRUE(sfs::exists(new_path)); + EXPECT_TRUE(bfs::exists(new_path)); // The file in the original path should not exist any more. - EXPECT_TRUE(!sfs::exists(ori_path)); + EXPECT_TRUE(!bfs::exists(ori_path)); // After move, the original path should be reset. EXPECT_TRUE(file_body->path().empty()); @@ -218,7 +220,7 @@ TEST(ClientTest, Get_Jpeg_Stream_NoMove) { webcc::ClientSession session; try { - sfs::path ori_path; + bfs::path ori_path; { auto r = session.Send(webcc::RequestBuilder{}. @@ -236,7 +238,7 @@ TEST(ClientTest, Get_Jpeg_Stream_NoMove) { } // The temp file should be deleted. - EXPECT_TRUE(!sfs::exists(ori_path)); + EXPECT_TRUE(!bfs::exists(ori_path)); } catch (const webcc::Error& error) { std::cerr << error << std::endl; @@ -309,23 +311,22 @@ TEST(ClientTest, Post) { } } -static sfs::path GenerateTempFile(const std::string& data) { +static bfs::path GenerateTempFile(const std::string& data) { try { - sfs::path path = - sfs::temp_directory_path() / webcc::random_string(10); + bfs::path path = bfs::temp_directory_path() / webcc::random_string(10); - std::ofstream ofs; + bfs::ofstream ofs; ofs.open(path, std::ios::binary); if (ofs.fail()) { - return sfs::path{}; + return bfs::path{}; } ofs << data; return path; - } catch (const sfs::filesystem_error&) { - return sfs::path{}; + } catch (const bfs::filesystem_error&) { + return bfs::path{}; } } @@ -356,8 +357,8 @@ TEST(ClientTest, Post_FileBody) { } // Remove the temp file. - std::error_code ec; - sfs::remove(path, ec); + boost::system::error_code ec; + bfs::remove(path, ec); } #if WEBCC_ENABLE_GZIP diff --git a/autotest/main.cc b/autotest/main.cc index 370cb1a..7ee7577 100644 --- a/autotest/main.cc +++ b/autotest/main.cc @@ -1,5 +1,3 @@ -#include - #include "gtest/gtest.h" #include "webcc/logger.h" diff --git a/doc/Build-Instructions.md b/doc/Build-Instructions.md index c3eac63..57dac80 100644 --- a/doc/Build-Instructions.md +++ b/doc/Build-Instructions.md @@ -2,7 +2,7 @@ ## Dependencies -* [Boost 1.66+](https://www.boost.org/) (asio, system, date_time) +* [Boost 1.66+](https://www.boost.org/) (asio, system, date_time, filesystem) * [OpenSSL](https://www.openssl.org/) (for HTTPS, optional) * [Zlib](https://www.zlib.net/) (for GZIP compression, optional) * [Googletest/gtest](https://github.com/google/googletest) (for automation and unit tests, optional) diff --git a/doc/Build-on-Linux.md b/doc/Build-on-Linux.md index 404e6de..95dedcb 100644 --- a/doc/Build-on-Linux.md +++ b/doc/Build-on-Linux.md @@ -2,8 +2,6 @@ _For Ubuntu based Linux distributions._ -_NOTE: The usage of C++17 `filesystem` library requires GCC to be version 8 and above. It means that Webcc will not compile on Ubuntu LTS 18.04._ - ## Install Build Essential ``` @@ -12,9 +10,7 @@ sudo apt install build-essential ## Install CMake -``` -sudo apt install cmake -``` +Please refer to https://apt.kitware.com/. ## Install Zlib & OpenSSL @@ -26,11 +22,11 @@ sudo apt install zlib1g-dev libssl-dev Download the `.tar.bz2` or `.tar.gz` from [here](https://www.boost.org/users/download/#live). -Unpack and go into the directory (suppose Boost version is 1.70): +Unpack and go into the directory (suppose Boost version is 1.74): ``` -tar -xzf boost_1_70_0.tar.bz2 -cd boost_1_70_0 +tar -xzf boost_1_74_0.tar.bz2 +cd boost_1_74_0 ``` Run `bootstrap.sh` to generate `b2`: @@ -44,7 +40,7 @@ You can change install prefix with `--prefix` (default is `/usr/local`, need `su Build and install: ``` -sudo ./b2 --with-system --with-date_time variant=debug link=static threading=multi -j4 install +sudo ./b2 --with-system --with-date_time --with-filesystem variant=debug link=static threading=multi -j4 install ``` Notes: @@ -91,7 +87,7 @@ cmake -G"Unix Makefiles" \ -DWEBCC_ENABLE_GZIP=1 \ -DWEBCC_ENABLE_AUTOTEST=OFF \ -DWEBCC_ENABLE_UNITTEST=OFF \ - -DWEBCC_ENABLE_EXAMPLES=OFF \ + -DWEBCC_ENABLE_EXAMPLES=ON \ .. ``` @@ -108,16 +104,3 @@ make -j4 ``` The number after `-j` depends on how many CPU cores you have. You can just ignore `-j` option. - -Install the libraries: - -```bash -make install -``` - -If `WEBCC_ENABLE_AUTOTEST` was `ON`, you can run the automation test: - -``` -cd autotest -./webcc_autotest -``` diff --git a/doc/Build-on-Mac.md b/doc/Build-on-Mac.md index e4db0a8..a1a305f 100644 --- a/doc/Build-on-Mac.md +++ b/doc/Build-on-Mac.md @@ -12,11 +12,11 @@ Download the .dmg from [here](https://cmake.org/download/). Just double click an Download the .tar.bz2 or .tar.gz from [here](https://www.boost.org/users/download/#live). -Unpack and go into the directory (suppose Boost version is 1.70): +Unpack and go into the directory (suppose Boost version is 1.74): ``` -tar -xzf boost_1_70_0.tar.bz2 -cd boost_1_70_0 +tar -xzf boost_1_74_0.tar.bz2 +cd boost_1_74_0 ``` Run `bootstrap.sh` to generate `b2`: @@ -30,7 +30,7 @@ You can change install prefix with `--prefix` option (default is `/usr/local`, n Build and install: ``` -sudo ./b2 --with-system --with-date_time variant=debug link=static threading=multi -j4 install +sudo ./b2 --with-system --with-date_time --with-filesystem variant=debug link=static threading=multi -j4 install ``` Notes: @@ -53,6 +53,7 @@ The libraries are installed to `/usr/local/lib`. E.g., $ ls -l /usr/local/lib/libboost* -rw-r--r-- 1 adam admin 540288 Apr 21 11:01 /usr/local/lib/libboost_date_time.a -rw-r--r-- 1 root admin 2976 Apr 21 11:01 /usr/local/lib/libboost_system.a +... ``` The headers are installed to `/usr/local/include/boost`. @@ -115,33 +116,3 @@ Open Terminal, go to the build directory, run `make`. E.g., $ cd github/webcc_build $ make -j4 ``` - -There might be some warnings, just ignore them. - -Suppose you have checked `WEBCC_ENABLE_AUTOTEST` during the configuration, you can run it now. - -``` -$ cd autotest -$ ./webcc_autotest -[==========] Running 7 tests from 1 test case. -[----------] Global test environment set-up. -[----------] 7 tests from ClientTest -[ RUN ] ClientTest.Get_RequestFunc -[ OK ] ClientTest.Get_RequestFunc (1066 ms) -[ RUN ] ClientTest.Get_Shortcut -[ OK ] ClientTest.Get_Shortcut (1844 ms) -[ RUN ] ClientTest.Get_SSL -[ OK ] ClientTest.Get_SSL (2158 ms) -[ RUN ] ClientTest.Compression_Gzip -[ OK ] ClientTest.Compression_Gzip (913 ms) -[ RUN ] ClientTest.Compression_Deflate -[ OK ] ClientTest.Compression_Deflate (921 ms) -[ RUN ] ClientTest.KeepAlive -[ OK ] ClientTest.KeepAlive (5121 ms) -[ RUN ] ClientTest.GetImageJpeg -[ OK ] ClientTest.GetImageJpeg (1244 ms) -[----------] 7 tests from ClientTest (13267 ms total) -[----------] Global test environment tear-down -[==========] 7 tests from 1 test case ran. (13267 ms total) -[ PASSED ] 7 tests. -``` diff --git a/doc/Build-on-Windows.md b/doc/Build-on-Windows.md index ebd2b66..2f9d760 100644 --- a/doc/Build-on-Windows.md +++ b/doc/Build-on-Windows.md @@ -15,12 +15,12 @@ In the prompt, `cd` to the Boost root directory. Run `bootstrap.bat` to generate Run `b2.exe` to start the build: ``` -b2 --with-system --with-date_time variant=debug variant=release link=static threading=multi address-model=64 stage +b2 --with-system --with-date_time --with-filesystem variant=debug variant=release link=static threading=multi address-model=64 stage ``` NOTE: Given `address-model=64` `b2.exe` will not build any x86 libraries. -As you can see, we only need to build `system` and `date_time` which are used by Asio. Asio itself is a header-only library. +As you can see, we only need to build `system`, `date_time` and `filesystem`. Asio itself is a header-only library. We don't install Boost to any other place (e.g., `C:\Boost`). We just `stage` it where it is. diff --git a/examples/book_client/book_client.cc b/examples/book_client/book_client.cc index 7e779a8..069fcc0 100644 --- a/examples/book_client/book_client.cc +++ b/examples/book_client/book_client.cc @@ -2,12 +2,16 @@ #include +#include "boost/filesystem/operations.hpp" + #include "json/json.h" #include "webcc/string.h" #include "book_json.h" +namespace bfs = boost::filesystem; + BookClient::BookClient(const std::string& url, int timeout) : url_(url), session_(timeout) { // Default Content-Type for requests with a body. @@ -124,8 +128,7 @@ bool BookClient::Delete(const std::string& id) { } } -bool BookClient::GetPhoto(const std::string& id, - const std::filesystem::path& path) { +bool BookClient::GetPhoto(const std::string& id, const bfs::path& path) { try { auto r = session_.Send(WEBCC_GET(url_). Path("books").Path(id).Path("photo")(), @@ -145,8 +148,7 @@ bool BookClient::GetPhoto(const std::string& id, } } -bool BookClient::SetPhoto(const std::string& id, - const std::filesystem::path& path) { +bool BookClient::SetPhoto(const std::string& id, const bfs::path& path) { try { if (!CheckPhoto(path)) { return false; @@ -168,13 +170,12 @@ bool BookClient::SetPhoto(const std::string& id, } } -bool BookClient::CheckPhoto(const std::filesystem::path& photo) { +bool BookClient::CheckPhoto(const bfs::path& photo) { if (photo.empty()) { return false; } - if (!std::filesystem::is_regular_file(photo) || - !std::filesystem::exists(photo)) { + if (!bfs::is_regular_file(photo) || !bfs::exists(photo)) { return false; } diff --git a/examples/book_client/book_client.h b/examples/book_client/book_client.h index 1ed6207..a152839 100644 --- a/examples/book_client/book_client.h +++ b/examples/book_client/book_client.h @@ -1,10 +1,11 @@ #ifndef BOOK_CLIENT_H_ #define BOOK_CLIENT_H_ -#include #include #include +#include "boost/filesystem/path.hpp" + #include "json/json-forwards.h" #include "webcc/client_session.h" @@ -28,13 +29,13 @@ public: bool Delete(const std::string& id); // Get photo, save to the given path. - bool GetPhoto(const std::string& id, const std::filesystem::path& path); + bool GetPhoto(const std::string& id, const boost::filesystem::path& path); // Set photo using the file of the given path. - bool SetPhoto(const std::string& id, const std::filesystem::path& path); + bool SetPhoto(const std::string& id, const boost::filesystem::path& path); private: - bool CheckPhoto(const std::filesystem::path& photo); + bool CheckPhoto(const boost::filesystem::path& photo); // Check HTTP response status. bool CheckStatus(webcc::ResponsePtr response, int expected_status); diff --git a/examples/book_client/main.cc b/examples/book_client/main.cc index 4d1c3cf..4c90aed 100644 --- a/examples/book_client/main.cc +++ b/examples/book_client/main.cc @@ -1,10 +1,13 @@ -#include #include +#include "boost/filesystem/operations.hpp" + #include "webcc/logger.h" #include "book_client.h" +namespace bfs = boost::filesystem; + // ----------------------------------------------------------------------------- void PrintSeparator() { @@ -36,9 +39,8 @@ int main(int argc, char* argv[]) { std::string url = argv[1]; - std::filesystem::path photo_dir = argv[2]; - if (!std::filesystem::is_directory(photo_dir) || - !std::filesystem::exists(photo_dir)) { + bfs::path photo_dir = argv[2]; + if (!bfs::is_directory(photo_dir) || !bfs::exists(photo_dir)) { std::cerr << "Invalid photo dir!" << std::endl; return 1; } diff --git a/examples/book_server/main.cc b/examples/book_server/main.cc index 18b58b4..9d06dc9 100644 --- a/examples/book_server/main.cc +++ b/examples/book_server/main.cc @@ -1,11 +1,14 @@ -#include #include +#include "boost/filesystem/operations.hpp" + #include "webcc/logger.h" #include "webcc/server.h" #include "views.h" +namespace bfs = boost::filesystem; + int main(int argc, char* argv[]) { if (argc < 3) { std::cout << "usage: book_server " << std::endl; @@ -18,17 +21,16 @@ int main(int argc, char* argv[]) { std::uint16_t port = static_cast(std::atoi(argv[1])); - std::filesystem::path upload_dir = argv[2]; - if (!std::filesystem::is_directory(upload_dir) || - !std::filesystem::exists(upload_dir)) { + bfs::path upload_dir = argv[2]; + if (!bfs::is_directory(upload_dir) || !bfs::exists(upload_dir)) { std::cerr << "Invalid upload dir!" << std::endl; return 1; } // Add a sub-dir for book photos. - std::filesystem::path photo_dir = upload_dir / "books"; - if (!std::filesystem::exists(photo_dir)) { - std::filesystem::create_directory(photo_dir); + bfs::path photo_dir = upload_dir / "books"; + if (!bfs::exists(photo_dir)) { + bfs::create_directory(photo_dir); } std::cout << "Book photos will be saved to: " << photo_dir << std::endl; diff --git a/examples/book_server/views.cc b/examples/book_server/views.cc index 8fc3541..cc59b01 100644 --- a/examples/book_server/views.cc +++ b/examples/book_server/views.cc @@ -1,5 +1,7 @@ #include "views.h" +#include "boost/filesystem/operations.hpp" + #include "json/json.h" #include "webcc/response_builder.h" @@ -8,6 +10,8 @@ #include "book_db.h" #include "book_json.h" +namespace bfs = boost::filesystem; + // ----------------------------------------------------------------------------- static BookDB g_book_db; @@ -53,7 +57,7 @@ webcc::ResponsePtr BookListView::Post(webcc::RequestPtr request) { // ----------------------------------------------------------------------------- -BookDetailView::BookDetailView(std::filesystem::path photo_dir) +BookDetailView::BookDetailView(bfs::path photo_dir) : photo_dir_(std::move(photo_dir)) { } @@ -121,8 +125,8 @@ webcc::ResponsePtr BookDetailView::Delete(webcc::RequestPtr request) { // Delete the photo from file system. if (!photo_name.empty()) { - std::error_code ec; - std::filesystem::remove(photo_dir_ / photo_name, ec); + boost::system::error_code ec; + bfs::remove(photo_dir_ / photo_name, ec); } return webcc::ResponseBuilder{}.OK()(); @@ -130,7 +134,7 @@ webcc::ResponsePtr BookDetailView::Delete(webcc::RequestPtr request) { // ----------------------------------------------------------------------------- -BookPhotoView::BookPhotoView(std::filesystem::path photo_dir) +BookPhotoView::BookPhotoView(bfs::path photo_dir) : photo_dir_(std::move(photo_dir)) { } @@ -160,8 +164,8 @@ webcc::ResponsePtr BookPhotoView::Get(webcc::RequestPtr request) { return webcc::ResponseBuilder{}.NotFound()(); } - std::filesystem::path photo_path = photo_dir_ / book.photo; - if (!std::filesystem::exists(photo_path)) { + bfs::path photo_path = photo_dir_ / book.photo; + if (!bfs::exists(photo_path)) { return webcc::ResponseBuilder{}.NotFound()(); } @@ -215,8 +219,8 @@ webcc::ResponsePtr BookPhotoView::Delete(webcc::RequestPtr request) { } // Error handling is simplified. - std::error_code ec; - std::filesystem::remove(photo_dir_ / book.photo, ec); + boost::system::error_code ec; + bfs::remove(photo_dir_ / book.photo, ec); return webcc::ResponseBuilder{}.OK()(); } diff --git a/examples/book_server/views.h b/examples/book_server/views.h index 9e3bc67..f7f81f5 100644 --- a/examples/book_server/views.h +++ b/examples/book_server/views.h @@ -1,7 +1,7 @@ #ifndef VIEWS_H_ #define VIEWS_H_ -#include +#include "boost/filesystem/path.hpp" #include "webcc/view.h" @@ -25,7 +25,7 @@ private: // URL: /books/{id} class BookDetailView : public webcc::View { public: - explicit BookDetailView(std::filesystem::path photo_dir); + explicit BookDetailView(boost::filesystem::path photo_dir); webcc::ResponsePtr Handle(webcc::RequestPtr request) override; @@ -40,7 +40,7 @@ private: webcc::ResponsePtr Delete(webcc::RequestPtr request); private: - std::filesystem::path photo_dir_; + boost::filesystem::path photo_dir_; }; // ----------------------------------------------------------------------------- @@ -48,7 +48,7 @@ private: // URL: /books/{id}/photo class BookPhotoView : public webcc::View { public: - explicit BookPhotoView(std::filesystem::path photo_dir); + explicit BookPhotoView(boost::filesystem::path photo_dir); webcc::ResponsePtr Handle(webcc::RequestPtr request) override; @@ -68,7 +68,7 @@ private: webcc::ResponsePtr Delete(webcc::RequestPtr request); private: - std::filesystem::path photo_dir_; + boost::filesystem::path photo_dir_; }; #endif // VIEWS_H_ diff --git a/examples/form_client.cc b/examples/form_client.cc index 3d30c71..d76b8cd 100644 --- a/examples/form_client.cc +++ b/examples/form_client.cc @@ -1,12 +1,13 @@ // A client posting multipart form data. -#include #include +#include "boost/filesystem/operations.hpp" + #include "webcc/client_session.h" #include "webcc/logger.h" -namespace sfs = std::filesystem; +namespace bfs = boost::filesystem; int main(int argc, char* argv[]) { if (argc < 2) { @@ -23,7 +24,7 @@ int main(int argc, char* argv[]) { WEBCC_LOG_INIT("", webcc::LOG_CONSOLE); - const sfs::path upload_dir(argv[1]); + const bfs::path upload_dir(argv[1]); std::string url; if (argc == 3) { @@ -32,7 +33,7 @@ int main(int argc, char* argv[]) { url = "http://httpbin.org/post"; } - if (!sfs::is_directory(upload_dir) || !sfs::exists(upload_dir)) { + if (!bfs::is_directory(upload_dir) || !bfs::exists(upload_dir)) { std::cerr << "Invalid upload dir!" << std::endl; return 1; } diff --git a/webcc/body.cc b/webcc/body.cc index d4cadb8..0407cdf 100644 --- a/webcc/body.cc +++ b/webcc/body.cc @@ -1,5 +1,7 @@ #include "webcc/body.h" +#include "boost/filesystem/operations.hpp" + #include "webcc/logger.h" #include "webcc/utility.h" @@ -7,6 +9,8 @@ #include "webcc/gzip.h" #endif +namespace bfs = boost::filesystem; + namespace webcc { // ----------------------------------------------------------------------------- @@ -153,7 +157,7 @@ void FormBody::Free(std::size_t index) { // ----------------------------------------------------------------------------- -FileBody::FileBody(const std::filesystem::path& path, std::size_t chunk_size) +FileBody::FileBody(const bfs::path& path, std::size_t chunk_size) : path_(path), chunk_size_(chunk_size), auto_delete_(false), size_(0) { size_ = utility::TellSize(path_); if (size_ == kInvalidLength) { @@ -161,15 +165,15 @@ FileBody::FileBody(const std::filesystem::path& path, std::size_t chunk_size) } } -FileBody::FileBody(const std::filesystem::path& path, bool auto_delete) +FileBody::FileBody(const bfs::path& path, bool auto_delete) : path_(path), chunk_size_(0), auto_delete_(auto_delete), size_(0) { // Don't need to tell file size. } FileBody::~FileBody() { if (auto_delete_ && !path_.empty()) { - std::error_code ec; - std::filesystem::remove(path_, ec); + boost::system::error_code ec; + bfs::remove(path_, ec); if (ec) { LOG_ERRO("Failed to remove file (%s).", ec.message().c_str()); } @@ -205,7 +209,7 @@ void FileBody::Dump(std::ostream& os, const std::string& prefix) const { os << prefix << "" << std::endl; } -bool FileBody::Move(const std::filesystem::path& new_path) { +bool FileBody::Move(const bfs::path& new_path) { if (path_ == new_path) { return false; } @@ -214,8 +218,8 @@ bool FileBody::Move(const std::filesystem::path& new_path) { ifstream_.close(); } - std::error_code ec; - std::filesystem::rename(path_, new_path, ec); + boost::system::error_code ec; + bfs::rename(path_, new_path, ec); if (ec) { LOG_ERRO("Failed to rename file (%s).", ec.message().c_str()); diff --git a/webcc/body.h b/webcc/body.h index e1c8584..c87528d 100644 --- a/webcc/body.h +++ b/webcc/body.h @@ -1,12 +1,14 @@ #ifndef WEBCC_BODY_H_ #define WEBCC_BODY_H_ -#include #include #include #include #include +#include "boost/filesystem/fstream.hpp" +#include "boost/filesystem/path.hpp" + #include "webcc/common.h" namespace webcc { @@ -152,14 +154,14 @@ private: class FileBody : public Body { public: // For message to be sent out. - FileBody(const std::filesystem::path& path, std::size_t chunk_size); + FileBody(const boost::filesystem::path& path, std::size_t chunk_size); // For message received. // No |chunk_size| is needed since you don't iterate the payload of a // received message. // If |auto_delete| is true, the file will be deleted on destructor unless it // is moved to another path (see Move()). - FileBody(const std::filesystem::path& path, bool auto_delete = false); + FileBody(const boost::filesystem::path& path, bool auto_delete = false); ~FileBody() override; @@ -173,7 +175,7 @@ public: void Dump(std::ostream& os, const std::string& prefix) const override; - const std::filesystem::path& path() const { + const boost::filesystem::path& path() const { return path_; } @@ -186,17 +188,17 @@ public: // If |new_path| resolves to an existing non-directory file, it is removed. // If |new_path| resolves to an existing directory, it is removed if empty // on ISO/IEC 9945 but is an error on Windows. - // See std::filesystem::rename() for more details. - bool Move(const std::filesystem::path& new_path); + // See boost::filesystem::rename() for more details. + bool Move(const boost::filesystem::path& new_path); private: - std::filesystem::path path_; + boost::filesystem::path path_; std::size_t chunk_size_; bool auto_delete_; std::size_t size_; // File size in bytes - std::ifstream ifstream_; + boost::filesystem::ifstream ifstream_; std::string chunk_; }; diff --git a/webcc/common.cc b/webcc/common.cc index e87acf1..2860278 100644 --- a/webcc/common.cc +++ b/webcc/common.cc @@ -6,6 +6,8 @@ #include "webcc/string.h" #include "webcc/utility.h" +namespace bfs = boost::filesystem; + namespace webcc { // ----------------------------------------------------------------------------- @@ -190,8 +192,7 @@ FormPartPtr FormPart::New(const std::string& name, std::string&& data, return form_part; } -FormPartPtr FormPart::NewFile(const std::string& name, - const std::filesystem::path& path, +FormPartPtr FormPart::NewFile(const std::string& name, const bfs::path& path, const std::string& media_type) { auto form_part = std::make_shared(); diff --git a/webcc/common.h b/webcc/common.h index 0a01266..c60d5a1 100644 --- a/webcc/common.h +++ b/webcc/common.h @@ -2,11 +2,12 @@ #define WEBCC_COMMON_H_ #include -#include #include #include #include +#include "boost/filesystem/path.hpp" + #include "webcc/globals.h" namespace webcc { @@ -158,7 +159,7 @@ public: // The file name will be extracted from path. // The media type, if not provided, will be inferred from file extension. static FormPartPtr NewFile(const std::string& name, - const std::filesystem::path& path, + const boost::filesystem::path& path, const std::string& media_type = ""); // API: SERVER @@ -229,7 +230,7 @@ private: std::string name_; // The path of the file to post. - std::filesystem::path path_; + boost::filesystem::path path_; // The original local file name. // E.g., "baby.jpg". diff --git a/webcc/logger.cc b/webcc/logger.cc index 3f2c7e3..a10439e 100644 --- a/webcc/logger.cc +++ b/webcc/logger.cc @@ -6,7 +6,6 @@ #include #include #include -#include #include // for put_time #include #include @@ -21,6 +20,10 @@ #include #endif +#include "boost/filesystem/operations.hpp" + +namespace bfs = boost::filesystem; + namespace webcc { // ----------------------------------------------------------------------------- @@ -33,7 +36,7 @@ static const char* kLevelNames[] = { // ----------------------------------------------------------------------------- -static FILE* FOpen(const std::filesystem::path& path, bool overwrite) { +static FILE* FOpen(const bfs::path& path, bool overwrite) { #if (defined(_WIN32) || defined(_WIN64)) return _wfopen(path.wstring().c_str(), overwrite ? L"w+" : L"a+"); #else @@ -45,7 +48,7 @@ struct Logger { Logger() : file(nullptr), modes(0) { } - void Init(const std::filesystem::path& path, int _modes) { + void Init(const bfs::path& path, int _modes) { modes = _modes; // Create log file only if necessary. @@ -153,22 +156,22 @@ static std::string GetThreadID() { return thread_id; } -static std::filesystem::path InitLogPath(const std::filesystem::path& dir) { +static bfs::path InitLogPath(const bfs::path& dir) { if (dir.empty()) { - return std::filesystem::current_path() / WEBCC_LOG_FILE_NAME; + return bfs::current_path() / WEBCC_LOG_FILE_NAME; } - if (!std::filesystem::exists(dir) || !std::filesystem::is_directory(dir)) { - std::error_code ec; - if (!std::filesystem::create_directories(dir, ec) || ec) { - return std::filesystem::path{}; + if (!bfs::exists(dir) || !bfs::is_directory(dir)) { + boost::system::error_code ec; + if (!bfs::create_directories(dir, ec) || ec) { + return bfs::path{}; } } return (dir / WEBCC_LOG_FILE_NAME); } -void LogInit(const std::filesystem::path& dir, int modes) { +void LogInit(const bfs::path& dir, int modes) { // Suppose this is called from the main thread. g_main_thread_id = DoGetThreadID(); diff --git a/webcc/logger.h b/webcc/logger.h index c2461aa..d106233 100644 --- a/webcc/logger.h +++ b/webcc/logger.h @@ -9,12 +9,7 @@ #include // for strrchr() #include -// Avoid include in the header. -namespace std { -namespace filesystem { -class path; -} // namespace filesystem -} // namespace std +#include "boost/filesystem/path.hpp" // Log levels. // VERB is similar to DEBUG commonly used by other projects. @@ -49,7 +44,7 @@ const int LOG_FILE_OVERWRITE = LOG_FILE | LOG_OVERWRITE; // Initialize logger. // If |dir| is empty, log file will be generated in current directory. -void LogInit(const std::filesystem::path& dir, int modes); +void LogInit(const boost::filesystem::path& dir, int modes); void Log(int level, const char* file, int line, const char* format, ...); diff --git a/webcc/parser.cc b/webcc/parser.cc index beba2a0..c6807bf 100644 --- a/webcc/parser.cc +++ b/webcc/parser.cc @@ -1,5 +1,7 @@ #include "webcc/parser.h" +#include "boost/filesystem/operations.hpp" + #include "webcc/logger.h" #include "webcc/message.h" #include "webcc/string.h" @@ -9,6 +11,8 @@ #include "webcc/gzip.h" #endif +namespace bfs = boost::filesystem; + namespace webcc { // ----------------------------------------------------------------------------- @@ -65,7 +69,7 @@ bool StringBodyHandler::Finish() { bool FileBodyHandler::OpenFile() { try { - temp_path_ = std::filesystem::temp_directory_path(); + temp_path_ = bfs::temp_directory_path(); // Generate a random string as file name. // A replacement of boost::filesystem::unique_path(). @@ -74,7 +78,7 @@ bool FileBodyHandler::OpenFile() { LOG_VERB("Generate a temp path for streaming: %s", temp_path_.string().c_str()); - } catch (const std::filesystem::filesystem_error&) { + } catch (const bfs::filesystem_error&) { LOG_ERRO("Failed to generate temp path for streaming."); return false; } diff --git a/webcc/parser.h b/webcc/parser.h index 29c79ae..9e87b14 100644 --- a/webcc/parser.h +++ b/webcc/parser.h @@ -1,10 +1,12 @@ #ifndef WEBCC_PARSER_H_ #define WEBCC_PARSER_H_ -#include #include #include +#include "boost/filesystem/fstream.hpp" +#include "boost/filesystem/path.hpp" + #include "webcc/common.h" #include "webcc/globals.h" @@ -82,8 +84,8 @@ public: private: std::size_t streamed_size_ = 0; - std::ofstream ofstream_; - std::filesystem::path temp_path_; + boost::filesystem::ofstream ofstream_; + boost::filesystem::path temp_path_; }; // ----------------------------------------------------------------------------- diff --git a/webcc/request_builder.cc b/webcc/request_builder.cc index dc826d5..15af692 100644 --- a/webcc/request_builder.cc +++ b/webcc/request_builder.cc @@ -9,6 +9,8 @@ #include "webcc/gzip.h" #endif +namespace bfs = boost::filesystem; + namespace webcc { RequestPtr RequestBuilder::operator()() { @@ -52,7 +54,7 @@ RequestPtr RequestBuilder::operator()() { return request; } -RequestBuilder& RequestBuilder::File(const std::filesystem::path& path, +RequestBuilder& RequestBuilder::File(const bfs::path& path, bool infer_media_type, std::size_t chunk_size) { body_.reset(new FileBody{ path, chunk_size }); @@ -65,7 +67,7 @@ RequestBuilder& RequestBuilder::File(const std::filesystem::path& path, } RequestBuilder& RequestBuilder::FormFile(const std::string& name, - const std::filesystem::path& path, + const bfs::path& path, const std::string& media_type) { assert(!name.empty()); return Form(FormPart::NewFile(name, path, media_type)); diff --git a/webcc/request_builder.h b/webcc/request_builder.h index b1347d2..fa745ec 100644 --- a/webcc/request_builder.h +++ b/webcc/request_builder.h @@ -1,10 +1,11 @@ #ifndef WEBCC_REQUEST_BUILDER_H_ #define WEBCC_REQUEST_BUILDER_H_ -#include #include #include +#include "boost/filesystem/path.hpp" + #include "webcc/request.h" #include "webcc/url.h" @@ -135,7 +136,7 @@ public: // Use the file content as body. // NOTE: Error::kFileError might be thrown. - RequestBuilder& File(const std::filesystem::path& path, + RequestBuilder& File(const boost::filesystem::path& path, bool infer_media_type = true, std::size_t chunk_size = 1024); @@ -147,7 +148,7 @@ public: // Add a form part of file. RequestBuilder& FormFile(const std::string& name, - const std::filesystem::path& path, + const boost::filesystem::path& path, const std::string& media_type = ""); // Add a form part of string data. diff --git a/webcc/response_builder.cc b/webcc/response_builder.cc index 9316266..bbedf1b 100644 --- a/webcc/response_builder.cc +++ b/webcc/response_builder.cc @@ -8,6 +8,8 @@ #include "webcc/gzip.h" #endif +namespace bfs = boost::filesystem; + namespace webcc { ResponsePtr ResponseBuilder::operator()() { @@ -43,7 +45,7 @@ ResponsePtr ResponseBuilder::operator()() { return response; } -ResponseBuilder& ResponseBuilder::File(const std::filesystem::path& path, +ResponseBuilder& ResponseBuilder::File(const bfs::path& path, bool infer_media_type, std::size_t chunk_size) { body_.reset(new FileBody{ path, chunk_size }); diff --git a/webcc/response_builder.h b/webcc/response_builder.h index d35e663..955b8d6 100644 --- a/webcc/response_builder.h +++ b/webcc/response_builder.h @@ -4,6 +4,8 @@ #include #include +#include "boost/filesystem/path.hpp" + #include "webcc/request.h" #include "webcc/response.h" @@ -94,7 +96,7 @@ public: // Use the file content as body. // NOTE: Error::kFileError might be thrown. - ResponseBuilder& File(const std::filesystem::path& path, + ResponseBuilder& File(const boost::filesystem::path& path, bool infer_media_type = true, std::size_t chunk_size = 1024); diff --git a/webcc/server.cc b/webcc/server.cc index aa9de01..e9762c8 100644 --- a/webcc/server.cc +++ b/webcc/server.cc @@ -4,20 +4,22 @@ #include #include +#include "boost/filesystem/operations.hpp" + #include "webcc/body.h" #include "webcc/logger.h" #include "webcc/request.h" #include "webcc/response.h" #include "webcc/utility.h" -namespace sfs = std::filesystem; +namespace bfs = boost::filesystem; using tcp = boost::asio::ip::tcp; namespace webcc { Server::Server(boost::asio::ip::tcp protocol, std::uint16_t port, - const sfs::path& doc_root) + const bfs::path& doc_root) : protocol_(protocol), port_(port), doc_root_(doc_root), @@ -302,8 +304,8 @@ bool Server::MatchViewOrStatic(const std::string& method, // Try to match a static file. if (method == methods::kGet && !doc_root_.empty()) { - sfs::path path = doc_root_ / url; - if (!sfs::is_directory(path) && sfs::exists(path)) { + bfs::path path = doc_root_ / url; + if (!bfs::is_directory(path) && bfs::exists(path)) { return true; } } @@ -319,7 +321,7 @@ ResponsePtr Server::ServeStatic(RequestPtr request) { return {}; } - sfs::path path = doc_root_ / request->url().path(); + bfs::path path = doc_root_ / request->url().path(); try { // NOTE: FileBody might throw Error::kFileError. diff --git a/webcc/server.h b/webcc/server.h index 0106ee7..e1d0df2 100644 --- a/webcc/server.h +++ b/webcc/server.h @@ -1,11 +1,12 @@ #ifndef WEBCC_SERVER_H_ #define WEBCC_SERVER_H_ -#include #include #include #include +#include "boost/filesystem/path.hpp" + #include "boost/asio/io_context.hpp" #include "boost/asio/ip/tcp.hpp" #include "boost/asio/signal_set.hpp" @@ -21,7 +22,7 @@ namespace webcc { class Server : public Router { public: Server(boost::asio::ip::tcp protocol, std::uint16_t port, - const std::filesystem::path& doc_root = {}); + const boost::filesystem::path& doc_root = {}); ~Server() = default; @@ -101,7 +102,7 @@ private: std::uint16_t port_; // The directory with the static files to be served. - std::filesystem::path doc_root_; + boost::filesystem::path doc_root_; // The size of the chunk loaded into memory each time when serving a // static file. diff --git a/webcc/utility.cc b/webcc/utility.cc index e873244..c2d0a78 100644 --- a/webcc/utility.cc +++ b/webcc/utility.cc @@ -2,15 +2,18 @@ #include #include -#include #include #include // for put_time #include #include +#include "boost/filesystem/fstream.hpp" + #include "webcc/string.h" #include "webcc/version.h" +namespace bfs = boost::filesystem; + namespace webcc { namespace utility { @@ -49,18 +52,18 @@ std::string HttpDate() { return std::string(buf) + " GMT"; } -std::size_t TellSize(const std::filesystem::path& path) { +std::size_t TellSize(const bfs::path& path) { // Flag "ate": seek to the end of stream immediately after open. - std::ifstream stream{ path, std::ios::binary | std::ios::ate }; + bfs::ifstream stream{ path, std::ios::binary | std::ios::ate }; if (stream.fail()) { return kInvalidLength; } return static_cast(stream.tellg()); } -bool ReadFile(const std::filesystem::path& path, std::string* output) { +bool ReadFile(const bfs::path& path, std::string* output) { // Flag "ate": seek to the end of stream immediately after open. - std::ifstream stream{ path, std::ios::binary | std::ios::ate }; + bfs::ifstream stream{ path, std::ios::binary | std::ios::ate }; if (stream.fail()) { return false; } diff --git a/webcc/utility.h b/webcc/utility.h index c0e0487..f4851b8 100644 --- a/webcc/utility.h +++ b/webcc/utility.h @@ -5,16 +5,10 @@ #include #include "boost/asio/ip/tcp.hpp" +#include "boost/filesystem/path.hpp" #include "webcc/globals.h" -// Avoid include in the header. -namespace std { -namespace filesystem { -class path; -} // namespace filesystem -} // namespace std - namespace webcc { namespace utility { @@ -28,10 +22,10 @@ std::string HttpDate(); // Tell the size in bytes of the given file. // Return kInvalidLength (-1) on failure. -std::size_t TellSize(const std::filesystem::path& path); +std::size_t TellSize(const boost::filesystem::path& path); // Read entire file into string. -bool ReadFile(const std::filesystem::path& path, std::string* output); +bool ReadFile(const boost::filesystem::path& path, std::string* output); // Dump the string data line by line to achieve more readability. // Also limit the maximum size of the data to be dumped.