mirror of https://github.com/CrowCpp/Crow.git
commit
ee0e0254d2
|
@ -25,7 +25,7 @@ steps:
|
|||
- export TRAVIS_JOB_ID=$DRONE_BUILD_NUMBER
|
||||
- export COVERALLS_PULL_REQUEST=$DRONE_PULL_REQUEST
|
||||
- apt-get -y update
|
||||
- apt-get -y install libboost-all-dev doxygen mkdocs graphviz zlib1g-dev gcc clang clang-format make cmake python3 python3-pip git openssl libssl-dev jq wget curl
|
||||
- apt-get -y install libasio-dev doxygen mkdocs graphviz zlib1g-dev gcc clang clang-format make cmake python3 python3-pip git openssl libssl-dev jq wget curl
|
||||
- git clone https://github.com/CrowCpp/cpp-coveralls.git
|
||||
- cd cpp-coveralls
|
||||
- pip3 install . --no-input
|
||||
|
@ -73,7 +73,7 @@ steps:
|
|||
commands:
|
||||
- export DEBIAN_FRONTEND=noninteractive
|
||||
- apt-get -y update
|
||||
- apt-get -y install libboost-all-dev zlib1g-dev gcc clang make cmake python3 openssl libssl-dev
|
||||
- apt-get -y install libasio-dev zlib1g-dev gcc clang make cmake python3 openssl libssl-dev
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake --version
|
||||
|
@ -123,7 +123,7 @@ steps:
|
|||
- export TRAVIS_BRANCH=$DRONE_REPO_BRANCH
|
||||
- export TRAVIS_JOB_ID=$DRONE_BUILD_NUMBER
|
||||
- apt-get -y update
|
||||
- apt-get -y install libboost-all-dev doxygen mkdocs graphviz zlib1g-dev gcc clang make cmake python3 python3-pip git openssl libssl-dev
|
||||
- apt-get -y install libasio-dev doxygen mkdocs graphviz zlib1g-dev gcc clang make cmake python3 python3-pip git openssl libssl-dev
|
||||
- pip3 install mkdocs-material mkdocs-redirects pyyaml mkdocs-meta-descriptions-plugin --no-input
|
||||
- git clone https://github.com/CrowCpp/cpp-coveralls.git
|
||||
- cd cpp-coveralls
|
||||
|
@ -170,7 +170,7 @@ steps:
|
|||
commands:
|
||||
- export DEBIAN_FRONTEND=noninteractive
|
||||
- apt-get -y update
|
||||
- apt-get -y install libboost-all-dev zlib1g-dev gcc clang make cmake python3 openssl libssl-dev
|
||||
- apt-get -y install libasio-dev zlib1g-dev gcc clang make cmake python3 openssl libssl-dev
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake --version
|
||||
|
|
|
@ -28,7 +28,7 @@ env:
|
|||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libboost-all-dev
|
||||
- libasio-dev
|
||||
- doxygen
|
||||
- mkdocs
|
||||
- graphviz
|
||||
|
|
|
@ -52,14 +52,17 @@ target_include_directories(Crow
|
|||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
|
||||
find_package(Boost 1.64 COMPONENTS system date_time REQUIRED)
|
||||
find_path(ASIO_INCLUDE_DIR asio.hpp REQUIRED)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
target_link_libraries(Crow
|
||||
INTERFACE
|
||||
Boost::boost Boost::system Boost::date_time
|
||||
Threads::Threads
|
||||
)
|
||||
target_include_directories(Crow
|
||||
INTERFACE
|
||||
${ASIO_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if("compression" IN_LIST CROW_FEATURES)
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(Boost 1.64 COMPONENTS system date_time)
|
||||
find_path(ASIO_INCLUDE_DIR asio.hpp REQUIRED)
|
||||
find_dependency(Threads)
|
||||
|
||||
set(CROW_INSTALLED_FEATURES "@CROW_FEATURES@")
|
||||
|
@ -41,3 +41,8 @@ set_target_properties(Crow::Crow PROPERTIES
|
|||
INTERFACE_COMPILE_DEFINITIONS "${_CROW_ICD}"
|
||||
INTERFACE_LINK_LIBRARIES "${_CROW_ILL}"
|
||||
)
|
||||
|
||||
target_include_directories(Crow::Crow
|
||||
INTERFACE
|
||||
${ASIO_INCLUDE_DIR}
|
||||
)
|
||||
|
|
|
@ -3,7 +3,7 @@ Here's how you can install Crow on your favorite GNU/Linux distro.
|
|||
|
||||
### Requirements
|
||||
- C++ compiler with at least C++11 support.
|
||||
- boost library & development headers (1.64 or later).
|
||||
- Asio development headers (1.10.9 or later).
|
||||
- **(optional)** ZLib for HTTP Compression.
|
||||
- **(optional)** OpenSSL for HTTPS support.
|
||||
- **(optional)** CMake for building tests, examples, and/or installing Crow.
|
||||
|
@ -91,6 +91,3 @@ All you need to do is run the following command:
|
|||
g++ main.cpp -lpthread
|
||||
```
|
||||
You can use arguments like `-DCROW_ENABLE_DEBUG`, `-DCROW_ENABLE_COMPRESSION -lz` for HTTP Compression, or `-DCROW_ENABLE_SSL -lssl` for HTTPS support, or even replace g++ with clang++.
|
||||
!!! warning
|
||||
|
||||
If you're using a version of boost prior to 1.69, you'll need to add the argument `-lboost_system` in order for you Crow application to compile correctly.
|
||||
|
|
|
@ -24,20 +24,20 @@ This will generate a `crow_all.h` file which you can use in the following steps
|
|||
## Setting up your Crow project
|
||||
### Using XCode
|
||||
1. Download and install [Homebrew](https://brew.sh).
|
||||
2. Run `brew install boost` in your terminal.
|
||||
2. Run `brew install asio` in your terminal.
|
||||
3. Create a new XCode project (macOS -> Command Line Tool).
|
||||
4. Change the following project settings:
|
||||
|
||||
=== "Multiple Headers"
|
||||
|
||||
1. Add header search paths for crow's include folder and boost's folder (`/usr/local/include`, `/usr/local/Cellar/boost/include`, and where you placed Crow's `include` folder)
|
||||
2. Add linker flags (`-lpthread` and `-lboost_system` if you're running an old version of boost)
|
||||
1. Add header search paths for crow's include folder and asio's folder (`/usr/local/include`, `/usr/local/Cellar/asio/include`, and where you placed Crow's `include` folder)
|
||||
2. Add linker flags (`-lpthread`)
|
||||
|
||||
=== "Single Header"
|
||||
|
||||
1. Place `crow_all.h` inside your project folder and add it to the project in XCode (you need to use File -> Add files to "project_name")
|
||||
2. Add header search paths for boost's folder (`/usr/local/include`, and `/usr/local/Cellar/boost/include`)
|
||||
3. Add linker flags (`-lpthread` and `-lboost_system` if you're running an old version of boost)
|
||||
2. Add header search paths for asio's folder (`/usr/local/include`, and `/usr/local/Cellar/asio/include`)
|
||||
3. Add linker flags (`-lpthread`)
|
||||
|
||||
5. Write your Crow application in `main.cpp` (something like the Hello World example will work).
|
||||
6. Press `▶` to compile and run your Crow application.
|
||||
|
@ -49,7 +49,7 @@ This will generate a `crow_all.h` file which you can use in the following steps
|
|||
This tutorial can be used for Crow projects built with CMake as well
|
||||
|
||||
1. Download and install [Homebrew](https://brew.sh).
|
||||
2. Run `brew install cmake boost` in your terminal.
|
||||
2. Run `brew install cmake asio` in your terminal.
|
||||
3. Get Crow's source code (the entire source code).
|
||||
3. Run the following Commands:
|
||||
1. `mkdir build`
|
||||
|
@ -70,6 +70,3 @@ g++ main.cpp -lpthread
|
|||
You'll need to install GCC via `brew install gcc`. the Clang compiler should be part of XCode or XCode command line tools.
|
||||
|
||||
You can use arguments like `-DCROW_ENABLE_DEBUG`, `-DCROW_ENABLE_COMPRESSION -lz` for HTTP Compression, or `-DCROW_ENABLE_SSL -lssl` for HTTPS support, or even replace g++ with clang++.
|
||||
!!! warning
|
||||
|
||||
If you're using a version of boost prior to 1.69, you'll need to add the argument `-lboost_system` in order for you Crow application to compile correctly.
|
||||
|
|
|
@ -10,8 +10,8 @@ To enable SSL, first your application needs to define either a `.crt` and `.key`
|
|||
|
||||
You also need to define `CROW_ENABLE_SSL` in your compiler definitions (`g++ main.cpp -DCROW_ENABLE_SSL` for example) or `set(CROW_FEATURES ssl)` in `CMakeLists.txt`.
|
||||
|
||||
You can also set your own SSL context (by using `boost::asio::ssl::context ctx`) and then applying it via the `#!cpp app.ssl(ctx)` method.<br><br>
|
||||
You can also set your own SSL context (by using `asio::ssl::context ctx`) and then applying it via the `#!cpp app.ssl(ctx)` method.<br><br>
|
||||
|
||||
!!! warning
|
||||
|
||||
|
||||
If you plan on using a proxy like Nginx or Apache2, **DO NOT** use SSL in crow, instead define it in your proxy and keep the connection between the proxy and Crow non-SSL.
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include "crow.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
class ExampleLogHandler : public crow::ILogHandler
|
||||
{
|
||||
public:
|
||||
|
@ -179,7 +177,7 @@ int main()
|
|||
// To see in action submit something like '/params?pew=42'
|
||||
if (req.url_params.get("pew") != nullptr)
|
||||
{
|
||||
double countD = boost::lexical_cast<double>(req.url_params.get("pew"));
|
||||
double countD = crow::utility::lexical_cast<double>(req.url_params.get("pew"));
|
||||
os << "The value of 'pew' is " << countD << '\n';
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include "crow.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
class ExampleLogHandler : public crow::ILogHandler
|
||||
{
|
||||
public:
|
||||
|
@ -110,7 +108,7 @@ int main()
|
|||
os << "The key 'foo' was " << (req.url_params.get("foo") == nullptr ? "not " : "") << "found.\n";
|
||||
if (req.url_params.get("pew") != nullptr)
|
||||
{
|
||||
double countD = boost::lexical_cast<double>(req.url_params.get("pew"));
|
||||
double countD = crow::utility::lexical_cast<double>(req.url_params.get("pew"));
|
||||
os << "The value of 'pew' is " << countD << '\n';
|
||||
}
|
||||
auto count = req.url_params.get_list("count");
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include "crow_all.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
class ExampleLogHandler : public crow::ILogHandler
|
||||
{
|
||||
public:
|
||||
|
@ -100,7 +98,7 @@ int main()
|
|||
os << "The key 'foo' was " << (req.url_params.get("foo") == nullptr ? "not " : "") << "found.\n";
|
||||
if (req.url_params.get("pew") != nullptr)
|
||||
{
|
||||
double countD = boost::lexical_cast<double>(req.url_params.get("pew"));
|
||||
double countD = crow::utility::lexical_cast<double>(req.url_params.get("pew"));
|
||||
os << "The value of 'pew' is " << countD << '\n';
|
||||
}
|
||||
auto count = req.url_params.get_list("count");
|
||||
|
|
|
@ -14,7 +14,7 @@ int main()
|
|||
// Use .pem file
|
||||
//app.port(18080).ssl_file("test.pem").run();
|
||||
|
||||
// Use custom context; see boost::asio::ssl::context
|
||||
// Use custom context; see asio::ssl::context
|
||||
/*
|
||||
* crow::ssl_context_t ctx;
|
||||
* ctx.set_verify_mode(...)
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
namespace crow
|
||||
{
|
||||
#ifdef CROW_ENABLE_SSL
|
||||
using ssl_context_t = boost::asio::ssl::context;
|
||||
using ssl_context_t = asio::ssl::context;
|
||||
#endif
|
||||
/// The main server application
|
||||
|
||||
|
@ -379,12 +379,12 @@ namespace crow
|
|||
self_t& ssl_file(const std::string& crt_filename, const std::string& key_filename)
|
||||
{
|
||||
ssl_used_ = true;
|
||||
ssl_context_.set_verify_mode(boost::asio::ssl::verify_peer);
|
||||
ssl_context_.set_verify_mode(boost::asio::ssl::verify_client_once);
|
||||
ssl_context_.set_verify_mode(asio::ssl::verify_peer);
|
||||
ssl_context_.set_verify_mode(asio::ssl::verify_client_once);
|
||||
ssl_context_.use_certificate_file(crt_filename, ssl_context_t::pem);
|
||||
ssl_context_.use_private_key_file(key_filename, ssl_context_t::pem);
|
||||
ssl_context_.set_options(
|
||||
boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::no_sslv3);
|
||||
asio::ssl::context::default_workarounds | asio::ssl::context::no_sslv2 | asio::ssl::context::no_sslv3);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -392,11 +392,11 @@ namespace crow
|
|||
self_t& ssl_file(const std::string& pem_filename)
|
||||
{
|
||||
ssl_used_ = true;
|
||||
ssl_context_.set_verify_mode(boost::asio::ssl::verify_peer);
|
||||
ssl_context_.set_verify_mode(boost::asio::ssl::verify_client_once);
|
||||
ssl_context_.set_verify_mode(asio::ssl::verify_peer);
|
||||
ssl_context_.set_verify_mode(asio::ssl::verify_client_once);
|
||||
ssl_context_.load_verify_file(pem_filename);
|
||||
ssl_context_.set_options(
|
||||
boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::no_sslv3);
|
||||
asio::ssl::context::default_workarounds | asio::ssl::context::no_sslv2 | asio::ssl::context::no_sslv3);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -404,16 +404,16 @@ namespace crow
|
|||
self_t& ssl_chainfile(const std::string& crt_filename, const std::string& key_filename)
|
||||
{
|
||||
ssl_used_ = true;
|
||||
ssl_context_.set_verify_mode(boost::asio::ssl::verify_peer);
|
||||
ssl_context_.set_verify_mode(boost::asio::ssl::verify_client_once);
|
||||
ssl_context_.set_verify_mode(asio::ssl::verify_peer);
|
||||
ssl_context_.set_verify_mode(asio::ssl::verify_client_once);
|
||||
ssl_context_.use_certificate_chain_file(crt_filename);
|
||||
ssl_context_.use_private_key_file(key_filename, ssl_context_t::pem);
|
||||
ssl_context_.set_options(
|
||||
boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::no_sslv3);
|
||||
asio::ssl::context::default_workarounds | asio::ssl::context::no_sslv2 | asio::ssl::context::no_sslv3);
|
||||
return *this;
|
||||
}
|
||||
|
||||
self_t& ssl(boost::asio::ssl::context&& ctx)
|
||||
self_t& ssl(asio::ssl::context&& ctx)
|
||||
{
|
||||
ssl_used_ = true;
|
||||
ssl_context_ = std::move(ctx);
|
||||
|
@ -540,7 +540,7 @@ namespace crow
|
|||
#ifdef CROW_ENABLE_SSL
|
||||
std::unique_ptr<ssl_server_t> ssl_server_;
|
||||
bool ssl_used_{false};
|
||||
ssl_context_t ssl_context_{boost::asio::ssl::context::sslv23};
|
||||
ssl_context_t ssl_context_{asio::ssl::context::sslv23};
|
||||
#endif
|
||||
|
||||
std::unique_ptr<server_t> server_;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <locale>
|
||||
#include <unordered_map>
|
||||
#include "crow/utility.h"
|
||||
|
||||
namespace crow
|
||||
{
|
||||
|
@ -15,12 +15,17 @@ namespace crow
|
|||
std::locale locale;
|
||||
|
||||
for (auto c : key)
|
||||
{
|
||||
boost::hash_combine(seed, std::toupper(c, locale));
|
||||
}
|
||||
hash_combine(seed, std::toupper(c, locale));
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
private:
|
||||
static inline void hash_combine(std::size_t& seed, char v)
|
||||
{
|
||||
std::hash<char> hasher;
|
||||
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
}
|
||||
};
|
||||
|
||||
/// Equals function for ci_map (unordered_multimap).
|
||||
|
@ -28,7 +33,7 @@ namespace crow
|
|||
{
|
||||
bool operator()(const std::string& l, const std::string& r) const
|
||||
{
|
||||
return boost::iequals(l, r);
|
||||
return utility::string_equals(l, r);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#pragma once
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#define ASIO_STANDALONE
|
||||
#include <asio.hpp>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
|
@ -18,10 +16,10 @@
|
|||
#include "crow/middleware.h"
|
||||
#include "crow/socket_adaptors.h"
|
||||
#include "crow/compression.h"
|
||||
#include "crow/utility.h"
|
||||
|
||||
namespace crow
|
||||
{
|
||||
using namespace boost;
|
||||
using tcp = asio::ip::tcp;
|
||||
|
||||
|
||||
|
@ -37,7 +35,7 @@ namespace crow
|
|||
|
||||
public:
|
||||
Connection(
|
||||
boost::asio::io_service& io_service,
|
||||
asio::io_service& io_service,
|
||||
Handler* handler,
|
||||
const std::string& server_name,
|
||||
std::tuple<Middlewares...>* middlewares,
|
||||
|
@ -79,7 +77,7 @@ namespace crow
|
|||
|
||||
void start()
|
||||
{
|
||||
adaptor_.start([this](const boost::system::error_code& ec) {
|
||||
adaptor_.start([this](const asio::error_code& ec) {
|
||||
if (!ec)
|
||||
{
|
||||
start_deadline();
|
||||
|
@ -144,7 +142,7 @@ namespace crow
|
|||
}
|
||||
}
|
||||
|
||||
CROW_LOG_INFO << "Request: " << boost::lexical_cast<std::string>(adaptor_.remote_endpoint()) << " " << this << " HTTP/" << (char)(req.http_ver_major + '0') << "." << (char)(req.http_ver_minor + '0') << ' ' << method_name(req.method) << " " << req.url;
|
||||
CROW_LOG_INFO << "Request: " << utility::lexical_cast<std::string>(adaptor_.remote_endpoint()) << " " << this << " HTTP/" << (char)(req.http_ver_major + '0') << "." << (char)(req.http_ver_minor + '0') << ' ' << method_name(req.method) << " " << req.url;
|
||||
|
||||
|
||||
need_to_call_after_handlers_ = false;
|
||||
|
@ -374,7 +372,7 @@ namespace crow
|
|||
void do_write_static()
|
||||
{
|
||||
is_writing = true;
|
||||
boost::asio::write(adaptor_.socket(), buffers_);
|
||||
asio::write(adaptor_.socket(), buffers_);
|
||||
|
||||
if (res.file_info.statResult == 0)
|
||||
{
|
||||
|
@ -383,7 +381,7 @@ namespace crow
|
|||
while (is.read(buf, sizeof(buf)).gcount() > 0)
|
||||
{
|
||||
std::vector<asio::const_buffer> buffers;
|
||||
buffers.push_back(boost::asio::buffer(buf));
|
||||
buffers.push_back(asio::buffer(buf));
|
||||
do_write_sync(buffers);
|
||||
}
|
||||
}
|
||||
|
@ -420,7 +418,7 @@ namespace crow
|
|||
else
|
||||
{
|
||||
is_writing = true;
|
||||
boost::asio::write(adaptor_.socket(), buffers_); // Write the response start / headers
|
||||
asio::write(adaptor_.socket(), buffers_); // Write the response start / headers
|
||||
cancel_deadline_timer();
|
||||
if (res.body.length() > 0)
|
||||
{
|
||||
|
@ -433,7 +431,7 @@ namespace crow
|
|||
buf = res.body.substr(0, 16384);
|
||||
res.body = res.body.substr(16384);
|
||||
buffers.clear();
|
||||
buffers.push_back(boost::asio::buffer(buf));
|
||||
buffers.push_back(asio::buffer(buf));
|
||||
do_write_sync(buffers);
|
||||
}
|
||||
// Collect whatever is left (less than 16KB) and send it down the socket
|
||||
|
@ -442,7 +440,7 @@ namespace crow
|
|||
res.body.clear();
|
||||
|
||||
buffers.clear();
|
||||
buffers.push_back(boost::asio::buffer(buf));
|
||||
buffers.push_back(asio::buffer(buf));
|
||||
do_write_sync(buffers);
|
||||
}
|
||||
is_writing = false;
|
||||
|
@ -465,8 +463,8 @@ namespace crow
|
|||
//auto self = this->shared_from_this();
|
||||
is_reading = true;
|
||||
adaptor_.socket().async_read_some(
|
||||
boost::asio::buffer(buffer_),
|
||||
[this](const boost::system::error_code& ec, std::size_t bytes_transferred) {
|
||||
asio::buffer(buffer_),
|
||||
[this](const asio::error_code& ec, std::size_t bytes_transferred) {
|
||||
bool error_while_reading = true;
|
||||
if (!ec)
|
||||
{
|
||||
|
@ -512,9 +510,9 @@ namespace crow
|
|||
{
|
||||
//auto self = this->shared_from_this();
|
||||
is_writing = true;
|
||||
boost::asio::async_write(
|
||||
asio::async_write(
|
||||
adaptor_.socket(), buffers_,
|
||||
[&](const boost::system::error_code& ec, std::size_t /*bytes_transferred*/) {
|
||||
[&](const asio::error_code& ec, std::size_t /*bytes_transferred*/) {
|
||||
is_writing = false;
|
||||
res.clear();
|
||||
res_body_copy_.clear();
|
||||
|
@ -539,7 +537,7 @@ namespace crow
|
|||
inline void do_write_sync(std::vector<asio::const_buffer>& buffers)
|
||||
{
|
||||
|
||||
boost::asio::write(adaptor_.socket(), buffers, [&](std::error_code ec, std::size_t) {
|
||||
asio::write(adaptor_.socket(), buffers, [&](asio::error_code ec, std::size_t) {
|
||||
if (!ec)
|
||||
{
|
||||
return false;
|
||||
|
@ -590,7 +588,7 @@ namespace crow
|
|||
Adaptor adaptor_;
|
||||
Handler* handler_;
|
||||
|
||||
boost::array<char, 4096> buffer_;
|
||||
std::array<char, 4096> buffer_;
|
||||
|
||||
HTTPParser<Connection> parser_;
|
||||
request req_;
|
||||
|
@ -599,7 +597,7 @@ namespace crow
|
|||
bool close_connection_ = false;
|
||||
|
||||
const std::string& server_name_;
|
||||
std::vector<boost::asio::const_buffer> buffers_;
|
||||
std::vector<asio::const_buffer> buffers_;
|
||||
|
||||
std::string content_length_;
|
||||
std::string date_str_;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#define ASIO_STANDALONE
|
||||
#include <asio.hpp>
|
||||
|
||||
#include "crow/common.h"
|
||||
#include "crow/ci_map.h"
|
||||
|
@ -35,7 +36,7 @@ namespace crow
|
|||
|
||||
void* middleware_context{};
|
||||
void* middleware_container{};
|
||||
boost::asio::io_service* io_service{};
|
||||
asio::io_service* io_service{};
|
||||
|
||||
/// Construct an empty request. (sets the method to `GET`)
|
||||
request():
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#define ASIO_STANDALONE
|
||||
#include <asio.hpp>
|
||||
#ifdef CROW_ENABLE_SSL
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <asio/ssl.hpp>
|
||||
#endif
|
||||
#include <cstdint>
|
||||
#include <atomic>
|
||||
|
@ -19,7 +19,6 @@
|
|||
|
||||
namespace crow
|
||||
{
|
||||
using namespace boost;
|
||||
using tcp = asio::ip::tcp;
|
||||
|
||||
template<typename Handler, typename Adaptor = SocketAdaptor, typename... Middlewares>
|
||||
|
@ -27,7 +26,7 @@ namespace crow
|
|||
{
|
||||
public:
|
||||
Server(Handler* handler, std::string bindaddr, uint16_t port, std::string server_name = std::string("Crow/") + VERSION, std::tuple<Middlewares...>* middlewares = nullptr, uint16_t concurrency = 1, uint8_t timeout = 5, typename Adaptor::context* adaptor_ctx = nullptr):
|
||||
acceptor_(io_service_, tcp::endpoint(boost::asio::ip::address::from_string(bindaddr), port)),
|
||||
acceptor_(io_service_, tcp::endpoint(asio::ip::address::from_string(bindaddr), port)),
|
||||
signals_(io_service_),
|
||||
tick_timer_(io_service_),
|
||||
handler_(handler),
|
||||
|
@ -50,8 +49,8 @@ namespace crow
|
|||
void on_tick()
|
||||
{
|
||||
tick_function_();
|
||||
tick_timer_.expires_from_now(boost::posix_time::milliseconds(tick_interval_.count()));
|
||||
tick_timer_.async_wait([this](const boost::system::error_code& ec) {
|
||||
tick_timer_.expires_after(std::chrono::milliseconds(tick_interval_.count()));
|
||||
tick_timer_.async_wait([this](const asio::error_code& ec) {
|
||||
if (ec)
|
||||
return;
|
||||
on_tick();
|
||||
|
@ -62,7 +61,7 @@ namespace crow
|
|||
{
|
||||
uint16_t worker_thread_count = concurrency_ - 1;
|
||||
for (int i = 0; i < worker_thread_count; i++)
|
||||
io_service_pool_.emplace_back(new boost::asio::io_service());
|
||||
io_service_pool_.emplace_back(new asio::io_service());
|
||||
get_cached_date_str_pool_.resize(worker_thread_count);
|
||||
task_timer_pool_.resize(worker_thread_count);
|
||||
|
||||
|
@ -125,9 +124,9 @@ namespace crow
|
|||
|
||||
if (tick_function_ && tick_interval_.count() > 0)
|
||||
{
|
||||
tick_timer_.expires_from_now(boost::posix_time::milliseconds(tick_interval_.count()));
|
||||
tick_timer_.expires_after(std::chrono::milliseconds(tick_interval_.count()));
|
||||
tick_timer_.async_wait(
|
||||
[this](const boost::system::error_code& ec) {
|
||||
[this](const asio::error_code& ec) {
|
||||
if (ec)
|
||||
return;
|
||||
on_tick();
|
||||
|
@ -142,7 +141,7 @@ namespace crow
|
|||
CROW_LOG_INFO << "Call `app.loglevel(crow::LogLevel::Warning)` to hide Info level logs.";
|
||||
|
||||
signals_.async_wait(
|
||||
[&](const boost::system::error_code& /*error*/, int /*signal_number*/) {
|
||||
[&](const asio::error_code& /*error*/, int /*signal_number*/) {
|
||||
stop();
|
||||
});
|
||||
|
||||
|
@ -226,7 +225,7 @@ namespace crow
|
|||
|
||||
acceptor_.async_accept(
|
||||
p->socket(),
|
||||
[this, p, &is, service_idx](boost::system::error_code ec) {
|
||||
[this, p, &is, service_idx](asio::error_code ec) {
|
||||
if (!ec)
|
||||
{
|
||||
is.post(
|
||||
|
@ -263,8 +262,9 @@ namespace crow
|
|||
bool server_started_{false};
|
||||
std::condition_variable cv_started_;
|
||||
std::mutex start_mutex_;
|
||||
boost::asio::signal_set signals_;
|
||||
boost::asio::deadline_timer tick_timer_;
|
||||
asio::signal_set signals_;
|
||||
|
||||
asio::basic_waitable_timer<std::chrono::high_resolution_clock> tick_timer_;
|
||||
|
||||
Handler* handler_;
|
||||
uint16_t concurrency_{2};
|
||||
|
|
|
@ -12,9 +12,6 @@
|
|||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
|
@ -117,7 +114,7 @@ namespace crow
|
|||
namespace detail
|
||||
{
|
||||
/// A read string implementation with comparison functionality.
|
||||
struct r_string : boost::less_than_comparable<r_string>, boost::less_than_comparable<r_string, std::string>, boost::equality_comparable<r_string>, boost::equality_comparable<r_string, std::string>
|
||||
struct r_string
|
||||
{
|
||||
r_string(){};
|
||||
r_string(char* s, char* e):
|
||||
|
@ -186,31 +183,85 @@ namespace crow
|
|||
owned_ = 1;
|
||||
}
|
||||
friend rvalue crow::json::load(const char* data, size_t size);
|
||||
|
||||
friend bool operator==(const r_string& l, const r_string& r);
|
||||
friend bool operator==(const std::string& l, const r_string& r);
|
||||
friend bool operator==(const r_string& l, const std::string& r);
|
||||
|
||||
template<typename T, typename U>
|
||||
inline static bool equals(const T& l, const U& r)
|
||||
{
|
||||
if (l.size() != r.size())
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < l.size(); i++)
|
||||
{
|
||||
if (*(l.begin() + i) != *(r.begin() + i))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool operator<(const r_string& l, const r_string& r)
|
||||
{
|
||||
return boost::lexicographical_compare(l, r);
|
||||
return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
|
||||
}
|
||||
|
||||
inline bool operator<(const r_string& l, const std::string& r)
|
||||
{
|
||||
return boost::lexicographical_compare(l, r);
|
||||
return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
|
||||
}
|
||||
|
||||
inline bool operator<(const std::string& l, const r_string& r)
|
||||
{
|
||||
return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
|
||||
}
|
||||
|
||||
inline bool operator>(const r_string& l, const r_string& r)
|
||||
{
|
||||
return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
|
||||
}
|
||||
|
||||
inline bool operator>(const r_string& l, const std::string& r)
|
||||
{
|
||||
return boost::lexicographical_compare(r, l);
|
||||
return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
|
||||
}
|
||||
|
||||
inline bool operator>(const std::string& l, const r_string& r)
|
||||
{
|
||||
return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
|
||||
}
|
||||
|
||||
inline bool operator==(const r_string& l, const r_string& r)
|
||||
{
|
||||
return boost::equals(l, r);
|
||||
return r_string::equals(l, r);
|
||||
}
|
||||
|
||||
inline bool operator==(const r_string& l, const std::string& r)
|
||||
{
|
||||
return boost::equals(l, r);
|
||||
return r_string::equals(l, r);
|
||||
}
|
||||
|
||||
inline bool operator==(const std::string& l, const r_string& r)
|
||||
{
|
||||
return r_string::equals(l, r);
|
||||
}
|
||||
|
||||
inline bool operator!=(const r_string& l, const r_string& r)
|
||||
{
|
||||
return !(l == r);
|
||||
}
|
||||
|
||||
inline bool operator!=(const r_string& l, const std::string& r)
|
||||
{
|
||||
return !(l == r);
|
||||
}
|
||||
|
||||
inline bool operator!=(const std::string& l, const r_string& r)
|
||||
{
|
||||
return !(l == r);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
|
@ -349,13 +400,13 @@ namespace crow
|
|||
{
|
||||
case type::Number:
|
||||
case type::String:
|
||||
return boost::lexical_cast<int64_t>(start_, end_ - start_);
|
||||
return utility::lexical_cast<int64_t>(start_, end_ - start_);
|
||||
default:
|
||||
const std::string msg = "expected number, got: " + std::string(get_type_str(t()));
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
#endif
|
||||
return boost::lexical_cast<int64_t>(start_, end_ - start_);
|
||||
return utility::lexical_cast<int64_t>(start_, end_ - start_);
|
||||
}
|
||||
|
||||
/// The unsigned integer value.
|
||||
|
@ -366,12 +417,12 @@ namespace crow
|
|||
{
|
||||
case type::Number:
|
||||
case type::String:
|
||||
return boost::lexical_cast<uint64_t>(start_, end_ - start_);
|
||||
return utility::lexical_cast<uint64_t>(start_, end_ - start_);
|
||||
default:
|
||||
throw std::runtime_error(std::string("expected number, got: ") + get_type_str(t()));
|
||||
}
|
||||
#endif
|
||||
return boost::lexical_cast<uint64_t>(start_, end_ - start_);
|
||||
return utility::lexical_cast<uint64_t>(start_, end_ - start_);
|
||||
}
|
||||
|
||||
/// The double precision floating-point number value.
|
||||
|
@ -381,7 +432,7 @@ namespace crow
|
|||
if (t() != type::Number)
|
||||
throw std::runtime_error("value is not number");
|
||||
#endif
|
||||
return boost::lexical_cast<double>(start_, end_ - start_);
|
||||
return utility::lexical_cast<double>(start_, end_ - start_);
|
||||
}
|
||||
|
||||
/// The boolean value.
|
||||
|
@ -968,8 +1019,8 @@ namespace crow
|
|||
{
|
||||
state = NumberParsingState::ZeroFirst;
|
||||
}
|
||||
else if (state == NumberParsingState::Digits ||
|
||||
state == NumberParsingState::DigitsAfterE ||
|
||||
else if (state == NumberParsingState::Digits ||
|
||||
state == NumberParsingState::DigitsAfterE ||
|
||||
state == NumberParsingState::DigitsAfterPoints)
|
||||
{
|
||||
// ok; pass
|
||||
|
@ -997,8 +1048,8 @@ namespace crow
|
|||
{
|
||||
state = NumberParsingState::Digits;
|
||||
}
|
||||
else if (state == NumberParsingState::Digits ||
|
||||
state == NumberParsingState::DigitsAfterE ||
|
||||
else if (state == NumberParsingState::Digits ||
|
||||
state == NumberParsingState::DigitsAfterE ||
|
||||
state == NumberParsingState::DigitsAfterPoints)
|
||||
{
|
||||
// ok; pass
|
||||
|
@ -1046,12 +1097,12 @@ namespace crow
|
|||
case 'e':
|
||||
case 'E':
|
||||
state = static_cast<NumberParsingState>("\7\7\7\5\5\7\7"[state]);
|
||||
/*if (state == NumberParsingState::Digits ||
|
||||
/*if (state == NumberParsingState::Digits ||
|
||||
state == NumberParsingState::DigitsAfterPoints)
|
||||
{
|
||||
state = NumberParsingState::E;
|
||||
}
|
||||
else
|
||||
else
|
||||
return {};*/
|
||||
break;
|
||||
default:
|
||||
|
@ -1898,7 +1949,7 @@ namespace crow
|
|||
|
||||
|
||||
|
||||
//std::vector<boost::asio::const_buffer> dump_ref(wvalue& v)
|
||||
//std::vector<asio::const_buffer> dump_ref(wvalue& v)
|
||||
//{
|
||||
//}
|
||||
} // namespace json
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
#include <iomanip>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <memory>
|
||||
#include "crow/utility.h"
|
||||
#include "crow/http_request.h"
|
||||
#include "crow/http_response.h"
|
||||
|
||||
|
@ -65,7 +65,7 @@ namespace crow
|
|||
if (expires_at_)
|
||||
{
|
||||
ss << DIVIDER << "Expires="
|
||||
<< std::put_time(expires_at_.get_ptr(), HTTP_DATE_FORMAT);
|
||||
<< std::put_time(expires_at_.get(), HTTP_DATE_FORMAT);
|
||||
}
|
||||
if (max_age_)
|
||||
{
|
||||
|
@ -93,14 +93,14 @@ namespace crow
|
|||
// Expires attribute
|
||||
Cookie& expires(const std::tm& time)
|
||||
{
|
||||
expires_at_ = time;
|
||||
expires_at_ = std::unique_ptr<std::tm>(new std::tm(time));
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Max-Age attribute
|
||||
Cookie& max_age(long long seconds)
|
||||
{
|
||||
max_age_ = seconds;
|
||||
max_age_ = std::unique_ptr<long long>(new long long(seconds));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -135,10 +135,28 @@ namespace crow
|
|||
// SameSite attribute
|
||||
Cookie& same_site(SameSitePolicy ssp)
|
||||
{
|
||||
same_site_ = ssp;
|
||||
same_site_ = std::unique_ptr<SameSitePolicy>(new SameSitePolicy(ssp));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Cookie(const Cookie& c):
|
||||
key_(c.key_),
|
||||
value_(c.value_),
|
||||
domain_(c.domain_),
|
||||
path_(c.path_),
|
||||
secure_(c.secure_),
|
||||
httponly_(c.httponly_)
|
||||
{
|
||||
if (c.max_age_)
|
||||
max_age_ = std::unique_ptr<long long>(new long long(*c.max_age_));
|
||||
|
||||
if (c.expires_at_)
|
||||
expires_at_ = std::unique_ptr<std::tm>(new std::tm(*c.expires_at_));
|
||||
|
||||
if (c.same_site_)
|
||||
same_site_ = std::unique_ptr<SameSitePolicy>(new SameSitePolicy(*c.same_site_));
|
||||
}
|
||||
|
||||
private:
|
||||
Cookie() = default;
|
||||
|
||||
|
@ -154,13 +172,13 @@ namespace crow
|
|||
private:
|
||||
std::string key_;
|
||||
std::string value_;
|
||||
boost::optional<long long> max_age_{};
|
||||
std::unique_ptr<long long> max_age_{};
|
||||
std::string domain_ = "";
|
||||
std::string path_ = "";
|
||||
bool secure_ = false;
|
||||
bool httponly_ = false;
|
||||
boost::optional<std::tm> expires_at_{};
|
||||
boost::optional<SameSitePolicy> same_site_{};
|
||||
std::unique_ptr<std::tm> expires_at_{};
|
||||
std::unique_ptr<SameSitePolicy> same_site_{};
|
||||
|
||||
static constexpr const char* DIVIDER = "; ";
|
||||
};
|
||||
|
@ -207,17 +225,15 @@ namespace crow
|
|||
if (pos_equal == cookies.npos)
|
||||
break;
|
||||
std::string name = cookies.substr(pos, pos_equal - pos);
|
||||
boost::trim(name);
|
||||
name = utility::trim(name);
|
||||
pos = pos_equal + 1;
|
||||
while (pos < cookies.size() && cookies[pos] == ' ')
|
||||
pos++;
|
||||
if (pos == cookies.size())
|
||||
break;
|
||||
|
||||
size_t pos_semicolon = cookies.find(';', pos);
|
||||
std::string value = cookies.substr(pos, pos_semicolon - pos);
|
||||
|
||||
boost::trim(value);
|
||||
value = utility::trim(value);
|
||||
if (value[0] == '"' && value[value.size() - 1] == '"')
|
||||
{
|
||||
value = value.substr(1, value.size() - 2);
|
||||
|
@ -229,8 +245,6 @@ namespace crow
|
|||
if (pos == cookies.npos)
|
||||
break;
|
||||
pos++;
|
||||
while (pos < cookies.size() && cookies[pos] == ' ')
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,7 +272,7 @@ namespace crow
|
|||
C::handle
|
||||
context.aaa
|
||||
|
||||
App::context : private CookieParser::contetx, ...
|
||||
App::context : private CookieParser::contetx, ...
|
||||
{
|
||||
jar
|
||||
|
||||
|
|
|
@ -258,7 +258,7 @@ namespace crow
|
|||
}
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("not implemented tag type" + boost::lexical_cast<std::string>(static_cast<int>(ctx.t())));
|
||||
throw std::runtime_error("not implemented tag type" + utility::lexical_cast<std::string>(static_cast<int>(ctx.t())));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -324,7 +324,7 @@ namespace crow
|
|||
current = action.pos;
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("{{#: not implemented context type: " + boost::lexical_cast<std::string>(static_cast<int>(ctx.t())));
|
||||
throw std::runtime_error("{{#: not implemented context type: " + utility::lexical_cast<std::string>(static_cast<int>(ctx.t())));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -333,7 +333,7 @@ namespace crow
|
|||
stack.pop_back();
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("not implemented " + boost::lexical_cast<std::string>(static_cast<int>(action.t)));
|
||||
throw std::runtime_error("not implemented " + utility::lexical_cast<std::string>(static_cast<int>(action.t)));
|
||||
}
|
||||
current++;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
#include "crow/http_parser_merged.h"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <iostream>
|
||||
#include <boost/optional.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace crow
|
||||
{
|
||||
|
@ -194,7 +194,7 @@ inline char * qs_k2v(const char * key, char * const * qs_kv, int qs_kv_size, int
|
|||
// return (zero-char value) ? ptr to trailing '\0' : ptr to value
|
||||
if(nth == 0)
|
||||
return qs_kv[i] + skip;
|
||||
else
|
||||
else
|
||||
--nth;
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ inline char * qs_k2v(const char * key, char * const * qs_kv, int qs_kv_size, int
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
inline boost::optional<std::pair<std::string, std::string>> qs_dict_name2kv(const char * dict_name, char * const * qs_kv, int qs_kv_size, int nth = 0)
|
||||
inline std::unique_ptr<std::pair<std::string, std::string>> qs_dict_name2kv(const char * dict_name, char * const * qs_kv, int qs_kv_size, int nth = 0)
|
||||
{
|
||||
int i;
|
||||
size_t name_len, skip_to_eq, skip_to_brace_open, skip_to_brace_close;
|
||||
|
@ -232,7 +232,7 @@ inline boost::optional<std::pair<std::string, std::string>> qs_dict_name2kv(cons
|
|||
{
|
||||
auto key = std::string(qs_kv[i] + skip_to_brace_open, skip_to_brace_close - skip_to_brace_open);
|
||||
auto value = std::string(qs_kv[i] + skip_to_eq);
|
||||
return boost::make_optional(std::make_pair(key, value));
|
||||
return std::unique_ptr<std::pair<std::string, std::string>>(new std::pair<std::string, std::string>(key, value));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -242,7 +242,7 @@ inline boost::optional<std::pair<std::string, std::string>> qs_dict_name2kv(cons
|
|||
}
|
||||
#endif // _qsSORTING
|
||||
|
||||
return boost::none;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
|
|
|
@ -1,28 +1,29 @@
|
|||
#pragma once
|
||||
#include <boost/asio.hpp>
|
||||
#define ASIO_STANDALONE
|
||||
#include <asio.hpp>
|
||||
#ifdef CROW_ENABLE_SSL
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <asio/ssl.hpp>
|
||||
#endif
|
||||
#include "crow/settings.h"
|
||||
#if BOOST_VERSION >= 107000
|
||||
#define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context())
|
||||
#include <asio/version.hpp>
|
||||
#if ASIO_VERSION >= 101300 // 1.13.0
|
||||
#define GET_IO_SERVICE(s) ((asio::io_context&)(s).get_executor().context())
|
||||
#else
|
||||
#define GET_IO_SERVICE(s) ((s).get_io_service())
|
||||
#endif
|
||||
namespace crow
|
||||
{
|
||||
using namespace boost;
|
||||
using tcp = asio::ip::tcp;
|
||||
|
||||
/// A wrapper for the asio::ip::tcp::socket and asio::ssl::stream
|
||||
struct SocketAdaptor
|
||||
{
|
||||
using context = void;
|
||||
SocketAdaptor(boost::asio::io_service& io_service, context*):
|
||||
SocketAdaptor(asio::io_service& io_service, context*):
|
||||
socket_(io_service)
|
||||
{}
|
||||
|
||||
boost::asio::io_service& get_io_service()
|
||||
asio::io_service& get_io_service()
|
||||
{
|
||||
return GET_IO_SERVICE(socket_);
|
||||
}
|
||||
|
@ -51,32 +52,32 @@ namespace crow
|
|||
|
||||
void close()
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
asio::error_code ec;
|
||||
socket_.close(ec);
|
||||
}
|
||||
|
||||
void shutdown_readwrite()
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
socket_.shutdown(boost::asio::socket_base::shutdown_type::shutdown_both, ec);
|
||||
asio::error_code ec;
|
||||
socket_.shutdown(asio::socket_base::shutdown_type::shutdown_both, ec);
|
||||
}
|
||||
|
||||
void shutdown_write()
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
socket_.shutdown(boost::asio::socket_base::shutdown_type::shutdown_send, ec);
|
||||
asio::error_code ec;
|
||||
socket_.shutdown(asio::socket_base::shutdown_type::shutdown_send, ec);
|
||||
}
|
||||
|
||||
void shutdown_read()
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
socket_.shutdown(boost::asio::socket_base::shutdown_type::shutdown_receive, ec);
|
||||
asio::error_code ec;
|
||||
socket_.shutdown(asio::socket_base::shutdown_type::shutdown_receive, ec);
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void start(F f)
|
||||
{
|
||||
f(boost::system::error_code());
|
||||
f(asio::error_code());
|
||||
}
|
||||
|
||||
tcp::socket socket_;
|
||||
|
@ -85,13 +86,13 @@ namespace crow
|
|||
#ifdef CROW_ENABLE_SSL
|
||||
struct SSLAdaptor
|
||||
{
|
||||
using context = boost::asio::ssl::context;
|
||||
using ssl_socket_t = boost::asio::ssl::stream<tcp::socket>;
|
||||
SSLAdaptor(boost::asio::io_service& io_service, context* ctx):
|
||||
using context = asio::ssl::context;
|
||||
using ssl_socket_t = asio::ssl::stream<tcp::socket>;
|
||||
SSLAdaptor(asio::io_service& io_service, context* ctx):
|
||||
ssl_socket_(new ssl_socket_t(io_service, *ctx))
|
||||
{}
|
||||
|
||||
boost::asio::ssl::stream<tcp::socket>& socket()
|
||||
asio::ssl::stream<tcp::socket>& socket()
|
||||
{
|
||||
return *ssl_socket_;
|
||||
}
|
||||
|
@ -116,7 +117,7 @@ namespace crow
|
|||
{
|
||||
if (is_open())
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
asio::error_code ec;
|
||||
raw_socket().close(ec);
|
||||
}
|
||||
}
|
||||
|
@ -125,8 +126,8 @@ namespace crow
|
|||
{
|
||||
if (is_open())
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
raw_socket().shutdown(boost::asio::socket_base::shutdown_type::shutdown_both, ec);
|
||||
asio::error_code ec;
|
||||
raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_both, ec);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,8 +135,8 @@ namespace crow
|
|||
{
|
||||
if (is_open())
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
raw_socket().shutdown(boost::asio::socket_base::shutdown_type::shutdown_send, ec);
|
||||
asio::error_code ec;
|
||||
raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_send, ec);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,12 +144,12 @@ namespace crow
|
|||
{
|
||||
if (is_open())
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
raw_socket().shutdown(boost::asio::socket_base::shutdown_type::shutdown_receive, ec);
|
||||
asio::error_code ec;
|
||||
raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_receive, ec);
|
||||
}
|
||||
}
|
||||
|
||||
boost::asio::io_service& get_io_service()
|
||||
asio::io_service& get_io_service()
|
||||
{
|
||||
return GET_IO_SERVICE(raw_socket());
|
||||
}
|
||||
|
@ -156,13 +157,13 @@ namespace crow
|
|||
template<typename F>
|
||||
void start(F f)
|
||||
{
|
||||
ssl_socket_->async_handshake(boost::asio::ssl::stream_base::server,
|
||||
[f](const boost::system::error_code& ec) {
|
||||
ssl_socket_->async_handshake(asio::ssl::stream_base::server,
|
||||
[f](const asio::error_code& ec) {
|
||||
f(ec);
|
||||
});
|
||||
}
|
||||
|
||||
std::unique_ptr<boost::asio::ssl::stream<tcp::socket>> ssl_socket_;
|
||||
std::unique_ptr<asio::ssl::stream<tcp::socket>> ssl_socket_;
|
||||
};
|
||||
#endif
|
||||
} // namespace crow
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#define ASIO_STANDALONE
|
||||
#include <asio.hpp>
|
||||
#include <asio/basic_waitable_timer.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
@ -25,15 +28,15 @@ namespace crow
|
|||
using time_type = clock_type::time_point;
|
||||
|
||||
public:
|
||||
task_timer(boost::asio::io_service& io_service):
|
||||
io_service_(io_service), deadline_timer_(io_service_)
|
||||
task_timer(asio::io_service& io_service):
|
||||
io_service_(io_service), timer_(io_service_)
|
||||
{
|
||||
deadline_timer_.expires_from_now(boost::posix_time::seconds(1));
|
||||
deadline_timer_.async_wait(
|
||||
timer_.expires_after(std::chrono::seconds(1));
|
||||
timer_.async_wait(
|
||||
std::bind(&task_timer::tick_handler, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
~task_timer() { deadline_timer_.cancel(); }
|
||||
~task_timer() { timer_.cancel(); }
|
||||
|
||||
void cancel(identifier_type id)
|
||||
{
|
||||
|
@ -107,21 +110,21 @@ namespace crow
|
|||
if (tasks_.empty()) highest_id_ = 0;
|
||||
}
|
||||
|
||||
void tick_handler(const boost::system::error_code& ec)
|
||||
void tick_handler(const asio::error_code& ec)
|
||||
{
|
||||
if (ec) return;
|
||||
|
||||
process_tasks();
|
||||
|
||||
deadline_timer_.expires_from_now(boost::posix_time::seconds(1));
|
||||
deadline_timer_.async_wait(
|
||||
timer_.expires_after(std::chrono::seconds(1));
|
||||
timer_.async_wait(
|
||||
std::bind(&task_timer::tick_handler, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
private:
|
||||
std::uint8_t default_timeout_{5};
|
||||
boost::asio::io_service& io_service_;
|
||||
boost::asio::deadline_timer deadline_timer_;
|
||||
asio::io_service& io_service_;
|
||||
asio::basic_waitable_timer<clock_type> timer_;
|
||||
std::map<identifier_type, std::pair<time_type, task_type>> tasks_;
|
||||
|
||||
// A continuosly increasing number to be issued to threads to identify them.
|
||||
|
|
|
@ -5,8 +5,10 @@
|
|||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "crow/settings.h"
|
||||
|
@ -500,7 +502,6 @@ namespace crow
|
|||
{
|
||||
static constexpr auto value = get_index_of_element_from_tuple_by_type_impl<T, N + 1, Args...>::value;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
namespace utility
|
||||
|
@ -780,5 +781,90 @@ namespace crow
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks two string for equality.
|
||||
* Always returns false if strings differ in size.
|
||||
* Defaults to case-insensitive comparison.
|
||||
*/
|
||||
inline static bool string_equals(const std::string& l, const std::string& r, bool case_sensitive = false)
|
||||
{
|
||||
if (l.length() != r.length())
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < l.length(); i++)
|
||||
{
|
||||
if (case_sensitive)
|
||||
{
|
||||
if (l[i] != r[i])
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (std::toupper(l[i]) != std::toupper(r[i]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
inline static T lexical_cast(const U& v)
|
||||
{
|
||||
std::stringstream stream;
|
||||
T res;
|
||||
|
||||
stream << v;
|
||||
stream >> res;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline static T lexical_cast(const char* v, size_t count)
|
||||
{
|
||||
std::stringstream stream;
|
||||
T res;
|
||||
|
||||
stream.write(v, count);
|
||||
stream >> res;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/// Return a copy of the given string with its
|
||||
/// leading and trailing whitespaces removed.
|
||||
inline static std::string trim(const std::string& v)
|
||||
{
|
||||
if (v.empty())
|
||||
return "";
|
||||
|
||||
size_t begin = 0, end = v.length();
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < v.length(); i++)
|
||||
{
|
||||
if (!std::isspace(v[i]))
|
||||
{
|
||||
begin = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == v.length())
|
||||
return "";
|
||||
|
||||
for (i = v.length(); i > 0; i--)
|
||||
{
|
||||
if (!std::isspace(v[i - 1]))
|
||||
{
|
||||
end = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return v.substr(begin, end - begin);
|
||||
}
|
||||
} // namespace utility
|
||||
} // namespace crow
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#pragma once
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <array>
|
||||
#include "crow/logging.h"
|
||||
#include "crow/socket_adaptors.h"
|
||||
#include "crow/http_request.h"
|
||||
#include "crow/TinySHA1.hpp"
|
||||
#include "crow/utility.h"
|
||||
|
||||
namespace crow
|
||||
{
|
||||
|
@ -86,7 +86,7 @@ namespace crow
|
|||
error_handler_(std::move(error_handler)),
|
||||
accept_handler_(std::move(accept_handler))
|
||||
{
|
||||
if (!boost::iequals(req.get_header_value("upgrade"), "websocket"))
|
||||
if (!utility::string_equals(req.get_header_value("upgrade"), "websocket"))
|
||||
{
|
||||
adaptor.close();
|
||||
handler_->remove_websocket(this);
|
||||
|
@ -282,12 +282,12 @@ namespace crow
|
|||
case WebSocketReadState::MiniHeader:
|
||||
{
|
||||
mini_header_ = 0;
|
||||
//boost::asio::async_read(adaptor_.socket(), boost::asio::buffer(&mini_header_, 1),
|
||||
//asio::async_read(adaptor_.socket(), asio::buffer(&mini_header_, 1),
|
||||
adaptor_.socket().async_read_some(
|
||||
boost::asio::buffer(&mini_header_, 2),
|
||||
[this](const boost::system::error_code& ec, std::size_t
|
||||
asio::buffer(&mini_header_, 2),
|
||||
[this](const asio::error_code& ec, std::size_t
|
||||
#ifdef CROW_ENABLE_DEBUG
|
||||
bytes_transferred
|
||||
bytes_transferred
|
||||
#endif
|
||||
)
|
||||
|
||||
|
@ -351,11 +351,11 @@ namespace crow
|
|||
{
|
||||
remaining_length_ = 0;
|
||||
remaining_length16_ = 0;
|
||||
boost::asio::async_read(
|
||||
adaptor_.socket(), boost::asio::buffer(&remaining_length16_, 2),
|
||||
[this](const boost::system::error_code& ec, std::size_t
|
||||
asio::async_read(
|
||||
adaptor_.socket(), asio::buffer(&remaining_length16_, 2),
|
||||
[this](const asio::error_code& ec, std::size_t
|
||||
#ifdef CROW_ENABLE_DEBUG
|
||||
bytes_transferred
|
||||
bytes_transferred
|
||||
#endif
|
||||
) {
|
||||
is_reading = false;
|
||||
|
@ -387,11 +387,11 @@ namespace crow
|
|||
break;
|
||||
case WebSocketReadState::Len64:
|
||||
{
|
||||
boost::asio::async_read(
|
||||
adaptor_.socket(), boost::asio::buffer(&remaining_length_, 8),
|
||||
[this](const boost::system::error_code& ec, std::size_t
|
||||
asio::async_read(
|
||||
adaptor_.socket(), asio::buffer(&remaining_length_, 8),
|
||||
[this](const asio::error_code& ec, std::size_t
|
||||
#ifdef CROW_ENABLE_DEBUG
|
||||
bytes_transferred
|
||||
bytes_transferred
|
||||
#endif
|
||||
) {
|
||||
is_reading = false;
|
||||
|
@ -431,11 +431,11 @@ namespace crow
|
|||
}
|
||||
else if (has_mask_)
|
||||
{
|
||||
boost::asio::async_read(
|
||||
adaptor_.socket(), boost::asio::buffer((char*)&mask_, 4),
|
||||
[this](const boost::system::error_code& ec, std::size_t
|
||||
asio::async_read(
|
||||
adaptor_.socket(), asio::buffer((char*)&mask_, 4),
|
||||
[this](const asio::error_code& ec, std::size_t
|
||||
#ifdef CROW_ENABLE_DEBUG
|
||||
bytes_transferred
|
||||
bytes_transferred
|
||||
#endif
|
||||
) {
|
||||
is_reading = false;
|
||||
|
@ -474,8 +474,8 @@ namespace crow
|
|||
if (remaining_length_ < to_read)
|
||||
to_read = remaining_length_;
|
||||
adaptor_.socket().async_read_some(
|
||||
boost::asio::buffer(buffer_, static_cast<std::size_t>(to_read)),
|
||||
[this](const boost::system::error_code& ec, std::size_t bytes_transferred) {
|
||||
asio::buffer(buffer_, static_cast<std::size_t>(to_read)),
|
||||
[this](const asio::error_code& ec, std::size_t bytes_transferred) {
|
||||
is_reading = false;
|
||||
|
||||
if (!ec)
|
||||
|
@ -618,15 +618,15 @@ namespace crow
|
|||
if (sending_buffers_.empty())
|
||||
{
|
||||
sending_buffers_.swap(write_buffers_);
|
||||
std::vector<boost::asio::const_buffer> buffers;
|
||||
std::vector<asio::const_buffer> buffers;
|
||||
buffers.reserve(sending_buffers_.size());
|
||||
for (auto& s : sending_buffers_)
|
||||
{
|
||||
buffers.emplace_back(boost::asio::buffer(s));
|
||||
buffers.emplace_back(asio::buffer(s));
|
||||
}
|
||||
boost::asio::async_write(
|
||||
asio::async_write(
|
||||
adaptor_.socket(), buffers,
|
||||
[&](const boost::system::error_code& ec, std::size_t /*bytes_transferred*/) {
|
||||
[&](const asio::error_code& ec, std::size_t /*bytes_transferred*/) {
|
||||
sending_buffers_.clear();
|
||||
if (!ec && !close_connection_)
|
||||
{
|
||||
|
@ -663,7 +663,7 @@ namespace crow
|
|||
std::vector<std::string> sending_buffers_;
|
||||
std::vector<std::string> write_buffers_;
|
||||
|
||||
boost::array<char, 4096> buffer_;
|
||||
std::array<char, 4096> buffer_;
|
||||
bool is_binary_;
|
||||
std::string message_;
|
||||
std::string fragment_;
|
||||
|
|
|
@ -6,7 +6,7 @@ pkgdesc="A Fast and Easy to use C++ microframework for the web."
|
|||
arch=(any)
|
||||
url="https://crowcpp.org"
|
||||
license=('custom:BSD-3-Clause')
|
||||
depends=('boost>=1.64.0')
|
||||
depends=('asio')
|
||||
optdepends=('openssl: HTTPS support' 'zlib: HTTP compression support' 'cmake: Choose this if you plan on using CMake for your Crow project')
|
||||
conflicts=("$pkgname-git")
|
||||
changelog='changelog.md'
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
|
||||
#define LOCALHOST_ADDRESS "127.0.0.1"
|
||||
|
||||
using namespace boost;
|
||||
|
||||
// TODO(EDev): SSL test with .pem file
|
||||
TEST_CASE("SSL")
|
||||
{
|
||||
|
@ -76,8 +74,8 @@ TEST_CASE("SSL")
|
|||
CHECK(std::string("Hello world, I'm keycrt.").substr((z * -1)) == to_test);
|
||||
}
|
||||
|
||||
boost::system::error_code ec;
|
||||
c.lowest_layer().shutdown(boost::asio::socket_base::shutdown_type::shutdown_both, ec);
|
||||
asio::error_code ec;
|
||||
c.lowest_layer().shutdown(asio::socket_base::shutdown_type::shutdown_both, ec);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -596,7 +596,7 @@ TEST_CASE("undefined_status_code")
|
|||
asio::ip::tcp::socket socket(is);
|
||||
socket.connect(asio::ip::tcp::endpoint(asio::ip::address::from_string(LOCALHOST_ADDRESS), app.port()));
|
||||
|
||||
boost::asio::streambuf request;
|
||||
asio::streambuf request;
|
||||
std::ostream request_stream(&request);
|
||||
request_stream << "GET " << route << " HTTP/1.0\r\n";
|
||||
request_stream << "Host: " << LOCALHOST_ADDRESS << "\r\n";
|
||||
|
@ -604,10 +604,10 @@ TEST_CASE("undefined_status_code")
|
|||
request_stream << "Connection: close\r\n\r\n";
|
||||
|
||||
// Send the request.
|
||||
boost::asio::write(socket, request);
|
||||
asio::write(socket, request);
|
||||
|
||||
boost::asio::streambuf response;
|
||||
boost::asio::read_until(socket, response, "\r\n");
|
||||
asio::streambuf response;
|
||||
asio::read_until(socket, response, "\r\n");
|
||||
|
||||
std::istream response_stream(&response);
|
||||
std::string http_version;
|
||||
|
@ -759,7 +759,7 @@ TEST_CASE("json_read_real")
|
|||
for (auto x : v)
|
||||
{
|
||||
CROW_LOG_DEBUG << x;
|
||||
CHECK(json::load(x).d() == boost::lexical_cast<double>(x));
|
||||
CHECK(json::load(x).d() == utility::lexical_cast<double>(x));
|
||||
}
|
||||
|
||||
auto ret = json::load(
|
||||
|
@ -1702,9 +1702,15 @@ TEST_CASE("middleware_cookieparser_format")
|
|||
}
|
||||
// expires
|
||||
{
|
||||
auto tp = boost::posix_time::time_from_string("2000-11-01 23:59:59.000");
|
||||
std::time_t tp;
|
||||
std::time(&tp);
|
||||
std::tm* tm = std::gmtime(&tp);
|
||||
std::istringstream ss("2000-11-01 23:59:59");
|
||||
ss >> std::get_time(tm, "%Y-%m-%d %H:%M:%S");
|
||||
std::mktime(tm);
|
||||
|
||||
auto c = Cookie("key", "value")
|
||||
.expires(boost::posix_time::to_tm(tp));
|
||||
.expires(*tm);
|
||||
auto s = c.dump();
|
||||
CHECK(valid(s, 2));
|
||||
CHECK(s.find("Expires=Wed, 01 Nov 2000 23:59:59 GMT") != std::string::npos);
|
||||
|
@ -1936,10 +1942,10 @@ TEST_CASE("simple_url_params")
|
|||
c.receive(asio::buffer(buf, 2048));
|
||||
c.close();
|
||||
|
||||
CHECK(boost::lexical_cast<int>(last_url_params.get("int")) == 100);
|
||||
CHECK(boost::lexical_cast<double>(last_url_params.get("double")) ==
|
||||
CHECK(utility::lexical_cast<int>(last_url_params.get("int")) == 100);
|
||||
CHECK(utility::lexical_cast<double>(last_url_params.get("double")) ==
|
||||
123.45);
|
||||
CHECK(boost::lexical_cast<bool>(last_url_params.get("boolean")));
|
||||
CHECK(utility::lexical_cast<bool>(last_url_params.get("boolean")));
|
||||
}
|
||||
// check single array value
|
||||
sendmsg = "GET /params?tmnt[]=leonardo\r\n\r\n";
|
||||
|
@ -2518,8 +2524,8 @@ TEST_CASE("websocket_max_payload")
|
|||
}
|
||||
}
|
||||
|
||||
boost::system::error_code ec;
|
||||
c.lowest_layer().shutdown(boost::asio::socket_base::shutdown_type::shutdown_both, ec);
|
||||
asio::error_code ec;
|
||||
c.lowest_layer().shutdown(asio::socket_base::shutdown_type::shutdown_both, ec);
|
||||
|
||||
app.stop();
|
||||
} // websocket_max_payload
|
||||
|
@ -3023,7 +3029,7 @@ TEST_CASE("timeout")
|
|||
asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
|
||||
|
||||
auto receive_future = async(launch::async, [&]() {
|
||||
boost::system::error_code ec;
|
||||
asio::error_code ec;
|
||||
c.receive(asio::buffer(buf, 2048), 0, ec);
|
||||
return ec;
|
||||
});
|
||||
|
@ -3043,7 +3049,7 @@ TEST_CASE("timeout")
|
|||
|
||||
size_t received;
|
||||
auto receive_future = async(launch::async, [&]() {
|
||||
boost::system::error_code ec;
|
||||
asio::error_code ec;
|
||||
received = c.receive(asio::buffer(buf, 2048), 0, ec);
|
||||
return ec;
|
||||
});
|
||||
|
@ -3069,9 +3075,9 @@ TEST_CASE("timeout")
|
|||
|
||||
TEST_CASE("task_timer")
|
||||
{
|
||||
using work_guard_type = boost::asio::executor_work_guard<boost::asio::io_service::executor_type>;
|
||||
using work_guard_type = asio::executor_work_guard<asio::io_service::executor_type>;
|
||||
|
||||
boost::asio::io_service io_service;
|
||||
asio::io_service io_service;
|
||||
work_guard_type work_guard(io_service.get_executor());
|
||||
thread io_thread([&io_service]() {
|
||||
io_service.run();
|
||||
|
@ -3106,3 +3112,39 @@ TEST_CASE("task_timer")
|
|||
io_service.stop();
|
||||
io_thread.join();
|
||||
} // task_timer
|
||||
|
||||
|
||||
TEST_CASE("trim")
|
||||
{
|
||||
CHECK(utility::trim("") == "");
|
||||
CHECK(utility::trim("0") == "0");
|
||||
CHECK(utility::trim(" a") == "a");
|
||||
CHECK(utility::trim("b ") == "b");
|
||||
CHECK(utility::trim(" c ") == "c");
|
||||
CHECK(utility::trim(" a b ") == "a b");
|
||||
CHECK(utility::trim(" ") == "");
|
||||
}
|
||||
|
||||
TEST_CASE("string_equals")
|
||||
{
|
||||
CHECK(utility::string_equals("a", "aa") == false);
|
||||
CHECK(utility::string_equals("a", "b") == false);
|
||||
CHECK(utility::string_equals("", "") == true);
|
||||
CHECK(utility::string_equals("abc", "abc") == true);
|
||||
CHECK(utility::string_equals("ABC", "abc") == true);
|
||||
|
||||
CHECK(utility::string_equals("a", "aa", true) == false);
|
||||
CHECK(utility::string_equals("a", "b", true) == false);
|
||||
CHECK(utility::string_equals("", "", true) == true);
|
||||
CHECK(utility::string_equals("abc", "abc", true) == true);
|
||||
CHECK(utility::string_equals("ABC", "abc", true) == false);
|
||||
}
|
||||
|
||||
TEST_CASE("lexical_cast")
|
||||
{
|
||||
CHECK(utility::lexical_cast<int>(4) == 4);
|
||||
CHECK(utility::lexical_cast<double>(4) == 4.0);
|
||||
CHECK(utility::lexical_cast<int>("5") == 5);
|
||||
CHECK(utility::lexical_cast<string>(4) == "4");
|
||||
CHECK(utility::lexical_cast<float>("10", 2) == 10.0f);
|
||||
}
|
||||
|
|
57
vcpkg.json
57
vcpkg.json
|
@ -3,32 +3,7 @@
|
|||
"version-string": "master",
|
||||
"dependencies": [
|
||||
{
|
||||
"name": "boost-array",
|
||||
"version>=": "1.70.0"
|
||||
},
|
||||
{
|
||||
"name": "boost-algorithm",
|
||||
"version>=": "1.70.0"
|
||||
},
|
||||
{
|
||||
"name": "boost-asio",
|
||||
"version>=": "1.70.0"
|
||||
},
|
||||
{
|
||||
"name": "boost-date-time",
|
||||
"version>=": "1.70.0"
|
||||
},
|
||||
{
|
||||
"name": "boost-functional",
|
||||
"version>=": "1.70.0"
|
||||
},
|
||||
{
|
||||
"name": "boost-lexical-cast",
|
||||
"version>=": "1.70.0"
|
||||
},
|
||||
{
|
||||
"name": "boost-optional",
|
||||
"version>=": "1.70.0"
|
||||
"name": "asio"
|
||||
},
|
||||
{
|
||||
"name": "openssl"
|
||||
|
@ -37,35 +12,5 @@
|
|||
"name": "zlib"
|
||||
}
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"name": "boost-array",
|
||||
"version": "1.70.0"
|
||||
},
|
||||
{
|
||||
"name": "boost-algorithm",
|
||||
"version": "1.70.0"
|
||||
},
|
||||
{
|
||||
"name": "boost-asio",
|
||||
"version-semver": "1.70.0-2"
|
||||
},
|
||||
{
|
||||
"name": "boost-date-time",
|
||||
"version": "1.70.0"
|
||||
},
|
||||
{
|
||||
"name": "boost-functional",
|
||||
"version": "1.70.0"
|
||||
},
|
||||
{
|
||||
"name": "boost-lexical-cast",
|
||||
"version": "1.70.0"
|
||||
},
|
||||
{
|
||||
"name": "boost-optional",
|
||||
"version": "1.70.0"
|
||||
}
|
||||
],
|
||||
"builtin-baseline": "44d94c2edbd44f0c01d66c2ad95eb6982a9a61bc"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue