From 7e62c3238b536ce5411da03a07934248a808d182 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Fri, 20 Aug 2021 20:16:05 +0800 Subject: [PATCH] format code with clang-format11 --- examples/client/main.cpp | 998 ++++++++-------- examples/server/main.cpp | 224 ++-- examples/server/qps.h | 39 +- include/rest_rpc.hpp | 4 +- include/rest_rpc/client_util.hpp | 54 +- include/rest_rpc/codec.h | 42 +- include/rest_rpc/connection.h | 625 ++++++----- include/rest_rpc/const_vars.h | 62 +- include/rest_rpc/cplusplus_14.h | 85 +- include/rest_rpc/io_service_pool.h | 31 +- include/rest_rpc/meta_util.hpp | 209 ++-- include/rest_rpc/nonstd_any.hpp | 770 ++++++------- include/rest_rpc/router.h | 334 +++--- include/rest_rpc/rpc_client.hpp | 44 +- include/rest_rpc/rpc_server.h | 367 +++--- include/rest_rpc/string_view.hpp | 1685 +++++++++++++++------------- include/rest_rpc/use_asio.hpp | 23 +- 17 files changed, 2839 insertions(+), 2757 deletions(-) diff --git a/examples/client/main.cpp b/examples/client/main.cpp index 05cd558..19aaef3 100644 --- a/examples/client/main.cpp +++ b/examples/client/main.cpp @@ -1,606 +1,608 @@ -#include -#include #include #include +#include +#include using namespace rest_rpc; using namespace rest_rpc::rpc_service; void test_add() { - try { - rpc_client client("127.0.0.1", 9000); - bool r = client.connect(); - if (!r) { - std::cout << "connect timeout" << std::endl; - return; - } + try { + rpc_client client("127.0.0.1", 9000); + bool r = client.connect(); + if (!r) { + std::cout << "connect timeout" << std::endl; + return; + } - { - auto result = client.call("add", 1, 2); - std::cout << result << std::endl; - } + { + auto result = client.call("add", 1, 2); + std::cout << result << std::endl; + } - { - auto result = client.call<2000, int>("add", 1, 2); - std::cout << result << std::endl; - } - } - catch (const std::exception & e) { - std::cout << e.what() << std::endl; - } + { + auto result = client.call<2000, int>("add", 1, 2); + std::cout << result << std::endl; + } + } catch (const std::exception &e) { + std::cout << e.what() << std::endl; + } } void test_translate() { - try { - rpc_client client("127.0.0.1", 9000); - bool r = client.connect(); - if (!r) { - std::cout << "connect timeout" << std::endl; - return; - } + try { + rpc_client client("127.0.0.1", 9000); + bool r = client.connect(); + if (!r) { + std::cout << "connect timeout" << std::endl; + return; + } - auto result = client.call("translate", "hello"); - std::cout << result << std::endl; - } - catch (const std::exception & e) { - std::cout << e.what() << std::endl; - } + auto result = client.call("translate", "hello"); + std::cout << result << std::endl; + } catch (const std::exception &e) { + std::cout << e.what() << std::endl; + } } void test_hello() { - try { - rpc_client client("127.0.0.1", 9000); - bool r = client.connect(); - if (!r) { - std::cout << "connect timeout" << std::endl; - return; - } + try { + rpc_client client("127.0.0.1", 9000); + bool r = client.connect(); + if (!r) { + std::cout << "connect timeout" << std::endl; + return; + } - client.call("hello", "purecpp"); - } - catch (const std::exception & e) { - std::cout << e.what() << std::endl; - } + client.call("hello", "purecpp"); + } catch (const std::exception &e) { + std::cout << e.what() << std::endl; + } } struct person { - int id; - std::string name; - int age; + int id; + std::string name; + int age; - MSGPACK_DEFINE(id, name, age); + MSGPACK_DEFINE(id, name, age); }; void test_get_person_name() { - try { - rpc_client client("127.0.0.1", 9000); - bool r = client.connect(); - if (!r) { - std::cout << "connect timeout" << std::endl; - return; - } + try { + rpc_client client("127.0.0.1", 9000); + bool r = client.connect(); + if (!r) { + std::cout << "connect timeout" << std::endl; + return; + } - auto result = client.call("get_person_name", person{ 1, "tom", 20 }); - std::cout << result << std::endl; - } - catch (const std::exception & e) { - std::cout << e.what() << std::endl; - } + auto result = + client.call("get_person_name", person{1, "tom", 20}); + std::cout << result << std::endl; + } catch (const std::exception &e) { + std::cout << e.what() << std::endl; + } } void test_get_person() { - try { - rpc_client client("127.0.0.1", 9000); - bool r = client.connect(); - if (!r) { - std::cout << "connect timeout" << std::endl; - return; - } + try { + rpc_client client("127.0.0.1", 9000); + bool r = client.connect(); + if (!r) { + std::cout << "connect timeout" << std::endl; + return; + } - auto result = client.call("get_person"); - std::cout << result.name << std::endl; - } - catch (const std::exception & e) { - std::cout << e.what() << std::endl; - } + auto result = client.call("get_person"); + std::cout << result.name << std::endl; + } catch (const std::exception &e) { + std::cout << e.what() << std::endl; + } } void test_async_client() { - rpc_client client("127.0.0.1", 9000); - bool r = client.connect(); - if (!r) { - std::cout << "connect timeout" << std::endl; - return; - } + rpc_client client("127.0.0.1", 9000); + bool r = client.connect(); + if (!r) { + std::cout << "connect timeout" << std::endl; + return; + } - client.set_error_callback([](boost::system::error_code ec) { - std::cout << ec.message() << std::endl; - }); + client.set_error_callback([](boost::system::error_code ec) { + std::cout << ec.message() << std::endl; + }); - auto f = client.async_call("get_person"); - if (f.wait_for(std::chrono::milliseconds(50)) == std::future_status::timeout) { - std::cout << "timeout" << std::endl; - } - else { - auto p = f.get().as(); - std::cout << p.name << std::endl; - } + auto f = client.async_call("get_person"); + if (f.wait_for(std::chrono::milliseconds(50)) == + std::future_status::timeout) { + std::cout << "timeout" << std::endl; + } else { + auto p = f.get().as(); + std::cout << p.name << std::endl; + } - auto fu = client.async_call("hello", "purecpp"); - fu.get().as(); //no return + auto fu = client.async_call("hello", "purecpp"); + fu.get().as(); // no return - //sync call - client.call("hello", "purecpp"); - auto p = client.call("get_person"); + // sync call + client.call("hello", "purecpp"); + auto p = client.call("get_person"); - std::string str; - std::cin >> str; + std::string str; + std::cin >> str; } void test_upload() { - rpc_client client("127.0.0.1", 9000); - bool r = client.connect(1); - if (!r) { - std::cout << "connect timeout" << std::endl; - return; - } + rpc_client client("127.0.0.1", 9000); + bool r = client.connect(1); + if (!r) { + std::cout << "connect timeout" << std::endl; + return; + } - std::ifstream file("E:/acl.7z", std::ios::binary); - file.seekg(0, std::ios::end); - size_t file_len = file.tellg(); - file.seekg(0, std::ios::beg); - std::string conent; - conent.resize(file_len); - file.read(&conent[0], file_len); - std::cout << file_len << std::endl; + std::ifstream file("E:/acl.7z", std::ios::binary); + file.seekg(0, std::ios::end); + size_t file_len = file.tellg(); + file.seekg(0, std::ios::beg); + std::string conent; + conent.resize(file_len); + file.read(&conent[0], file_len); + std::cout << file_len << std::endl; - { - auto f = client.async_call("upload", "test", conent); - if (f.wait_for(std::chrono::milliseconds(500)) == std::future_status::timeout) { - std::cout << "timeout" << std::endl; - } - else { - f.get().as(); - std::cout << "ok" << std::endl; - } - } - { - auto f = client.async_call("upload", "test1", conent); - if (f.wait_for(std::chrono::milliseconds(500)) == std::future_status::timeout) { - std::cout << "timeout" << std::endl; - } - else { - f.get().as(); - std::cout << "ok" << std::endl; - } - } + { + auto f = client.async_call("upload", "test", conent); + if (f.wait_for(std::chrono::milliseconds(500)) == + std::future_status::timeout) { + std::cout << "timeout" << std::endl; + } else { + f.get().as(); + std::cout << "ok" << std::endl; + } + } + { + auto f = client.async_call("upload", "test1", conent); + if (f.wait_for(std::chrono::milliseconds(500)) == + std::future_status::timeout) { + std::cout << "timeout" << std::endl; + } else { + f.get().as(); + std::cout << "ok" << std::endl; + } + } } void test_download() { - rpc_client client("127.0.0.1", 9000); - bool r = client.connect(1); - if (!r) { - std::cout << "connect timeout" << std::endl; - return; - } + rpc_client client("127.0.0.1", 9000); + bool r = client.connect(1); + if (!r) { + std::cout << "connect timeout" << std::endl; + return; + } - auto f = client.async_call("download", "test"); - if (f.wait_for(std::chrono::milliseconds(500)) == std::future_status::timeout) { - std::cout << "timeout" << std::endl; - } - else { - auto content = f.get().as(); - std::cout << content.size() << std::endl; - std::ofstream file("test", std::ios::binary); - file.write(content.data(), content.size()); - } + auto f = client.async_call("download", "test"); + if (f.wait_for(std::chrono::milliseconds(500)) == + std::future_status::timeout) { + std::cout << "timeout" << std::endl; + } else { + auto content = f.get().as(); + std::cout << content.size() << std::endl; + std::ofstream file("test", std::ios::binary); + file.write(content.data(), content.size()); + } } void test_echo() { - rpc_client client("127.0.0.1", 9000); - bool r = client.connect(); - if (!r) { - std::cout << "connect timeout" << std::endl; - return; - } + rpc_client client("127.0.0.1", 9000); + bool r = client.connect(); + if (!r) { + std::cout << "connect timeout" << std::endl; + return; + } - { - auto result = client.call("echo", "test"); - std::cout << result << std::endl; - } + { + auto result = client.call("echo", "test"); + std::cout << result << std::endl; + } - { - auto result = client.call("async_echo", "test"); - std::cout << result << std::endl; - } + { + auto result = client.call("async_echo", "test"); + std::cout << result << std::endl; + } } void test_sync_client() { - test_add(); - test_translate(); - test_hello(); - test_get_person_name(); - test_get_person(); + test_add(); + test_translate(); + test_hello(); + test_get_person_name(); + test_get_person(); } void test_performance1() { - rpc_client client("127.0.0.1", 9000); - bool r = client.connect(); - if (!r) { - std::cout << "connect timeout" << std::endl; - return; - } + rpc_client client("127.0.0.1", 9000); + bool r = client.connect(); + if (!r) { + std::cout << "connect timeout" << std::endl; + return; + } - person p{ 1, "tom", 20 }; + person p{1, "tom", 20}; - for (size_t i = 0; i < 100000000; i++) { - auto future = client.async_call("get_name", p); - auto status = future.wait_for(std::chrono::seconds(2)); - if (status == std::future_status::deferred) { - std::cout << "deferred\n"; - } - else if (status == std::future_status::timeout) { - std::cout << "timeout\n"; - } - else if (status == std::future_status::ready) { - } - } + for (size_t i = 0; i < 100000000; i++) { + auto future = client.async_call("get_name", p); + auto status = future.wait_for(std::chrono::seconds(2)); + if (status == std::future_status::deferred) { + std::cout << "deferred\n"; + } else if (status == std::future_status::timeout) { + std::cout << "timeout\n"; + } else if (status == std::future_status::ready) { + } + } - std::cout << "finish\n"; + std::cout << "finish\n"; - std::string str; - std::cin >> str; + std::string str; + std::cin >> str; } void multi_client_performance(size_t n) { - std::vector> group; - for (int i = 0; i < n; ++i) { - group.emplace_back(std::make_shared(test_performance1));// []{test_performance1();}); - } - for (auto& p : group) { - p->join(); - } + std::vector> group; + for (int i = 0; i < n; ++i) { + group.emplace_back(std::make_shared( + test_performance1)); // []{test_performance1();}); + } + for (auto &p : group) { + p->join(); + } } void test_performance2() { - rpc_client client("127.0.0.1", 9000); - bool r = client.connect(); - if (!r) { - std::cout << "connect timeout" << std::endl; - return; - } + rpc_client client("127.0.0.1", 9000); + bool r = client.connect(); + if (!r) { + std::cout << "connect timeout" << std::endl; + return; + } - person p{ 1, "tom", 20 }; + person p{1, "tom", 20}; - try { - for (size_t i = 0; i < 100000000; i++) { - client.call("get_name", p); - } - std::cout << "finish\n"; - } - catch (const std::exception & ex) { - std::cout << ex.what() << '\n'; - } + try { + for (size_t i = 0; i < 100000000; i++) { + client.call("get_name", p); + } + std::cout << "finish\n"; + } catch (const std::exception &ex) { + std::cout << ex.what() << '\n'; + } - std::string str; - std::cin >> str; + std::string str; + std::cin >> str; } void test_call_with_timeout() { - rpc_client client; - client.async_connect("127.0.0.1", 9000); + rpc_client client; + client.async_connect("127.0.0.1", 9000); - try { - auto result = client.call<50, person>("get_person"); - std::cout << result.name << std::endl; - client.close(); - bool r = client.connect(); - result = client.call<50, person>("get_person"); - std::cout << result.name << std::endl; - } - catch (const std::exception & ex) { - std::cout << ex.what() << std::endl; - } + try { + auto result = client.call<50, person>("get_person"); + std::cout << result.name << std::endl; + client.close(); + bool r = client.connect(); + result = client.call<50, person>("get_person"); + std::cout << result.name << std::endl; + } catch (const std::exception &ex) { + std::cout << ex.what() << std::endl; + } - std::string str; - std::cin >> str; + std::string str; + std::cin >> str; } void test_connect() { - rpc_client client; - client.enable_auto_reconnect(); //automatic reconnect - client.enable_auto_heartbeat(); //automatic heartbeat - bool r = client.connect("127.0.0.1", 9000); - int count = 0; - while (true) { - if (client.has_connected()) { - std::cout << "connected ok\n"; - break; - } - else { - std::cout << "connected failed: "<< count++<<"\n"; - } - std::this_thread::sleep_for(std::chrono::seconds(1)); - } + rpc_client client; + client.enable_auto_reconnect(); // automatic reconnect + client.enable_auto_heartbeat(); // automatic heartbeat + bool r = client.connect("127.0.0.1", 9000); + int count = 0; + while (true) { + if (client.has_connected()) { + std::cout << "connected ok\n"; + break; + } else { + std::cout << "connected failed: " << count++ << "\n"; + } + std::this_thread::sleep_for(std::chrono::seconds(1)); + } - //{ - // rpc_client client; - // bool r = client.connect("127.0.0.1", 9000); - // int count = 0; - // while (true) { - // if (client.connect()) { - // std::cout << "connected ok\n"; - // break; - // } - // else { - // std::cout << "connected failed: " << count++ << "\n"; - // } - // } - //} + //{ + // rpc_client client; + // bool r = client.connect("127.0.0.1", 9000); + // int count = 0; + // while (true) { + // if (client.connect()) { + // std::cout << "connected ok\n"; + // break; + // } + // else { + // std::cout << "connected failed: " << count++ << "\n"; + // } + // } + //} - std::string str; - std::cin >> str; + std::string str; + std::cin >> str; } void test_callback() { - rpc_client client; - bool r = client.connect("127.0.0.1", 9000); + rpc_client client; + bool r = client.connect("127.0.0.1", 9000); - for (size_t i = 0; i < 100; i++) { - std::string test = "test" + std::to_string(i + 1); - //set timeout 100ms - client.async_call<100>("async_echo", [](const boost::system::error_code & ec, string_view data) { - if (ec) { - std::cout << ec.value() << " timeout" << std::endl; - return; - } + for (size_t i = 0; i < 100; i++) { + std::string test = "test" + std::to_string(i + 1); + // set timeout 100ms + client.async_call<100>( + "async_echo", + [](const boost::system::error_code &ec, string_view data) { + if (ec) { + std::cout << ec.value() << " timeout" << std::endl; + return; + } - auto str = as(data); - std::cout << "echo " << str << '\n'; - }, test); + auto str = as(data); + std::cout << "echo " << str << '\n'; + }, + test); - std::string test1 = "test" + std::to_string(i + 2); - //zero means no timeout check, no param means using default timeout(5s) - client.async_call<0>("echo", [](const boost::system::error_code & ec, string_view data) { - auto str = as(data); - std::cout << "echo " << str << '\n'; - }, test1); - } + std::string test1 = "test" + std::to_string(i + 2); + // zero means no timeout check, no param means using default timeout(5s) + client.async_call<0>( + "echo", + [](const boost::system::error_code &ec, string_view data) { + auto str = as(data); + std::cout << "echo " << str << '\n'; + }, + test1); + } - client.run(); + client.run(); } -void wait_for_notification(rpc_client & client) { - client.async_call<0>("sub", [&client](const boost::system::error_code & ec, string_view data) { - auto str = as(data); - std::cout << str << '\n'; +void wait_for_notification(rpc_client &client) { + client.async_call<0>( + "sub", [&client](const boost::system::error_code &ec, string_view data) { + auto str = as(data); + std::cout << str << '\n'; - wait_for_notification(client); - }); + wait_for_notification(client); + }); } void test_sub1() { - rpc_client client; - client.enable_auto_reconnect(); - client.enable_auto_heartbeat(); - bool r = client.connect("127.0.0.1", 9000); - if (!r) { - return; - } + rpc_client client; + client.enable_auto_reconnect(); + client.enable_auto_heartbeat(); + bool r = client.connect("127.0.0.1", 9000); + if (!r) { + return; + } - client.subscribe("key", [](string_view data) { - std::cout << data << "\n"; - }); + client.subscribe("key", [](string_view data) { std::cout << data << "\n"; }); - client.subscribe("key", "048a796c8a3c6a6b7bd1223bf2c8cee05232e927b521984ba417cb2fca6df9d1", [](string_view data) { - msgpack_codec codec; - person p = codec.unpack(data.data(), data.size()); - std::cout << p.name << "\n"; - }); + client.subscribe( + "key", "048a796c8a3c6a6b7bd1223bf2c8cee05232e927b521984ba417cb2fca6df9d1", + [](string_view data) { + msgpack_codec codec; + person p = codec.unpack(data.data(), data.size()); + std::cout << p.name << "\n"; + }); - client.subscribe("key1", "048a796c8a3c6a6b7bd1223bf2c8cee05232e927b521984ba417cb2fca6df9d1", [](string_view data) { - std::cout << data << "\n"; - }); + client.subscribe( + "key1", + "048a796c8a3c6a6b7bd1223bf2c8cee05232e927b521984ba417cb2fca6df9d1", + [](string_view data) { std::cout << data << "\n"; }); - bool stop = false; - std::thread thd1([&client, &stop] { - while (true) { - try { - if (client.has_connected()) { - int r = client.call("add", 2, 3); - std::cout << "add result: " << r << "\n"; - } - - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - catch (const std::exception& ex) { - std::cout << ex.what() << "\n"; - } - } - }); + bool stop = false; + std::thread thd1([&client, &stop] { + while (true) { + try { + if (client.has_connected()) { + int r = client.call("add", 2, 3); + std::cout << "add result: " << r << "\n"; + } - /*rpc_client client1; - bool r1 = client1.connect("127.0.0.1", 9000); - if (!r1) { - return; - } + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } catch (const std::exception &ex) { + std::cout << ex.what() << "\n"; + } + } + }); - person p{10, "jack", 21}; - client1.publish("key", "hello subscriber"); - client1.publish_by_token("key", "sub_key", p); - - std::thread thd([&client1, p] { - while (true) { - try { - client1.publish("key", "hello subscriber"); - client1.publish_by_token("key", "unique_token", p); - } - catch (const std::exception& ex) { - std::cout << ex.what() << "\n"; - } - } - }); + /*rpc_client client1; + bool r1 = client1.connect("127.0.0.1", 9000); + if (!r1) { + return; + } + + person p{10, "jack", 21}; + client1.publish("key", "hello subscriber"); + client1.publish_by_token("key", "sub_key", p); + + std::thread thd([&client1, p] { + while (true) { + try { + client1.publish("key", "hello subscriber"); + client1.publish_by_token("key", "unique_token", p); + } + catch (const std::exception& ex) { + std::cout << ex.what() << "\n"; + } + } + }); */ - std::string str; - std::cin >> str; + std::string str; + std::cin >> str; } void test_multiple_thread() { - std::vector> cls; - std::vector> v; - for (int j = 0; j < 4; ++j) { - auto client = std::make_shared(); - cls.push_back(client); - bool r = client->connect("127.0.0.1", 9000); - if (!r) { - return; - } + std::vector> cls; + std::vector> v; + for (int j = 0; j < 4; ++j) { + auto client = std::make_shared(); + cls.push_back(client); + bool r = client->connect("127.0.0.1", 9000); + if (!r) { + return; + } - for (size_t i = 0; i < 2; i++) { - person p{ 1, "tom", 20 }; - v.emplace_back(std::make_shared([client] { - person p{ 1, "tom", 20 }; - for (size_t i = 0; i < 1000000; i++) { - client->async_call<0>("get_name", [](const boost::system::error_code & ec, string_view data) { - if (ec) { - std::cout << ec.message() << '\n'; - } - }, p); + for (size_t i = 0; i < 2; i++) { + person p{1, "tom", 20}; + v.emplace_back(std::make_shared([client] { + person p{1, "tom", 20}; + for (size_t i = 0; i < 1000000; i++) { + client->async_call<0>( + "get_name", + [](const boost::system::error_code &ec, string_view data) { + if (ec) { + std::cout << ec.message() << '\n'; + } + }, + p); - //auto future = client->async_call("get_name", p); - //auto status = future.wait_for(std::chrono::seconds(2)); - //if (status == std::future_status::deferred) { - // std::cout << "deferred\n"; - //} - //else if (status == std::future_status::timeout) { - // std::cout << "timeout\n"; - //} - //else if (status == std::future_status::ready) { - //} + // auto future = client->async_call("get_name", p); + // auto status = future.wait_for(std::chrono::seconds(2)); + // if (status == std::future_status::deferred) { + // std::cout << "deferred\n"; + //} + // else if (status == std::future_status::timeout) { + // std::cout << "timeout\n"; + //} + // else if (status == std::future_status::ready) { + //} - //client->call("get_name", p); - } - })); - } - } + // client->call("get_name", p); + } + })); + } + } - - std::string str; - std::cin >> str; + std::string str; + std::cin >> str; } void test_threads() { - rpc_client client; - bool r = client.connect("127.0.0.1", 9000); - if (!r) { - return; - } + rpc_client client; + bool r = client.connect("127.0.0.1", 9000); + if (!r) { + return; + } - std::thread thd1([&client] { - for (size_t i = 0; i < 1000000; i++) { - auto future = client.async_call("echo", "test"); - auto status = future.wait_for(std::chrono::seconds(2)); - if (status == std::future_status::timeout) { - std::cout << "timeout\n"; - } - else if (status == std::future_status::ready) { - std::string content = future.get().as(); - } + std::thread thd1([&client] { + for (size_t i = 0; i < 1000000; i++) { + auto future = client.async_call("echo", "test"); + auto status = future.wait_for(std::chrono::seconds(2)); + if (status == std::future_status::timeout) { + std::cout << "timeout\n"; + } else if (status == std::future_status::ready) { + std::string content = future.get().as(); + } - std::this_thread::sleep_for(std::chrono::microseconds(2)); - } - std::cout << "thread2 finished" << '\n'; - }); - - std::thread thd2([&client] { - for (size_t i = 1000000; i < 2*1000000; i++) { - client.async_call("get_int", [i](boost::system::error_code ec, string_view data) { - if (ec) { - std::cout << ec.message() << '\n'; - return; - } - int r = as(data); - if (r != i) { - std::cout << "error not match" << '\n'; - } - }, i); - std::this_thread::sleep_for(std::chrono::microseconds(2)); - } + std::this_thread::sleep_for(std::chrono::microseconds(2)); + } + std::cout << "thread2 finished" << '\n'; + }); - std::cout << "thread2 finished" << '\n'; - }); + std::thread thd2([&client] { + for (size_t i = 1000000; i < 2 * 1000000; i++) { + client.async_call( + "get_int", + [i](boost::system::error_code ec, string_view data) { + if (ec) { + std::cout << ec.message() << '\n'; + return; + } + int r = as(data); + if (r != i) { + std::cout << "error not match" << '\n'; + } + }, + i); + std::this_thread::sleep_for(std::chrono::microseconds(2)); + } - for (size_t i = 2*1000000; i < 3 * 1000000; i++) { - auto future = client.async_call("echo", "test"); - auto status = future.wait_for(std::chrono::seconds(2)); - if (status == std::future_status::timeout) { - std::cout << "timeout\n"; - } - else if (status == std::future_status::ready) { - std::string content = future.get().as(); - } - std::this_thread::sleep_for(std::chrono::microseconds(2)); - } - std::cout << "thread finished" << '\n'; - - std::string str; - std::cin >> str; + std::cout << "thread2 finished" << '\n'; + }); + + for (size_t i = 2 * 1000000; i < 3 * 1000000; i++) { + auto future = client.async_call("echo", "test"); + auto status = future.wait_for(std::chrono::seconds(2)); + if (status == std::future_status::timeout) { + std::cout << "timeout\n"; + } else if (status == std::future_status::ready) { + std::string content = future.get().as(); + } + std::this_thread::sleep_for(std::chrono::microseconds(2)); + } + std::cout << "thread finished" << '\n'; + + std::string str; + std::cin >> str; } void test_ssl() { - bool is_ssl = true; - rpc_client client; - client.set_error_callback([](boost::system::error_code ec) { - std::cout << ec.message() << "\n"; - }); + bool is_ssl = true; + rpc_client client; + client.set_error_callback( + [](boost::system::error_code ec) { std::cout << ec.message() << "\n"; }); #ifdef CINATRA_ENABLE_SSL - client.set_ssl_context_callback([](boost::asio::ssl::context& ctx) { - ctx.set_verify_mode(boost::asio::ssl::context::verify_peer); - ctx.load_verify_file("server.crt"); - }); + client.set_ssl_context_callback([](boost::asio::ssl::context &ctx) { + ctx.set_verify_mode(boost::asio::ssl::context::verify_peer); + ctx.load_verify_file("server.crt"); + }); #endif - bool r = client.connect("127.0.0.1", 9000, is_ssl); - if (!r) { - return; + bool r = client.connect("127.0.0.1", 9000, is_ssl); + if (!r) { + return; + } + + for (size_t i = 0; i < 100; i++) { + try { + auto result = client.call("echo", "purecpp"); + std::cout << result << " sync\n"; + } catch (const std::exception &e) { + std::cout << e.what() << " sync\n"; } - for (size_t i = 0; i < 100; i++) { - try { - auto result = client.call("echo", "purecpp"); - std::cout << result << " sync\n"; - } - catch (const std::exception& e) { - std::cout << e.what() << " sync\n"; - } - - auto future = client.async_call("echo", "purecpp"); - auto status = future.wait_for(std::chrono::milliseconds(5000)); - if (status == std::future_status::timeout) { - std::cout << "timeout future\n"; - } - else { - auto result1 = future.get(); - std::cout << result1.as() << " future\n"; - } - - client.async_call("echo", [](boost::system::error_code ec, string_view data) { - if (ec) { - std::cout << ec.message() <<" "<< data << "\n"; - return; - } - - auto result = as(data); - std::cout << result << " async\n"; - }, "purecpp"); + auto future = client.async_call("echo", "purecpp"); + auto status = future.wait_for(std::chrono::milliseconds(5000)); + if (status == std::future_status::timeout) { + std::cout << "timeout future\n"; + } else { + auto result1 = future.get(); + std::cout << result1.as() << " future\n"; } - std::getchar(); + client.async_call( + "echo", + [](boost::system::error_code ec, string_view data) { + if (ec) { + std::cout << ec.message() << " " << data << "\n"; + return; + } + + auto result = as(data); + std::cout << result << " async\n"; + }, + "purecpp"); + } + + std::getchar(); } -void benchmark_test(){ +void benchmark_test() { rpc_client client; bool r = client.connect("127.0.0.1", 9000); if (!r) { @@ -608,33 +610,35 @@ void benchmark_test(){ } for (size_t i = 0; i < 1000000; i++) { - client.async_call("echo", [i](boost::system::error_code ec, string_view data) { - if (ec) { - return; - } - - }, "hello wolrd"); + client.async_call( + "echo", + [i](boost::system::error_code ec, string_view data) { + if (ec) { + return; + } + }, + "hello wolrd"); } std::getchar(); - std::cout<<"benchmark test finished\n"; + std::cout << "benchmark test finished\n"; } int main() { benchmark_test(); - test_connect(); - test_callback(); - test_echo(); - test_sync_client(); - test_async_client(); - test_threads(); - test_sub1(); - test_call_with_timeout(); - test_connect(); - test_upload(); - test_download(); - multi_client_performance(20); - test_performance1(); - test_multiple_thread(); - return 0; + test_connect(); + test_callback(); + test_echo(); + test_sync_client(); + test_async_client(); + test_threads(); + test_sub1(); + test_call_with_timeout(); + test_connect(); + test_upload(); + test_download(); + multi_client_performance(20); + test_performance1(); + test_multiple_thread(); + return 0; } \ No newline at end of file diff --git a/examples/server/main.cpp b/examples/server/main.cpp index fbe3210..f4c095c 100644 --- a/examples/server/main.cpp +++ b/examples/server/main.cpp @@ -5,153 +5,157 @@ using namespace rpc_service; #include "qps.h" -struct dummy{ - int add(rpc_conn conn, int a, int b) { - auto shared_conn = conn.lock(); - if (shared_conn) { - shared_conn->set_user_data(std::string("aa")); - auto s = conn.lock()->get_user_data(); - std::cout << s << '\n'; //aa - } +struct dummy { + int add(rpc_conn conn, int a, int b) { + auto shared_conn = conn.lock(); + if (shared_conn) { + shared_conn->set_user_data(std::string("aa")); + auto s = conn.lock()->get_user_data(); + std::cout << s << '\n'; // aa + } - return a + b; - } + return a + b; + } }; -std::string translate(rpc_conn conn, const std::string& orignal) { - std::string temp = orignal; - for (auto& c : temp) { - c = std::toupper(c); - } - return temp; +std::string translate(rpc_conn conn, const std::string &orignal) { + std::string temp = orignal; + for (auto &c : temp) { + c = std::toupper(c); + } + return temp; } -void hello(rpc_conn conn, const std::string& str) { - std::cout << "hello " << str << std::endl; +void hello(rpc_conn conn, const std::string &str) { + std::cout << "hello " << str << std::endl; } struct person { - int id; - std::string name; - int age; + int id; + std::string name; + int age; - MSGPACK_DEFINE(id, name, age); + MSGPACK_DEFINE(id, name, age); }; -std::string get_person_name(rpc_conn conn, const person& p) { - return p.name; +std::string get_person_name(rpc_conn conn, const person &p) { return p.name; } + +person get_person(rpc_conn conn) { return {1, "tom", 20}; } + +void upload(rpc_conn conn, const std::string &filename, + const std::string &content) { + std::cout << content.size() << std::endl; + std::ofstream file(filename, std::ios::binary); + file.write(content.data(), content.size()); } -person get_person(rpc_conn conn) { - return { 1, "tom", 20 }; -} +std::string download(rpc_conn conn, const std::string &filename) { + std::ifstream file(filename, std::ios::binary); + if (!file) { + return ""; + } -void upload(rpc_conn conn, const std::string& filename, const std::string& content) { - std::cout << content.size() << std::endl; - std::ofstream file(filename, std::ios::binary); - file.write(content.data(), content.size()); -} + file.seekg(0, std::ios::end); + size_t file_len = file.tellg(); + file.seekg(0, std::ios::beg); + std::string content; + content.resize(file_len); + file.read(&content[0], file_len); + std::cout << file_len << std::endl; -std::string download(rpc_conn conn, const std::string& filename) { - std::ifstream file(filename, std::ios::binary); - if (!file) { - return ""; - } - - file.seekg(0, std::ios::end); - size_t file_len = file.tellg(); - file.seekg(0, std::ios::beg); - std::string content; - content.resize(file_len); - file.read(&content[0], file_len); - std::cout << file_len << std::endl; - - return content; + return content; } qps g_qps; -std::string get_name(rpc_conn conn, const person& p) { - g_qps.increase(); - return p.name; -} - -//if you want to response later, you can use async model, you can control when to response -void async_echo(rpc_conn conn, const std::string& src) { - auto req_id = conn.lock()->request_id();//note: you need keep the request id at that time, and pass it into the async thread - - std::thread thd([conn, req_id, src] { - std::this_thread::sleep_for(std::chrono::seconds(1)); - auto conn_sp = conn.lock(); - if (conn_sp) { - conn_sp->pack_and_response(req_id, std::move(src)); - } - }); - thd.detach(); -} - -std::string echo(rpc_conn conn, const std::string& src) { +std::string get_name(rpc_conn conn, const person &p) { g_qps.increase(); - return src; + return p.name; } -int get_int(rpc_conn conn, int val) { - return val; +// if you want to response later, you can use async model, you can control when +// to response +void async_echo(rpc_conn conn, const std::string &src) { + auto req_id = + conn.lock()->request_id(); // note: you need keep the request id at that + // time, and pass it into the async thread + + std::thread thd([conn, req_id, src] { + std::this_thread::sleep_for(std::chrono::seconds(1)); + auto conn_sp = conn.lock(); + if (conn_sp) { + conn_sp->pack_and_response(req_id, std::move(src)); + } + }); + thd.detach(); } +std::string echo(rpc_conn conn, const std::string &src) { + g_qps.increase(); + return src; +} + +int get_int(rpc_conn conn, int val) { return val; } + void test_ssl() { - rpc_server server(9000, std::thread::hardware_concurrency(), { "server.crt", "server.key" }); - server.register_handler("hello", hello); - server.register_handler("echo", echo); - server.run(); + rpc_server server(9000, std::thread::hardware_concurrency(), + {"server.crt", "server.key"}); + server.register_handler("hello", hello); + server.register_handler("echo", echo); + server.run(); } -void benchmark_test(){ +void benchmark_test() { rpc_server server(9000, std::thread::hardware_concurrency()); server.register_handler("echo", echo); server.run(); } int main() { -// benchmark_test(); - rpc_server server(9000, std::thread::hardware_concurrency()); + // benchmark_test(); + rpc_server server(9000, std::thread::hardware_concurrency()); - dummy d; - server.register_handler("add", &dummy::add, &d); - server.register_handler("translate", translate); - server.register_handler("hello", hello); - server.register_handler("get_person_name", get_person_name); - server.register_handler("get_person", get_person); - server.register_handler("upload", upload); - server.register_handler("download", download); - server.register_handler("get_name", get_name); - server.register_handler("async_echo", async_echo); - server.register_handler("echo", echo); - server.register_handler("get_int", get_int); + dummy d; + server.register_handler("add", &dummy::add, &d); + server.register_handler("translate", translate); + server.register_handler("hello", hello); + server.register_handler("get_person_name", get_person_name); + server.register_handler("get_person", get_person); + server.register_handler("upload", upload); + server.register_handler("download", download); + server.register_handler("get_name", get_name); + server.register_handler("async_echo", async_echo); + server.register_handler("echo", echo); + server.register_handler("get_int", get_int); - server.register_handler("publish_by_token", [&server](rpc_conn conn, std::string key, std::string token, std::string val) { - server.publish_by_token(std::move(key), std::move(token), std::move(val)); - }); + server.register_handler("publish_by_token", [&server](rpc_conn conn, + std::string key, + std::string token, + std::string val) { + server.publish_by_token(std::move(key), std::move(token), std::move(val)); + }); - server.register_handler("publish", [&server](rpc_conn conn, std::string key, std::string token, std::string val) { - server.publish(std::move(key), std::move(val)); - }); + server.register_handler("publish", + [&server](rpc_conn conn, std::string key, + std::string token, std::string val) { + server.publish(std::move(key), std::move(val)); + }); - std::thread thd([&server] { - person p{ 1, "tom", 20 }; - while (true) { - server.publish("key", "hello subscriber"); - auto list = server.get_token_list(); - for (auto& token : list) { - server.publish_by_token("key", token, p); - server.publish_by_token("key1", token, "hello subscriber1"); - } - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - } - }); + std::thread thd([&server] { + person p{1, "tom", 20}; + while (true) { + server.publish("key", "hello subscriber"); + auto list = server.get_token_list(); + for (auto &token : list) { + server.publish_by_token("key", token, p); + server.publish_by_token("key1", token, "hello subscriber1"); + } + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + }); - server.run(); + server.run(); - std::string str; - std::cin >> str; + std::string str; + std::cin >> str; } \ No newline at end of file diff --git a/examples/server/qps.h b/examples/server/qps.h index 408a520..5a700bf 100644 --- a/examples/server/qps.h +++ b/examples/server/qps.h @@ -1,31 +1,30 @@ #pragma once #include -#include #include +#include class qps { public: - void increase() { - counter_.fetch_add(1, std::memory_order_release); - } + void increase() { counter_.fetch_add(1, std::memory_order_release); } - qps() : counter_(0) { - thd_ = std::thread([this] { - while (!stop_) { - std::cout << "qps: " << counter_.load(std::memory_order_acquire) << '\n'; - std::this_thread::sleep_for(std::chrono::seconds(1)); - //counter_.store(0, std::memory_order_release); - } - }); - } + qps() : counter_(0) { + thd_ = std::thread([this] { + while (!stop_) { + std::cout << "qps: " << counter_.load(std::memory_order_acquire) + << '\n'; + std::this_thread::sleep_for(std::chrono::seconds(1)); + // counter_.store(0, std::memory_order_release); + } + }); + } - ~qps() { - stop_ = true; - thd_.join(); - } + ~qps() { + stop_ = true; + thd_.join(); + } private: - bool stop_ = false; - std::thread thd_; - std::atomic counter_; + bool stop_ = false; + std::thread thd_; + std::atomic counter_; }; \ No newline at end of file diff --git a/include/rest_rpc.hpp b/include/rest_rpc.hpp index 4a7f6ae..31cd532 100644 --- a/include/rest_rpc.hpp +++ b/include/rest_rpc.hpp @@ -1,2 +1,2 @@ -#include "rest_rpc/rpc_server.h" -#include "rest_rpc/rpc_client.hpp" \ No newline at end of file +#include "rest_rpc/rpc_client.hpp" +#include "rest_rpc/rpc_server.h" \ No newline at end of file diff --git a/include/rest_rpc/client_util.hpp b/include/rest_rpc/client_util.hpp index b9e164e..9369ec7 100644 --- a/include/rest_rpc/client_util.hpp +++ b/include/rest_rpc/client_util.hpp @@ -16,37 +16,35 @@ using string_view = boost::string_view; #include "codec.h" namespace rest_rpc { - inline bool has_error(string_view result) { - if (result.empty()) { - return true; - } +inline bool has_error(string_view result) { + if (result.empty()) { + return true; + } - rpc_service::msgpack_codec codec; - auto tp = codec.unpack>(result.data(), result.size()); + rpc_service::msgpack_codec codec; + auto tp = codec.unpack>(result.data(), result.size()); - return std::get<0>(tp) != 0; - } + return std::get<0>(tp) != 0; +} - template - inline T get_result(string_view result) { - rpc_service::msgpack_codec codec; - auto tp = codec.unpack>(result.data(), result.size()); - return std::get<1>(tp); - } +template inline T get_result(string_view result) { + rpc_service::msgpack_codec codec; + auto tp = codec.unpack>(result.data(), result.size()); + return std::get<1>(tp); +} +inline std::string get_error_msg(string_view result) { + rpc_service::msgpack_codec codec; + auto tp = + codec.unpack>(result.data(), result.size()); + return std::get<1>(tp); +} - inline std::string get_error_msg(string_view result) { - rpc_service::msgpack_codec codec; - auto tp = codec.unpack>(result.data(), result.size()); - return std::get<1>(tp); - } +template inline T as(string_view result) { + if (has_error(result)) { + throw std::logic_error(get_error_msg(result)); + } - template - inline T as(string_view result) { - if (has_error(result)) { - throw std::logic_error(get_error_msg(result)); - } - - return get_result(result); - } -} \ No newline at end of file + return get_result(result); +} +} // namespace rest_rpc \ No newline at end of file diff --git a/include/rest_rpc/codec.h b/include/rest_rpc/codec.h index 0b642f5..5c95b80 100644 --- a/include/rest_rpc/codec.h +++ b/include/rest_rpc/codec.h @@ -6,44 +6,44 @@ namespace rest_rpc { namespace rpc_service { - using buffer_type = msgpack::sbuffer; - struct msgpack_codec { +using buffer_type = msgpack::sbuffer; +struct msgpack_codec { const static size_t init_size = 2 * 1024; - template - static buffer_type pack_args(Args&&... args) { - buffer_type buffer(init_size); + template static buffer_type pack_args(Args &&...args) { + buffer_type buffer(init_size); msgpack::pack(buffer, std::forward_as_tuple(std::forward(args)...)); return buffer; } - template::value>::type> - static std::string pack_args_str(Arg arg, Args&&... args) { - buffer_type buffer(init_size); - msgpack::pack(buffer, std::forward_as_tuple((int)arg, std::forward(args)...)); - return std::string(buffer.data(), buffer.size()); + template ::value>::type> + static std::string pack_args_str(Arg arg, Args &&...args) { + buffer_type buffer(init_size); + msgpack::pack(buffer, + std::forward_as_tuple((int)arg, std::forward(args)...)); + return std::string(buffer.data(), buffer.size()); } - template - buffer_type pack(T&& t) const { - buffer_type buffer; + template buffer_type pack(T &&t) const { + buffer_type buffer; msgpack::pack(buffer, std::forward(t)); return buffer; } - template - T unpack(char const* data, size_t length) { + template T unpack(char const *data, size_t length) { try { msgpack::unpack(msg_, data, length); return msg_.get().as(); - } catch (...) { throw std::invalid_argument("unpack failed: Args not match!"); } + } catch (...) { + throw std::invalid_argument("unpack failed: Args not match!"); + } } - private: +private: msgpack::unpacked msg_; }; -} // namespace rpc_service -} // namespace rest_rpc +} // namespace rpc_service +} // namespace rest_rpc -#endif // REST_RPC_CODEC_H_ \ No newline at end of file +#endif // REST_RPC_CODEC_H_ \ No newline at end of file diff --git a/include/rest_rpc/connection.h b/include/rest_rpc/connection.h index f6885cb..973f22e 100644 --- a/include/rest_rpc/connection.h +++ b/include/rest_rpc/connection.h @@ -1,383 +1,394 @@ #ifndef REST_RPC_CONNECTION_H_ #define REST_RPC_CONNECTION_H_ -#include -#include -#include -#include -#include "use_asio.hpp" #include "const_vars.h" -#include "router.h" #include "cplusplus_14.h" #include "nonstd_any.hpp" +#include "router.h" +#include "use_asio.hpp" +#include +#include +#include +#include using boost::asio::ip::tcp; namespace rest_rpc { - namespace rpc_service { - struct ssl_configure { - std::string cert_file; - std::string key_file; - }; +namespace rpc_service { +struct ssl_configure { + std::string cert_file; + std::string key_file; +}; - class connection : public std::enable_shared_from_this, private asio::noncopyable { - public: - connection(boost::asio::io_service& io_service, std::size_t timeout_seconds, router& router) - : socket_(io_service), - body_(INIT_BUF_SIZE), - timer_(io_service), - timeout_seconds_(timeout_seconds), - has_closed_(false), - router_(router){ - } +class connection : public std::enable_shared_from_this, + private asio::noncopyable { +public: + connection(boost::asio::io_service &io_service, std::size_t timeout_seconds, + router &router) + : socket_(io_service), body_(INIT_BUF_SIZE), timer_(io_service), + timeout_seconds_(timeout_seconds), has_closed_(false), router_(router) { + } - ~connection() { - close(); - } + ~connection() { close(); } - void start() { - if (is_ssl() && !has_shake_) { - async_handshake(); - } - else { - read_head(); - } - } + void start() { + if (is_ssl() && !has_shake_) { + async_handshake(); + } else { + read_head(); + } + } - tcp::socket& socket() { return socket_; } + tcp::socket &socket() { return socket_; } - bool has_closed() const { return has_closed_; } - uint64_t request_id() const { - return req_id_; - } + bool has_closed() const { return has_closed_; } + uint64_t request_id() const { return req_id_; } - void response(uint64_t req_id, std::string data, request_type req_type = request_type::req_res) { - auto len = data.size(); - assert(len < MAX_BUF_LEN); + void response(uint64_t req_id, std::string data, + request_type req_type = request_type::req_res) { + auto len = data.size(); + assert(len < MAX_BUF_LEN); - std::unique_lock lock(write_mtx_); - write_queue_.emplace_back(message_type{ req_id, req_type, std::make_shared(std::move(data)) }); - if (write_queue_.size() > 1) { - return; - } + std::unique_lock lock(write_mtx_); + write_queue_.emplace_back(message_type{ + req_id, req_type, std::make_shared(std::move(data))}); + if (write_queue_.size() > 1) { + return; + } - write(); - } + write(); + } - template - void pack_and_response(uint64_t req_id, T data) { - auto result = msgpack_codec::pack_args_str(result_code::OK, std::move(data)); - response(req_id, std::move(result)); - } + template void pack_and_response(uint64_t req_id, T data) { + auto result = + msgpack_codec::pack_args_str(result_code::OK, std::move(data)); + response(req_id, std::move(result)); + } - void set_conn_id(int64_t id) { conn_id_ = id; } + void set_conn_id(int64_t id) { conn_id_ = id; } - int64_t conn_id() const { return conn_id_; } + int64_t conn_id() const { return conn_id_; } - template - void set_user_data(const T &data) { - user_data_ = data; - } + template void set_user_data(const T &data) { user_data_ = data; } - template - T get_user_data() { - return nonstd::any_cast(user_data_); - } + template T get_user_data() { + return nonstd::any_cast(user_data_); + } - const std::vector& body() const { - return body_; - } + const std::vector &body() const { return body_; } - std::string remote_address() const { - if (has_closed_) { - return ""; - } + std::string remote_address() const { + if (has_closed_) { + return ""; + } - return socket_.remote_endpoint().address().to_string(); - } - - void publish(const std::string& key, const std::string& data) { - auto result = msgpack_codec::pack_args_str(result_code::OK, key, data); - response(0, std::move(result), request_type::sub_pub); - } + return socket_.remote_endpoint().address().to_string(); + } - void set_callback(std::function)> callback) { - callback_ = std::move(callback); - } + void publish(const std::string &key, const std::string &data) { + auto result = msgpack_codec::pack_args_str(result_code::OK, key, data); + response(0, std::move(result), request_type::sub_pub); + } - void init_ssl_context(const ssl_configure& ssl_conf) { + void set_callback( + std::function)> + callback) { + callback_ = std::move(callback); + } + + void init_ssl_context(const ssl_configure &ssl_conf) { #ifdef CINATRA_ENABLE_SSL - unsigned long ssl_options = boost::asio::ssl::context::default_workarounds - | boost::asio::ssl::context::no_sslv2 - | boost::asio::ssl::context::single_dh_use; - try { - boost::asio::ssl::context ssl_context(boost::asio::ssl::context::sslv23); - ssl_context.set_options(ssl_options); - ssl_context.set_password_callback([](std::size_t size, - boost::asio::ssl::context_base::password_purpose purpose) {return "123456"; }); + unsigned long ssl_options = boost::asio::ssl::context::default_workarounds | + boost::asio::ssl::context::no_sslv2 | + boost::asio::ssl::context::single_dh_use; + try { + boost::asio::ssl::context ssl_context(boost::asio::ssl::context::sslv23); + ssl_context.set_options(ssl_options); + ssl_context.set_password_callback( + [](std::size_t size, + boost::asio::ssl::context_base::password_purpose purpose) { + return "123456"; + }); - boost::system::error_code ec; - if (rpcfs::exists(ssl_conf.cert_file, ec)) { - ssl_context.use_certificate_chain_file(ssl_conf.cert_file); - } + boost::system::error_code ec; + if (rpcfs::exists(ssl_conf.cert_file, ec)) { + ssl_context.use_certificate_chain_file(ssl_conf.cert_file); + } - if (rpcfs::exists(ssl_conf.key_file, ec)) - ssl_context.use_private_key_file(ssl_conf.key_file, boost::asio::ssl::context::pem); + if (rpcfs::exists(ssl_conf.key_file, ec)) + ssl_context.use_private_key_file(ssl_conf.key_file, + boost::asio::ssl::context::pem); - //ssl_context_callback(ssl_context); - ssl_stream_ = std::make_unique>(socket_, ssl_context); - } - catch (const std::exception& e) { - print(e); - } + // ssl_context_callback(ssl_context); + ssl_stream_ = std::make_unique< + boost::asio::ssl::stream>( + socket_, ssl_context); + } catch (const std::exception &e) { + print(e); + } #endif + } + +private: + void read_head() { + reset_timer(); + auto self(this->shared_from_this()); + async_read_head( + [this, self](boost::system::error_code ec, std::size_t length) { + if (!socket_.is_open()) { + // LOG(INFO) << "socket already closed"; + return; + } + + if (!ec) { + // const uint32_t body_len = *((int*)(head_)); + // req_id_ = *((std::uint64_t*)(head_ + sizeof(int32_t))); + rpc_header *header = (rpc_header *)(head_); + req_id_ = header->req_id; + const uint32_t body_len = header->body_len; + req_type_ = header->req_type; + if (body_len > 0 && body_len < MAX_BUF_LEN) { + if (body_.size() < body_len) { + body_.resize(body_len); + } + read_body(body_len); + return; } - private: - void read_head() { - reset_timer(); - auto self(this->shared_from_this()); - async_read_head([this, self](boost::system::error_code ec, std::size_t length) { - if (!socket_.is_open()) { - //LOG(INFO) << "socket already closed"; - return; - } + if (body_len == 0) { // nobody, just head, maybe as heartbeat. + cancel_timer(); + read_head(); + } else { + print("invalid body len"); + close(); + } + } else { + print(ec); + close(); + } + }); + } - if (!ec) { - //const uint32_t body_len = *((int*)(head_)); - //req_id_ = *((std::uint64_t*)(head_ + sizeof(int32_t))); - rpc_header* header = (rpc_header*)(head_); - req_id_ = header->req_id; - const uint32_t body_len = header->body_len; - req_type_ = header->req_type; - if (body_len > 0 && body_len < MAX_BUF_LEN) { - if (body_.size() < body_len) { body_.resize(body_len); } - read_body(body_len); - return; - } + void read_body(std::size_t size) { + auto self(this->shared_from_this()); + async_read( + size, [this, self](boost::system::error_code ec, std::size_t length) { + cancel_timer(); - if (body_len == 0) { // nobody, just head, maybe as heartbeat. - cancel_timer(); - read_head(); - } - else { - print("invalid body len"); - close(); - } - } - else { - print(ec); - close(); - } - }); - } + if (!socket_.is_open()) { + // LOG(INFO) << "socket already closed"; + return; + } - void read_body(std::size_t size) { - auto self(this->shared_from_this()); - async_read(size, [this, self](boost::system::error_code ec, std::size_t length) { - cancel_timer(); + if (!ec) { + read_head(); + if (req_type_ == request_type::req_res) { + router_.route(body_.data(), length, + this->shared_from_this()); + } else if (req_type_ == request_type::sub_pub) { + try { + msgpack_codec codec; + auto p = codec.unpack>( + body_.data(), length); + callback_(std::move(std::get<0>(p)), std::move(std::get<1>(p)), + this->shared_from_this()); + } catch (const std::exception &ex) { + print(ex); + } + } + } else { + // LOG(INFO) << ec.message(); + } + }); + } - if (!socket_.is_open()) { - //LOG(INFO) << "socket already closed"; - return; - } + void write() { + auto &msg = write_queue_.front(); + write_size_ = (uint32_t)msg.content->size(); + std::array write_buffers; + write_buffers[0] = boost::asio::buffer(&write_size_, sizeof(uint32_t)); + write_buffers[1] = boost::asio::buffer(&msg.req_id, sizeof(uint64_t)); + write_buffers[2] = boost::asio::buffer(&msg.req_type, sizeof(request_type)); + write_buffers[3] = boost::asio::buffer(msg.content->data(), write_size_); - if (!ec) { - read_head(); - if (req_type_ == request_type::req_res) { - router_.route(body_.data(), length, this->shared_from_this()); - } - else if (req_type_ == request_type::sub_pub) { - try { - msgpack_codec codec; - auto p = codec.unpack>(body_.data(), length); - callback_(std::move(std::get<0>(p)), std::move(std::get<1>(p)), this->shared_from_this()); - } - catch (const std::exception& ex) { - print(ex); - } - } - } - else { - //LOG(INFO) << ec.message(); - } - }); - } - - void write() { - auto& msg = write_queue_.front(); - write_size_ = (uint32_t)msg.content->size(); - std::array write_buffers; - write_buffers[0] = boost::asio::buffer(&write_size_, sizeof(uint32_t)); - write_buffers[1] = boost::asio::buffer(&msg.req_id, sizeof(uint64_t)); - write_buffers[2] = boost::asio::buffer(&msg.req_type, sizeof(request_type)); - write_buffers[3] = boost::asio::buffer(msg.content->data(), write_size_); - - auto self = this->shared_from_this(); - async_write(write_buffers, - [this, self](boost::system::error_code ec, std::size_t length) { - on_write(ec, length); - }); - } - - void on_write(boost::system::error_code ec, std::size_t length) { - if (ec) { - print(ec); - close(false); - return; - } - - if (has_closed()) { return; } - - std::unique_lock lock(write_mtx_); - write_queue_.pop_front(); - - if (!write_queue_.empty()) { - write(); - } - } - - void async_handshake() { -#ifdef CINATRA_ENABLE_SSL - auto self = this->shared_from_this(); - ssl_stream_->async_handshake(boost::asio::ssl::stream_base::server, - [this, self](const boost::system::error_code& error) { - if (error) { - print(error); - close(); - return; - } - - has_shake_ = true; - read_head(); + auto self = this->shared_from_this(); + async_write(write_buffers, + [this, self](boost::system::error_code ec, std::size_t length) { + on_write(ec, length); }); -#endif - } + } - bool is_ssl() const { + void on_write(boost::system::error_code ec, std::size_t length) { + if (ec) { + print(ec); + close(false); + return; + } + + if (has_closed()) { + return; + } + + std::unique_lock lock(write_mtx_); + write_queue_.pop_front(); + + if (!write_queue_.empty()) { + write(); + } + } + + void async_handshake() { #ifdef CINATRA_ENABLE_SSL - return ssl_stream_ != nullptr; + auto self = this->shared_from_this(); + ssl_stream_->async_handshake( + boost::asio::ssl::stream_base::server, + [this, self](const boost::system::error_code &error) { + if (error) { + print(error); + close(); + return; + } + + has_shake_ = true; + read_head(); + }); +#endif + } + + bool is_ssl() const { +#ifdef CINATRA_ENABLE_SSL + return ssl_stream_ != nullptr; #else - return false; + return false; #endif - } + } - template - void async_read_head(Handler handler) { - if (is_ssl()) { + template void async_read_head(Handler handler) { + if (is_ssl()) { #ifdef CINATRA_ENABLE_SSL - boost::asio::async_read(*ssl_stream_, boost::asio::buffer(head_, HEAD_LEN), std::move(handler)); + boost::asio::async_read(*ssl_stream_, + boost::asio::buffer(head_, HEAD_LEN), + std::move(handler)); #endif - } - else { - boost::asio::async_read(socket_, boost::asio::buffer(head_, HEAD_LEN), std::move(handler)); - } - } + } else { + boost::asio::async_read(socket_, boost::asio::buffer(head_, HEAD_LEN), + std::move(handler)); + } + } - template - void async_read(size_t size_to_read, Handler handler) { - if (is_ssl()) { + template + void async_read(size_t size_to_read, Handler handler) { + if (is_ssl()) { #ifdef CINATRA_ENABLE_SSL - boost::asio::async_read(*ssl_stream_, boost::asio::buffer(body_.data(), size_to_read), std::move(handler)); + boost::asio::async_read(*ssl_stream_, + boost::asio::buffer(body_.data(), size_to_read), + std::move(handler)); #endif - } - else { - boost::asio::async_read(socket_, boost::asio::buffer(body_.data(), size_to_read), std::move(handler)); - } - } + } else { + boost::asio::async_read(socket_, + boost::asio::buffer(body_.data(), size_to_read), + std::move(handler)); + } + } - template - void async_write(const BufferType& buffers, Handler handler) { - if (is_ssl()) { + template + void async_write(const BufferType &buffers, Handler handler) { + if (is_ssl()) { #ifdef CINATRA_ENABLE_SSL - boost::asio::async_write(*ssl_stream_, buffers, std::move(handler)); + boost::asio::async_write(*ssl_stream_, buffers, std::move(handler)); #endif - } - else { - boost::asio::async_write(socket_, buffers, std::move(handler)); - } - } + } else { + boost::asio::async_write(socket_, buffers, std::move(handler)); + } + } - void reset_timer() { - if (timeout_seconds_ == 0) { return; } + void reset_timer() { + if (timeout_seconds_ == 0) { + return; + } - auto self(this->shared_from_this()); - timer_.expires_from_now(std::chrono::seconds(timeout_seconds_)); - timer_.async_wait([this, self](const boost::system::error_code& ec) { - if (has_closed()) { return; } + auto self(this->shared_from_this()); + timer_.expires_from_now(std::chrono::seconds(timeout_seconds_)); + timer_.async_wait([this, self](const boost::system::error_code &ec) { + if (has_closed()) { + return; + } - if (ec) { return; } + if (ec) { + return; + } - //LOG(INFO) << "rpc connection timeout"; - close(false); - }); - } + // LOG(INFO) << "rpc connection timeout"; + close(false); + }); + } - void cancel_timer() { - if (timeout_seconds_ == 0) { return; } + void cancel_timer() { + if (timeout_seconds_ == 0) { + return; + } - timer_.cancel(); - } + timer_.cancel(); + } - void close(bool close_ssl = true) { + void close(bool close_ssl = true) { #ifdef CINATRA_ENABLE_SSL - if (close_ssl && ssl_stream_) { - boost::system::error_code ec; - ssl_stream_->shutdown(ec); - ssl_stream_ = nullptr; - } + if (close_ssl && ssl_stream_) { + boost::system::error_code ec; + ssl_stream_->shutdown(ec); + ssl_stream_ = nullptr; + } #endif - if (has_closed_) { - return; - } + if (has_closed_) { + return; + } - boost::system::error_code ignored_ec; - socket_.shutdown(tcp::socket::shutdown_both, ignored_ec); - socket_.close(ignored_ec); - has_closed_ = true; - has_shake_ = false; - } + boost::system::error_code ignored_ec; + socket_.shutdown(tcp::socket::shutdown_both, ignored_ec); + socket_.close(ignored_ec); + has_closed_ = true; + has_shake_ = false; + } - template - void print(Args... args) { + template void print(Args... args) { #ifdef _DEBUG - std::initializer_list{( std::cout << args << ' ', 0)...}; - std::cout << "\n"; + std::initializer_list{(std::cout << args << ' ', 0)...}; + std::cout << "\n"; #endif - } + } - void print(const boost::system::error_code& ec) { - print(ec.value(), ec.message()); - } + void print(const boost::system::error_code &ec) { + print(ec.value(), ec.message()); + } - void print(const std::exception& ex) { - print(ex.what()); - } + void print(const std::exception &ex) { print(ex.what()); } - tcp::socket socket_; + tcp::socket socket_; #ifdef CINATRA_ENABLE_SSL - std::unique_ptr> ssl_stream_ = nullptr; + std::unique_ptr> + ssl_stream_ = nullptr; #endif - bool has_shake_ = false; - char head_[HEAD_LEN]; - std::vector body_; - std::uint64_t req_id_; - request_type req_type_; + bool has_shake_ = false; + char head_[HEAD_LEN]; + std::vector body_; + std::uint64_t req_id_; + request_type req_type_; - uint32_t write_size_ = 0; - std::mutex write_mtx_; + uint32_t write_size_ = 0; + std::mutex write_mtx_; - asio::steady_timer timer_; - std::size_t timeout_seconds_; - int64_t conn_id_ = 0; - bool has_closed_; + asio::steady_timer timer_; + std::size_t timeout_seconds_; + int64_t conn_id_ = 0; + bool has_closed_; - std::deque write_queue_; - std::function)> callback_; - router& router_; - nonstd::any user_data_; - }; - } // namespace rpc_service -} // namespace rest_rpc + std::deque write_queue_; + std::function)> + callback_; + router &router_; + nonstd::any user_data_; +}; +} // namespace rpc_service +} // namespace rest_rpc -#endif // REST_RPC_CONNECTION_H_ +#endif // REST_RPC_CONNECTION_H_ diff --git a/include/rest_rpc/const_vars.h b/include/rest_rpc/const_vars.h index 7173a4e..8b3ba7c 100644 --- a/include/rest_rpc/const_vars.h +++ b/include/rest_rpc/const_vars.h @@ -3,41 +3,37 @@ namespace rest_rpc { - enum class result_code : std::int16_t { - OK = 0, - FAIL = 1, - }; +enum class result_code : std::int16_t { + OK = 0, + FAIL = 1, +}; - enum class error_code { - OK, - UNKNOWN, - FAIL, - TIMEOUT, - CANCEL, - BADCONNECTION, - }; +enum class error_code { + OK, + UNKNOWN, + FAIL, + TIMEOUT, + CANCEL, + BADCONNECTION, +}; - enum class request_type : uint8_t { - req_res, - sub_pub - }; +enum class request_type : uint8_t { req_res, sub_pub }; - struct message_type { - std::uint64_t req_id; - request_type req_type; - std::shared_ptr content; - }; +struct message_type { + std::uint64_t req_id; + request_type req_type; + std::shared_ptr content; +}; +#pragma pack(1) +struct rpc_header { + uint32_t body_len; + uint64_t req_id; + request_type req_type; +}; +#pragma pack() -#pragma pack (1) - struct rpc_header { - uint32_t body_len; - uint64_t req_id; - request_type req_type; - }; -#pragma pack () - - static const size_t MAX_BUF_LEN = 1048576 * 10; - static const size_t HEAD_LEN = 13; - static const size_t INIT_BUF_SIZE = 2 * 1024; -} \ No newline at end of file +static const size_t MAX_BUF_LEN = 1048576 * 10; +static const size_t HEAD_LEN = 13; +static const size_t INIT_BUF_SIZE = 2 * 1024; +} // namespace rest_rpc \ No newline at end of file diff --git a/include/rest_rpc/cplusplus_14.h b/include/rest_rpc/cplusplus_14.h index 20425f0..ac95c98 100644 --- a/include/rest_rpc/cplusplus_14.h +++ b/include/rest_rpc/cplusplus_14.h @@ -1,44 +1,37 @@ #ifndef REST_RPC_CPLUSPLUS_14_H_ #define REST_RPC_CPLUSPLUS_14_H_ -#include #include #include +#include #if __cplusplus == 201103L namespace std { -template -struct unique_if { - typedef unique_ptr single_object; -}; +template struct unique_if { typedef unique_ptr single_object; }; -template -struct unique_if { +template struct unique_if { typedef unique_ptr unknown_bound; }; -template -struct unique_if { +template struct unique_if { typedef void known_bound; }; -template -typename unique_if::single_object make_unique(Args&&... args) { +template +typename unique_if::single_object make_unique(Args &&...args) { return unique_ptr(new T(forward(args)...)); } -template -typename unique_if::unknown_bound make_unique(size_t n) { +template typename unique_if::unknown_bound make_unique(size_t n) { typedef typename remove_extent::type U; return unique_ptr(new U[n]()); } -template -typename unique_if::known_bound make_unique(Args&&...) = delete; +template +typename unique_if::known_bound make_unique(Args &&...) = delete; -template -struct index_sequence { +template struct index_sequence { using type = index_sequence; using value_type = size_t; static constexpr std::size_t size() noexcept { return sizeof...(Ints); } @@ -46,63 +39,61 @@ struct index_sequence { // -------------------------------------------------------------- -template -struct _merge_and_renumber; +template struct _merge_and_renumber; -template +template struct _merge_and_renumber, index_sequence> : index_sequence {}; // -------------------------------------------------------------- -template -struct make_index_sequence : _merge_and_renumber::type, - typename make_index_sequence::type> {}; +template +struct make_index_sequence + : _merge_and_renumber::type, + typename make_index_sequence::type> {}; -template<> -struct make_index_sequence<0> : index_sequence<> {}; -template<> -struct make_index_sequence<1> : index_sequence<0> {}; +template <> struct make_index_sequence<0> : index_sequence<> {}; +template <> struct make_index_sequence<1> : index_sequence<0> {}; -template +template using index_sequence_for = make_index_sequence; -template +template using enable_if_t = typename enable_if::type; -template -using remove_const_t = typename remove_const::type; +template using remove_const_t = typename remove_const::type; -template +template using remove_reference_t = typename remove_reference::type; -template +template using tuple_element_t = typename tuple_element::type; -template -using decay_t = typename decay::type; +template using decay_t = typename decay::type; -template -auto apply_helper(F&& f, Tuple&& tp, std::index_sequence) +template +auto apply_helper(F &&f, Tuple &&tp, std::index_sequence) -> decltype(std::forward(f)(std::get(std::forward(tp))...)) { return std::forward(f)(std::get(std::forward(tp))...); } -template -auto apply(F&& f, Tuple&& tp) - -> decltype(apply_helper(std::forward(f), std::forward(tp), - std::make_index_sequence>::value>{})) { - return apply_helper(std::forward(f), std::forward(tp), - std::make_index_sequence>::value>{}); +template +auto apply(F &&f, Tuple &&tp) -> decltype(apply_helper( + std::forward(f), std::forward(tp), + std::make_index_sequence>::value>{})) { + return apply_helper( + std::forward(f), std::forward(tp), + std::make_index_sequence>::value>{}); } -template -auto invoke(F&& f, Args&&... args) -> decltype(std::forward(f)(std::forward(args)...)) { +template +auto invoke(F &&f, Args &&...args) + -> decltype(std::forward(f)(std::forward(args)...)) { return std::forward(f)(std::forward(args)...); } -} // namespace std +} // namespace std #endif -#endif // REST_RPC_CPLUSPLUS_14_H_ +#endif // REST_RPC_CPLUSPLUS_14_H_ diff --git a/include/rest_rpc/io_service_pool.h b/include/rest_rpc/io_service_pool.h index 219430d..6be83e3 100644 --- a/include/rest_rpc/io_service_pool.h +++ b/include/rest_rpc/io_service_pool.h @@ -1,16 +1,17 @@ #ifndef REST_RPC_IO_SERVICE_POOL_H_ #define REST_RPC_IO_SERVICE_POOL_H_ -#include -#include #include "use_asio.hpp" +#include +#include namespace rest_rpc { namespace rpc_service { class io_service_pool : private asio::noncopyable { - public: +public: explicit io_service_pool(std::size_t pool_size) : next_io_service_(0) { - if (pool_size == 0) throw std::runtime_error("io_service_pool size is 0"); + if (pool_size == 0) + throw std::runtime_error("io_service_pool size is 0"); for (std::size_t i = 0; i < pool_size; ++i) { io_service_ptr io_service(new boost::asio::io_service); @@ -23,11 +24,12 @@ class io_service_pool : private asio::noncopyable { void run() { std::vector> threads; for (std::size_t i = 0; i < io_services_.size(); ++i) { - threads.emplace_back( - std::make_shared([](io_service_ptr svr) { svr->run(); }, io_services_[i])); + threads.emplace_back(std::make_shared( + [](io_service_ptr svr) { svr->run(); }, io_services_[i])); } - for (std::size_t i = 0; i < threads.size(); ++i) threads[i]->join(); + for (std::size_t i = 0; i < threads.size(); ++i) + threads[i]->join(); } void stop() { @@ -36,14 +38,15 @@ class io_service_pool : private asio::noncopyable { } } - boost::asio::io_service& get_io_service() { - boost::asio::io_service& io_service = *io_services_[next_io_service_]; + boost::asio::io_service &get_io_service() { + boost::asio::io_service &io_service = *io_services_[next_io_service_]; ++next_io_service_; - if (next_io_service_ == io_services_.size()) next_io_service_ = 0; + if (next_io_service_ == io_services_.size()) + next_io_service_ = 0; return io_service; } - private: +private: typedef std::shared_ptr io_service_ptr; typedef std::shared_ptr work_ptr; @@ -56,7 +59,7 @@ class io_service_pool : private asio::noncopyable { /// The next io_service to use for a connection. std::size_t next_io_service_; }; -} // namespace rpc_service -} // namespace rest_rpc +} // namespace rpc_service +} // namespace rest_rpc -#endif // REST_RPC_IO_SERVICE_POOL_H_ \ No newline at end of file +#endif // REST_RPC_IO_SERVICE_POOL_H_ \ No newline at end of file diff --git a/include/rest_rpc/meta_util.hpp b/include/rest_rpc/meta_util.hpp index 0fa1562..6e89b8e 100644 --- a/include/rest_rpc/meta_util.hpp +++ b/include/rest_rpc/meta_util.hpp @@ -1,106 +1,119 @@ #ifndef REST_RPC_META_UTIL_HPP #define REST_RPC_META_UTIL_HPP +#include #include "cplusplus_14.h" -namespace rest_rpc{ +namespace rest_rpc { - template - void for_each(const std::tuple& t, Func&& f, std::index_sequence) { - (void)std::initializer_list { (f(std::get(t)), void(), 0)...}; - } - - template - void for_each_i(const std::tuple& t, Func&& f, std::index_sequence) { - (void)std::initializer_list { (f(std::get(t), std::integral_constant{}), void(), 0)...}; - } - - template - struct function_traits; - - template - struct function_traits - { - public: - enum { arity = sizeof...(Args)+1 }; - typedef Ret function_type(Arg, Args...); - typedef Ret return_type; - using stl_function_type = std::function; - typedef Ret(*pointer)(Arg, Args...); - - typedef std::tuple tuple_type; - typedef std::tuple>, std::remove_const_t>...> bare_tuple_type; - using args_tuple = std::tuple>...>; - using args_tuple_2nd = std::tuple>...>; - }; - - template - struct function_traits { - public: - enum { arity = 0 }; - typedef Ret function_type(); - typedef Ret return_type; - using stl_function_type = std::function; - typedef Ret(*pointer)(); - - typedef std::tuple<> tuple_type; - typedef std::tuple<> bare_tuple_type; - using args_tuple = std::tuple; - using args_tuple_2nd = std::tuple; - }; - - template - struct function_traits : function_traits{}; - - template - struct function_traits> : function_traits{}; - - template - struct function_traits : function_traits{}; - - template - struct function_traits : function_traits{}; - - template - struct function_traits : function_traits{}; - - template - using remove_const_reference_t = std::remove_const_t>; - - template - auto make_tuple_from_sequence(std::index_sequence)->decltype(std::make_tuple(Is...)) { - std::make_tuple(Is...); - } - - template - constexpr auto make_tuple_from_sequence()->decltype(make_tuple_from_sequence(std::make_index_sequence{})) { - return make_tuple_from_sequence(std::make_index_sequence{}); - } - - namespace detail { - template - void tuple_switch(const std::size_t i, Tuple&& t, F&& f, std::index_sequence) { - (void)std::initializer_list { - (i == Is && ( - (void)std::forward(f)(std::integral_constant{}), 0))... - }; - } - } // namespace detail - - template - inline void tuple_switch(const std::size_t i, Tuple&& t, F&& f) { - constexpr auto N = - std::tuple_size>::value; - - detail::tuple_switch(i, std::forward(t), std::forward(f), - std::make_index_sequence{}); - } - - template - using nth_type_of = std::tuple_element_t>; - - template - using last_type_of = nth_type_of; +template +void for_each(const std::tuple &t, Func &&f, + std::index_sequence) { + (void)std::initializer_list{(f(std::get(t)), void(), 0)...}; } -#endif //REST_RPC_META_UTIL_HPP +template +void for_each_i(const std::tuple &t, Func &&f, + std::index_sequence) { + (void)std::initializer_list{ + (f(std::get(t), std::integral_constant{}), void(), + 0)...}; +} + +template struct function_traits; + +template +struct function_traits { +public: + enum { arity = sizeof...(Args) + 1 }; + typedef Ret function_type(Arg, Args...); + typedef Ret return_type; + using stl_function_type = std::function; + typedef Ret (*pointer)(Arg, Args...); + + typedef std::tuple tuple_type; + typedef std::tuple>, + std::remove_const_t>...> + bare_tuple_type; + using args_tuple = + std::tuple>...>; + using args_tuple_2nd = + std::tuple>...>; +}; + +template struct function_traits { +public: + enum { arity = 0 }; + typedef Ret function_type(); + typedef Ret return_type; + using stl_function_type = std::function; + typedef Ret (*pointer)(); + + typedef std::tuple<> tuple_type; + typedef std::tuple<> bare_tuple_type; + using args_tuple = std::tuple; + using args_tuple_2nd = std::tuple; +}; + +template +struct function_traits : function_traits {}; + +template +struct function_traits> + : function_traits {}; + +template +struct function_traits + : function_traits {}; + +template +struct function_traits + : function_traits {}; + +template +struct function_traits : function_traits {}; + +template +using remove_const_reference_t = + std::remove_const_t>; + +template +auto make_tuple_from_sequence(std::index_sequence) + -> decltype(std::make_tuple(Is...)) { + std::make_tuple(Is...); +} + +template +constexpr auto make_tuple_from_sequence() + -> decltype(make_tuple_from_sequence(std::make_index_sequence{})) { + return make_tuple_from_sequence(std::make_index_sequence{}); +} + +namespace detail { +template +void tuple_switch(const std::size_t i, Tuple &&t, F &&f, + std::index_sequence) { + (void)std::initializer_list{ + (i == Is && + ((void)std::forward(f)(std::integral_constant{}), 0))...}; +} +} // namespace detail + +template +inline void tuple_switch(const std::size_t i, Tuple &&t, F &&f) { + constexpr auto N = std::tuple_size>::value; + + detail::tuple_switch(i, std::forward(t), std::forward(f), + std::make_index_sequence{}); +} + +template +using nth_type_of = std::tuple_element_t>; + +template +using last_type_of = nth_type_of; +} // namespace rest_rpc + +#endif // REST_RPC_META_UTIL_HPP diff --git a/include/rest_rpc/nonstd_any.hpp b/include/rest_rpc/nonstd_any.hpp index 622d7d4..7817ea9 100644 --- a/include/rest_rpc/nonstd_any.hpp +++ b/include/rest_rpc/nonstd_any.hpp @@ -4,96 +4,102 @@ // https://github.com/martinmoene/any-lite // // Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// (See accompanying file LICENSE.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) #pragma once #ifndef NONSTD_ANY_LITE_HPP #define NONSTD_ANY_LITE_HPP -#define any_lite_MAJOR 0 -#define any_lite_MINOR 4 -#define any_lite_PATCH 0 +#define any_lite_MAJOR 0 +#define any_lite_MINOR 4 +#define any_lite_PATCH 0 -#define any_lite_VERSION any_STRINGIFY(any_lite_MAJOR) "." any_STRINGIFY(any_lite_MINOR) "." any_STRINGIFY(any_lite_PATCH) +#define any_lite_VERSION \ + any_STRINGIFY(any_lite_MAJOR) "." any_STRINGIFY( \ + any_lite_MINOR) "." any_STRINGIFY(any_lite_PATCH) -#define any_STRINGIFY( x ) any_STRINGIFY_( x ) -#define any_STRINGIFY_( x ) #x +#define any_STRINGIFY(x) any_STRINGIFY_(x) +#define any_STRINGIFY_(x) #x // any-lite configuration: -#define any_ANY_DEFAULT 0 -#define any_ANY_NONSTD 1 -#define any_ANY_STD 2 +#define any_ANY_DEFAULT 0 +#define any_ANY_NONSTD 1 +#define any_ANY_STD 2 // tweak header support: #ifdef __has_include -# if __has_include() -# include -# endif -#define any_HAVE_TWEAK_HEADER 1 +#if __has_include() +#include +#endif +#define any_HAVE_TWEAK_HEADER 1 #else -#define any_HAVE_TWEAK_HEADER 0 +#define any_HAVE_TWEAK_HEADER 0 //# pragma message("any.hpp: Note: Tweak header not supported.") #endif // any selection and configuration: -#if !defined( any_CONFIG_SELECT_ANY ) -# define any_CONFIG_SELECT_ANY ( any_HAVE_STD_ANY ? any_ANY_STD : any_ANY_NONSTD ) +#if !defined(any_CONFIG_SELECT_ANY) +#define any_CONFIG_SELECT_ANY (any_HAVE_STD_ANY ? any_ANY_STD : any_ANY_NONSTD) #endif // Control presence of exception handling (try and auto discover): #ifndef any_CONFIG_NO_EXCEPTIONS -# if _MSC_VER -# include // for _HAS_EXCEPTIONS -# endif -# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS) -# define any_CONFIG_NO_EXCEPTIONS 0 -# else -# define any_CONFIG_NO_EXCEPTIONS 1 -# endif +#if _MSC_VER +#include // for _HAS_EXCEPTIONS +#endif +#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS) +#define any_CONFIG_NO_EXCEPTIONS 0 +#else +#define any_CONFIG_NO_EXCEPTIONS 1 +#endif #endif // C++ language version detection (C++20 is speculative): // Note: VC14.0/1900 (VS2015) lacks too much from C++14. -#ifndef any_CPLUSPLUS -# if defined(_MSVC_LANG ) && !defined(__clang__) -# define any_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG ) -# else -# define any_CPLUSPLUS __cplusplus -# endif +#ifndef any_CPLUSPLUS +#if defined(_MSVC_LANG) && !defined(__clang__) +#define any_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG) +#else +#define any_CPLUSPLUS __cplusplus +#endif #endif -#define any_CPP98_OR_GREATER ( any_CPLUSPLUS >= 199711L ) -#define any_CPP11_OR_GREATER ( any_CPLUSPLUS >= 201103L ) -#define any_CPP14_OR_GREATER ( any_CPLUSPLUS >= 201402L ) -#define any_CPP17_OR_GREATER ( any_CPLUSPLUS >= 201703L ) -#define any_CPP20_OR_GREATER ( any_CPLUSPLUS >= 202000L ) +#define any_CPP98_OR_GREATER (any_CPLUSPLUS >= 199711L) +#define any_CPP11_OR_GREATER (any_CPLUSPLUS >= 201103L) +#define any_CPP14_OR_GREATER (any_CPLUSPLUS >= 201402L) +#define any_CPP17_OR_GREATER (any_CPLUSPLUS >= 201703L) +#define any_CPP20_OR_GREATER (any_CPLUSPLUS >= 202000L) // Use C++17 std::any if available and requested: -#if any_CPP17_OR_GREATER && defined(__has_include ) -# if __has_include( ) -# define any_HAVE_STD_ANY 1 -# else -# define any_HAVE_STD_ANY 0 -# endif +#if any_CPP17_OR_GREATER && defined(__has_include) +#if __has_include( ) +#define any_HAVE_STD_ANY 1 #else -# define any_HAVE_STD_ANY 0 +#define any_HAVE_STD_ANY 0 +#endif +#else +#define any_HAVE_STD_ANY 0 #endif -#define any_USES_STD_ANY ( (any_CONFIG_SELECT_ANY == any_ANY_STD) || ((any_CONFIG_SELECT_ANY == any_ANY_DEFAULT) && any_HAVE_STD_ANY) ) +#define any_USES_STD_ANY \ + ((any_CONFIG_SELECT_ANY == any_ANY_STD) || \ + ((any_CONFIG_SELECT_ANY == any_ANY_DEFAULT) && any_HAVE_STD_ANY)) // -// in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite: +// in_place: code duplicated in any-lite, expected-lite, optional-lite, +// value-ptr-lite, variant-lite: // #ifndef nonstd_lite_HAVE_IN_PLACE_TYPES -#define nonstd_lite_HAVE_IN_PLACE_TYPES 1 +#define nonstd_lite_HAVE_IN_PLACE_TYPES 1 // C++17 std::in_place in : @@ -103,20 +109,23 @@ namespace nonstd { - using std::in_place; - using std::in_place_type; - using std::in_place_index; - using std::in_place_t; - using std::in_place_type_t; - using std::in_place_index_t; +using std::in_place; +using std::in_place_index; +using std::in_place_index_t; +using std::in_place_t; +using std::in_place_type; +using std::in_place_type_t; -#define nonstd_lite_in_place_t( T) std::in_place_t -#define nonstd_lite_in_place_type_t( T) std::in_place_type_t -#define nonstd_lite_in_place_index_t(K) std::in_place_index_t +#define nonstd_lite_in_place_t(T) std::in_place_t +#define nonstd_lite_in_place_type_t(T) std::in_place_type_t +#define nonstd_lite_in_place_index_t(K) std::in_place_index_t -#define nonstd_lite_in_place( T) std::in_place_t{} -#define nonstd_lite_in_place_type( T) std::in_place_type_t{} -#define nonstd_lite_in_place_index(K) std::in_place_index_t{} +#define nonstd_lite_in_place(T) \ + std::in_place_t {} +#define nonstd_lite_in_place_type(T) \ + std::in_place_type_t {} +#define nonstd_lite_in_place_index(K) \ + std::in_place_index_t {} } // namespace nonstd @@ -125,51 +134,52 @@ namespace nonstd { #include namespace nonstd { - namespace detail { +namespace detail { - template< class T > - struct in_place_type_tag {}; +template struct in_place_type_tag {}; - template< std::size_t K > - struct in_place_index_tag {}; +template struct in_place_index_tag {}; - } // namespace detail +} // namespace detail - struct in_place_t {}; +struct in_place_t {}; - template< class T > - inline in_place_t in_place(detail::in_place_type_tag = detail::in_place_type_tag()) - { - return in_place_t(); - } +template +inline in_place_t +in_place(detail::in_place_type_tag = detail::in_place_type_tag()) { + return in_place_t(); +} - template< std::size_t K > - inline in_place_t in_place(detail::in_place_index_tag = detail::in_place_index_tag()) - { - return in_place_t(); - } +template +inline in_place_t +in_place(detail::in_place_index_tag = detail::in_place_index_tag()) { + return in_place_t(); +} - template< class T > - inline in_place_t in_place_type(detail::in_place_type_tag = detail::in_place_type_tag()) - { - return in_place_t(); - } +template +inline in_place_t +in_place_type(detail::in_place_type_tag = detail::in_place_type_tag()) { + return in_place_t(); +} - template< std::size_t K > - inline in_place_t in_place_index(detail::in_place_index_tag = detail::in_place_index_tag()) - { - return in_place_t(); - } +template +inline in_place_t in_place_index( + detail::in_place_index_tag = detail::in_place_index_tag()) { + return in_place_t(); +} - // mimic templated typedef: +// mimic templated typedef: -#define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag ) -#define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag ) -#define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag ) +#define nonstd_lite_in_place_t(T) \ + nonstd::in_place_t (&)(nonstd::detail::in_place_type_tag) +#define nonstd_lite_in_place_type_t(T) \ + nonstd::in_place_t (&)(nonstd::detail::in_place_type_tag) +#define nonstd_lite_in_place_index_t(K) \ + nonstd::in_place_t (&)(nonstd::detail::in_place_index_tag) -#define nonstd_lite_in_place( T) nonstd::in_place_type -#define nonstd_lite_in_place_type( T) nonstd::in_place_type -#define nonstd_lite_in_place_index(K) nonstd::in_place_index +#define nonstd_lite_in_place(T) nonstd::in_place_type +#define nonstd_lite_in_place_type(T) nonstd::in_place_type +#define nonstd_lite_in_place_index(K) nonstd::in_place_index } // namespace nonstd @@ -187,12 +197,12 @@ namespace nonstd { namespace nonstd { - using std::any; - using std::any_cast; - using std::make_any; - using std::swap; - using std::bad_any_cast; -} +using std::any; +using std::any_cast; +using std::bad_any_cast; +using std::make_any; +using std::swap; +} // namespace nonstd #else // any_USES_STD_ANY @@ -200,38 +210,44 @@ namespace nonstd { // Compiler versions: // -// MSVC++ 6.0 _MSC_VER == 1200 any_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0) -// MSVC++ 7.0 _MSC_VER == 1300 any_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002) -// MSVC++ 7.1 _MSC_VER == 1310 any_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003) -// MSVC++ 8.0 _MSC_VER == 1400 any_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005) -// MSVC++ 9.0 _MSC_VER == 1500 any_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008) -// MSVC++ 10.0 _MSC_VER == 1600 any_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010) -// MSVC++ 11.0 _MSC_VER == 1700 any_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012) -// MSVC++ 12.0 _MSC_VER == 1800 any_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013) -// MSVC++ 14.0 _MSC_VER == 1900 any_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015) -// MSVC++ 14.1 _MSC_VER >= 1910 any_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017) -// MSVC++ 14.2 _MSC_VER >= 1920 any_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019) +// MSVC++ 6.0 _MSC_VER == 1200 any_COMPILER_MSVC_VERSION == 60 (Visual +// Studio 6.0) MSVC++ 7.0 _MSC_VER == 1300 any_COMPILER_MSVC_VERSION == 70 +// (Visual Studio .NET 2002) MSVC++ 7.1 _MSC_VER == 1310 +// any_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003) MSVC++ 8.0 +// _MSC_VER == 1400 any_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005) +// MSVC++ 9.0 _MSC_VER == 1500 any_COMPILER_MSVC_VERSION == 90 (Visual +// Studio 2008) MSVC++ 10.0 _MSC_VER == 1600 any_COMPILER_MSVC_VERSION == 100 +// (Visual Studio 2010) MSVC++ 11.0 _MSC_VER == 1700 any_COMPILER_MSVC_VERSION +// == 110 (Visual Studio 2012) MSVC++ 12.0 _MSC_VER == 1800 +// any_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013) MSVC++ 14.0 _MSC_VER +// == 1900 any_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015) MSVC++ 14.1 +// _MSC_VER >= 1910 any_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017) +// MSVC++ 14.2 _MSC_VER >= 1920 any_COMPILER_MSVC_VERSION == 142 (Visual +// Studio 2019) -#if defined(_MSC_VER ) && !defined(__clang__) -# define any_COMPILER_MSVC_VER (_MSC_VER ) -# define any_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) ) +#if defined(_MSC_VER) && !defined(__clang__) +#define any_COMPILER_MSVC_VER (_MSC_VER) +#define any_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * (5 + (_MSC_VER < 1900))) #else -# define any_COMPILER_MSVC_VER 0 -# define any_COMPILER_MSVC_VERSION 0 +#define any_COMPILER_MSVC_VER 0 +#define any_COMPILER_MSVC_VERSION 0 #endif -#define any_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) ) +#define any_COMPILER_VERSION(major, minor, patch) \ + (10 * (10 * (major) + (minor)) + (patch)) #if defined(__clang__) -# define any_COMPILER_CLANG_VERSION any_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) +#define any_COMPILER_CLANG_VERSION \ + any_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) #else -# define any_COMPILER_CLANG_VERSION 0 +#define any_COMPILER_CLANG_VERSION 0 #endif #if defined(__GNUC__) && !defined(__clang__) -# define any_COMPILER_GNUC_VERSION any_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#define any_COMPILER_GNUC_VERSION \ + any_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) #else -# define any_COMPILER_GNUC_VERSION 0 +#define any_COMPILER_GNUC_VERSION 0 #endif // half-open range [lo..hi): @@ -239,116 +255,114 @@ namespace nonstd { // Presence of language and library features: -#define any_HAVE( feature ) ( any_HAVE_##feature ) +#define any_HAVE(feature) (any_HAVE_##feature) #ifdef _HAS_CPP0X -# define any_HAS_CPP0X _HAS_CPP0X +#define any_HAS_CPP0X _HAS_CPP0X #else -# define any_HAS_CPP0X 0 +#define any_HAS_CPP0X 0 #endif -#define any_CPP11_90 (any_CPP11_OR_GREATER || any_COMPILER_MSVC_VER >= 1500) -#define any_CPP11_100 (any_CPP11_OR_GREATER || any_COMPILER_MSVC_VER >= 1600) -#define any_CPP11_120 (any_CPP11_OR_GREATER || any_COMPILER_MSVC_VER >= 1800) -#define any_CPP11_140 (any_CPP11_OR_GREATER || any_COMPILER_MSVC_VER >= 1900) +#define any_CPP11_90 (any_CPP11_OR_GREATER || any_COMPILER_MSVC_VER >= 1500) +#define any_CPP11_100 (any_CPP11_OR_GREATER || any_COMPILER_MSVC_VER >= 1600) +#define any_CPP11_120 (any_CPP11_OR_GREATER || any_COMPILER_MSVC_VER >= 1800) +#define any_CPP11_140 (any_CPP11_OR_GREATER || any_COMPILER_MSVC_VER >= 1900) -#define any_CPP14_000 (any_CPP14_OR_GREATER) -#define any_CPP17_000 (any_CPP17_OR_GREATER) +#define any_CPP14_000 (any_CPP14_OR_GREATER) +#define any_CPP17_000 (any_CPP17_OR_GREATER) // Presence of C++11 language features: -#define any_HAVE_CONSTEXPR_11 any_CPP11_140 -#define any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG \ - any_CPP11_120 -#define any_HAVE_INITIALIZER_LIST any_CPP11_120 -#define any_HAVE_NOEXCEPT any_CPP11_140 -#define any_HAVE_NULLPTR any_CPP11_100 -#define any_HAVE_TYPE_TRAITS any_CPP11_90 -#define any_HAVE_STATIC_ASSERT any_CPP11_100 -#define any_HAVE_ADD_CONST any_CPP11_90 -#define any_HAVE_REMOVE_REFERENCE any_CPP11_90 +#define any_HAVE_CONSTEXPR_11 any_CPP11_140 +#define any_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG any_CPP11_120 +#define any_HAVE_INITIALIZER_LIST any_CPP11_120 +#define any_HAVE_NOEXCEPT any_CPP11_140 +#define any_HAVE_NULLPTR any_CPP11_100 +#define any_HAVE_TYPE_TRAITS any_CPP11_90 +#define any_HAVE_STATIC_ASSERT any_CPP11_100 +#define any_HAVE_ADD_CONST any_CPP11_90 +#define any_HAVE_REMOVE_REFERENCE any_CPP11_90 -#define any_HAVE_TR1_ADD_CONST (!! any_COMPILER_GNUC_VERSION ) -#define any_HAVE_TR1_REMOVE_REFERENCE (!! any_COMPILER_GNUC_VERSION ) -#define any_HAVE_TR1_TYPE_TRAITS (!! any_COMPILER_GNUC_VERSION ) +#define any_HAVE_TR1_ADD_CONST (!!any_COMPILER_GNUC_VERSION) +#define any_HAVE_TR1_REMOVE_REFERENCE (!!any_COMPILER_GNUC_VERSION) +#define any_HAVE_TR1_TYPE_TRAITS (!!any_COMPILER_GNUC_VERSION) // Presence of C++14 language features: -#define any_HAVE_CONSTEXPR_14 any_CPP14_000 +#define any_HAVE_CONSTEXPR_14 any_CPP14_000 // Presence of C++17 language features: -#define any_HAVE_NODISCARD any_CPP17_000 +#define any_HAVE_NODISCARD any_CPP17_000 // Presence of C++ language features: #if any_HAVE_CONSTEXPR_11 -# define any_constexpr constexpr +#define any_constexpr constexpr #else -# define any_constexpr /*constexpr*/ +#define any_constexpr /*constexpr*/ #endif #if any_HAVE_CONSTEXPR_14 -# define any_constexpr14 constexpr +#define any_constexpr14 constexpr #else -# define any_constexpr14 /*constexpr*/ +#define any_constexpr14 /*constexpr*/ #endif #if any_HAVE_NOEXCEPT -# define any_noexcept noexcept +#define any_noexcept noexcept #else -# define any_noexcept /*noexcept*/ +#define any_noexcept /*noexcept*/ #endif #if any_HAVE_NULLPTR -# define any_nullptr nullptr +#define any_nullptr nullptr #else -# define any_nullptr NULL +#define any_nullptr NULL #endif #if any_HAVE_NODISCARD -# define any_nodiscard [[nodiscard]] +#define any_nodiscard [[nodiscard]] #else -# define any_nodiscard /*[[nodiscard]]*/ +#define any_nodiscard /*[[nodiscard]]*/ #endif // additional includes: #if any_CONFIG_NO_EXCEPTIONS -# include +#include #else -# include +#include #endif -#if ! any_HAVE_NULLPTR -# include +#if !any_HAVE_NULLPTR +#include #endif #if any_HAVE_INITIALIZER_LIST -# include +#include #endif #if any_HAVE_TYPE_TRAITS -# include +#include #elif any_HAVE_TR1_TYPE_TRAITS -# include +#include #endif // Method enabling #if any_CPP11_OR_GREATER -#define any_REQUIRES_0(...) \ - template< bool B = (__VA_ARGS__), typename std::enable_if::type = 0 > +#define any_REQUIRES_0(...) \ + template ::type = 0> -#define any_REQUIRES_T(...) \ - , typename std::enable_if< (__VA_ARGS__), int >::type = 0 +#define any_REQUIRES_T(...) \ + , typename std::enable_if<(__VA_ARGS__), int>::type = 0 -#define any_REQUIRES_R(R, ...) \ - typename std::enable_if<__VA_ARGS__, R>::type +#define any_REQUIRES_R(R, ...) typename std::enable_if<__VA_ARGS__, R>::type -#define any_REQUIRES_A(...) \ - , typename std::enable_if<__VA_ARGS__, void*>::type = nullptr +#define any_REQUIRES_A(...) \ + , typename std::enable_if<__VA_ARGS__, void *>::type = nullptr #endif @@ -357,362 +371,308 @@ namespace nonstd { // namespace nonstd { - namespace any_lite { +namespace any_lite { - // C++11 emulation: +// C++11 emulation: - namespace std11 { +namespace std11 { #if any_HAVE_ADD_CONST - using std::add_const; +using std::add_const; #elif any_HAVE_TR1_ADD_CONST - using std::tr1::add_const; +using std::tr1::add_const; #else - template< class T > struct add_const { typedef const T type; }; +template struct add_const { typedef const T type; }; #endif // any_HAVE_ADD_CONST #if any_HAVE_REMOVE_REFERENCE - using std::remove_reference; +using std::remove_reference; #elif any_HAVE_TR1_REMOVE_REFERENCE - using std::tr1::remove_reference; +using std::tr1::remove_reference; #else - template< class T > struct remove_reference { typedef T type; }; - template< class T > struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; #endif // any_HAVE_REMOVE_REFERENCE - } // namespace std11 +} // namespace std11 - namespace detail { +namespace detail { - // for any_REQUIRES_T +// for any_REQUIRES_T - /*enum*/ class enabler {}; +/*enum*/ class enabler {}; - } // namespace detail +} // namespace detail -#if ! any_CONFIG_NO_EXCEPTIONS +#if !any_CONFIG_NO_EXCEPTIONS - class bad_any_cast : public std::bad_cast - { - public: +class bad_any_cast : public std::bad_cast { +public: #if any_CPP11_OR_GREATER - virtual const char* what() const any_noexcept + virtual const char *what() const any_noexcept #else - virtual const char* what() const throw() + virtual const char *what() const throw() #endif - { - return "any-lite: bad any_cast"; - } - }; + { + return "any-lite: bad any_cast"; + } +}; #endif // any_CONFIG_NO_EXCEPTIONS - class any - { - public: - any_constexpr any() any_noexcept - : content(any_nullptr) - {} +class any { +public: + any_constexpr any() any_noexcept : content(any_nullptr) {} - any(any const& other) - : content(other.content ? other.content->clone() : any_nullptr) - {} + any(any const &other) + : content(other.content ? other.content->clone() : any_nullptr) {} #if any_CPP11_OR_GREATER - any(any&& other) any_noexcept - : content(std::move(other.content)) - { - other.content = any_nullptr; - } + any(any &&other) any_noexcept : content(std::move(other.content)) { + other.content = any_nullptr; + } - template< - class ValueType, class T = typename std::decay::type - any_REQUIRES_T(!std::is_same::value) - > - any(ValueType&& value) any_noexcept - : content(new holder(std::forward(value))) - {} + template ::type + any_REQUIRES_T(!std::is_same::value)> + any(ValueType &&value) any_noexcept + : content(new holder(std::forward(value))) {} - template< - class T, class... Args - any_REQUIRES_T(std::is_constructible::value) - > - explicit any(nonstd_lite_in_place_type_t(T), Args&&... args) - : content(new holder(T(std::forward(args)...))) - {} + template ::value)> + explicit any(nonstd_lite_in_place_type_t(T), Args &&...args) + : content(new holder(T(std::forward(args)...))) {} - template< - class T, class U, class... Args - any_REQUIRES_T(std::is_constructible&, Args&&...>::value) - > - explicit any(nonstd_lite_in_place_type_t(T), std::initializer_list il, Args&&... args) - : content(new holder(T(il, std::forward(args)...))) - {} + template &, + Args &&...>::value)> + explicit any(nonstd_lite_in_place_type_t(T), std::initializer_list il, + Args &&...args) + : content(new holder(T(il, std::forward(args)...))) {} #else - template< class ValueType > - any(ValueType const& value) - : content(new holder(value)) - {} + template + any(ValueType const &value) : content(new holder(value)) {} #endif // any_CPP11_OR_GREATER - ~any() - { - reset(); - } + ~any() { reset(); } - any& operator=(any const& other) - { - any(other).swap(*this); - return *this; - } + any &operator=(any const &other) { + any(other).swap(*this); + return *this; + } #if any_CPP11_OR_GREATER - any& operator=(any&& other) any_noexcept - { - any(std::move(other)).swap(*this); - return *this; - } + any &operator=(any &&other) any_noexcept { + any(std::move(other)).swap(*this); + return *this; + } - template< - class ValueType, class T = typename std::decay::type - any_REQUIRES_T(!std::is_same::value) - > - any& operator=(T&& value) - { - any(std::move(value)).swap(*this); - return *this; - } + template ::type + any_REQUIRES_T(!std::is_same::value)> + any &operator=(T &&value) { + any(std::move(value)).swap(*this); + return *this; + } - template< class T, class... Args > - void emplace(Args && ... args) - { - any(T(std::forward(args)...)).swap(*this); - } + template void emplace(Args &&...args) { + any(T(std::forward(args)...)).swap(*this); + } - template< - class T, class U, class... Args - any_REQUIRES_T(std::is_constructible&, Args&&...>::value) - > - void emplace(std::initializer_list il, Args&&... args) - { - any(T(il, std::forward(args)...)).swap(*this); - } + template &, + Args &&...>::value)> + void emplace(std::initializer_list il, Args &&...args) { + any(T(il, std::forward(args)...)).swap(*this); + } #else - template< class ValueType > - any& operator=(ValueType const& value) - { - any(value).swap(*this); - return *this; - } + template any &operator=(ValueType const &value) { + any(value).swap(*this); + return *this; + } #endif // any_CPP11_OR_GREATER - void reset() any_noexcept - { - delete content; content = any_nullptr; - } + void reset() any_noexcept { + delete content; + content = any_nullptr; + } - void swap(any& other) any_noexcept - { - std::swap(content, other.content); - } + void swap(any &other) any_noexcept { std::swap(content, other.content); } - bool has_value() const any_noexcept - { - return content != any_nullptr; - } + bool has_value() const any_noexcept { return content != any_nullptr; } - const std::type_info& type() const any_noexcept - { - return has_value() ? content->type() : typeid(void); - } + const std::type_info &type() const any_noexcept { + return has_value() ? content->type() : typeid(void); + } - // - // non-standard: - // + // + // non-standard: + // - template< class ValueType > - const ValueType* to_ptr() const - { - return &(static_cast *>(content)->held); - } + template const ValueType *to_ptr() const { + return &(static_cast *>(content)->held); + } - template< class ValueType > - ValueType* to_ptr() - { - return &(static_cast *>(content)->held); - } + template ValueType *to_ptr() { + return &(static_cast *>(content)->held); + } - private: - class placeholder - { - public: - virtual ~placeholder() - { - } +private: + class placeholder { + public: + virtual ~placeholder() {} - virtual std::type_info const& type() const = 0; + virtual std::type_info const &type() const = 0; - virtual placeholder* clone() const = 0; - }; + virtual placeholder *clone() const = 0; + }; - template< typename ValueType > - class holder : public placeholder - { - public: - holder(ValueType const& value) - : held(value) - {} + template class holder : public placeholder { + public: + holder(ValueType const &value) : held(value) {} #if any_CPP11_OR_GREATER - holder(ValueType&& value) - : held(std::move(value)) - {} + holder(ValueType &&value) : held(std::move(value)) {} #endif - virtual std::type_info const& type() const - { - return typeid(ValueType); - } + virtual std::type_info const &type() const { return typeid(ValueType); } - virtual placeholder* clone() const - { - return new holder(held); - } + virtual placeholder *clone() const { return new holder(held); } - ValueType held; - }; + ValueType held; + }; - placeholder* content; - }; + placeholder *content; +}; - inline void swap(any& x, any& y) any_noexcept - { - x.swap(y); - } +inline void swap(any &x, any &y) any_noexcept { x.swap(y); } #if any_CPP11_OR_GREATER - template< class T, class ...Args > - inline any make_any(Args&& ...args) - { - return any(nonstd_lite_in_place_type(T), std::forward(args)...); - } +template inline any make_any(Args &&...args) { + return any(nonstd_lite_in_place_type(T), std::forward(args)...); +} - template< class T, class U, class ...Args > - inline any make_any(std::initializer_list il, Args&& ...args) - { - return any(nonstd_lite_in_place_type(T), il, std::forward(args)...); - } +template +inline any make_any(std::initializer_list il, Args &&...args) { + return any(nonstd_lite_in_place_type(T), il, std::forward(args)...); +} #endif // any_CPP11_OR_GREATER - template< - class ValueType +template ::value || std::is_copy_constructible::value), nonstd::any_lite::detail::enabler >::type + // any_REQUIRES_T(...) Allow for VC120 (VS2013): + , + typename = typename std::enable_if< + (std::is_reference::value || + std::is_copy_constructible::value), + nonstd::any_lite::detail::enabler>::type #endif - > - any_nodiscard inline ValueType any_cast(any const& operand) - { - const ValueType* result = any_cast::type >::type>(&operand); + > +any_nodiscard inline ValueType any_cast(any const &operand) { + const ValueType *result = any_cast::type>::type>(&operand); #if any_CONFIG_NO_EXCEPTIONS - assert(result); + assert(result); #else - if (!result) - { - throw bad_any_cast(); - } + if (!result) { + throw bad_any_cast(); + } #endif - return *result; - } + return *result; +} - template< - class ValueType +template ::value || std::is_copy_constructible::value), nonstd::any_lite::detail::enabler >::type + // any_REQUIRES_T(...) Allow for VC120 (VS2013): + , + typename = typename std::enable_if< + (std::is_reference::value || + std::is_copy_constructible::value), + nonstd::any_lite::detail::enabler>::type #endif - > - any_nodiscard inline ValueType any_cast(any& operand) - { - const ValueType* result = any_cast::type>(&operand); + > +any_nodiscard inline ValueType any_cast(any &operand) { + const ValueType *result = + any_cast::type>(&operand); #if any_CONFIG_NO_EXCEPTIONS - assert(result); + assert(result); #else - if (!result) - { - throw bad_any_cast(); - } + if (!result) { + throw bad_any_cast(); + } #endif - return *result; - } + return *result; +} #if any_CPP11_OR_GREATER - template< - class ValueType +template ::value || std::is_copy_constructible::value) + any_REQUIRES_T(std::is_reference::value || + std::is_copy_constructible::value) #endif - > - any_nodiscard inline ValueType any_cast(any&& operand) - { - const ValueType* result = any_cast::type>(&operand); + > +any_nodiscard inline ValueType any_cast(any &&operand) { + const ValueType *result = + any_cast::type>(&operand); #if any_CONFIG_NO_EXCEPTIONS - assert(result); + assert(result); #else - if (!result) - { - throw bad_any_cast(); - } + if (!result) { + throw bad_any_cast(); + } #endif - return *result; - } + return *result; +} #endif // any_CPP11_OR_GREATER - template< class ValueType > - any_nodiscard inline ValueType const* any_cast(any const* operand) any_noexcept - { - return operand != any_nullptr && operand->type() == typeid(ValueType) ? operand->to_ptr() : any_nullptr; - } +template +any_nodiscard inline ValueType const * +any_cast(any const *operand) any_noexcept { + return operand != any_nullptr && operand->type() == typeid(ValueType) + ? operand->to_ptr() + : any_nullptr; +} - template - any_nodiscard inline ValueType* any_cast(any* operand) any_noexcept - { - return operand != any_nullptr && operand->type() == typeid(ValueType) ? operand->to_ptr() : any_nullptr; - } +template +any_nodiscard inline ValueType *any_cast(any *operand) any_noexcept { + return operand != any_nullptr && operand->type() == typeid(ValueType) + ? operand->to_ptr() + : any_nullptr; +} - } // namespace any_lite +} // namespace any_lite - using namespace any_lite; +using namespace any_lite; } // namespace nonstd diff --git a/include/rest_rpc/router.h b/include/rest_rpc/router.h index bfc789e..1900335 100644 --- a/include/rest_rpc/router.h +++ b/include/rest_rpc/router.h @@ -1,185 +1,205 @@ #ifndef REST_RPC_ROUTER_H_ #define REST_RPC_ROUTER_H_ -#include -#include "use_asio.hpp" #include "codec.h" #include "meta_util.hpp" +#include "use_asio.hpp" +#include namespace rest_rpc { - enum class ExecMode { sync, async }; - const constexpr ExecMode Async = ExecMode::async; +enum class ExecMode { sync, async }; +const constexpr ExecMode Async = ExecMode::async; - namespace rpc_service { - class connection; +namespace rpc_service { +class connection; - class router : asio::noncopyable { - public: - template - void register_handler(std::string const& name, Function f) { - return register_nonmember_func(name, std::move(f)); - } +class router : asio::noncopyable { +public: + template + void register_handler(std::string const &name, Function f) { + return register_nonmember_func(name, std::move(f)); + } - template - void register_handler(std::string const& name, const Function& f, Self* self) { - return register_member_func(name, f, self); - } + template + void register_handler(std::string const &name, const Function &f, + Self *self) { + return register_member_func(name, f, self); + } - void remove_handler(std::string const& name) { this->map_invokers_.erase(name); } + void remove_handler(std::string const &name) { + this->map_invokers_.erase(name); + } - template - void route(const char* data, std::size_t size, std::weak_ptr conn) { - auto conn_sp = conn.lock(); - if (!conn_sp) { - return; - } + template + void route(const char *data, std::size_t size, std::weak_ptr conn) { + auto conn_sp = conn.lock(); + if (!conn_sp) { + return; + } - auto req_id = conn_sp->request_id(); - std::string result; - try { - msgpack_codec codec; - auto p = codec.unpack>(data, size); - auto& func_name = std::get<0>(p); - auto it = map_invokers_.find(func_name); - if (it == map_invokers_.end()) { - result = codec.pack_args_str(result_code::FAIL, "unknown function: " + func_name); - conn_sp->response(req_id, std::move(result)); - return; - } + auto req_id = conn_sp->request_id(); + std::string result; + try { + msgpack_codec codec; + auto p = codec.unpack>(data, size); + auto &func_name = std::get<0>(p); + auto it = map_invokers_.find(func_name); + if (it == map_invokers_.end()) { + result = codec.pack_args_str(result_code::FAIL, + "unknown function: " + func_name); + conn_sp->response(req_id, std::move(result)); + return; + } - ExecMode model; - it->second(conn, data, size, result, model); - if (model == ExecMode::sync) { - if (result.size() >= MAX_BUF_LEN) { - result = codec.pack_args_str(result_code::FAIL, "the response result is out of range: more than 10M " + func_name); - } - conn_sp->response(req_id, std::move(result)); - } - } - catch (const std::exception & ex) { - msgpack_codec codec; - result = codec.pack_args_str(result_code::FAIL, ex.what()); - conn_sp->response(req_id, std::move(result)); - } - } + ExecMode model; + it->second(conn, data, size, result, model); + if (model == ExecMode::sync) { + if (result.size() >= MAX_BUF_LEN) { + result = codec.pack_args_str( + result_code::FAIL, + "the response result is out of range: more than 10M " + + func_name); + } + conn_sp->response(req_id, std::move(result)); + } + } catch (const std::exception &ex) { + msgpack_codec codec; + result = codec.pack_args_str(result_code::FAIL, ex.what()); + conn_sp->response(req_id, std::move(result)); + } + } - router() = default; + router() = default; - private: - router(const router&) = delete; - router(router&&) = delete; +private: + router(const router &) = delete; + router(router &&) = delete; - template - static typename std::result_of, Args...)>::type call_helper( - const F & f, const std::index_sequence&, std::tuple tup, std::weak_ptr ptr) { - return f(ptr, std::move(std::get(tup))...); - } + template + static typename std::result_of, Args...)>::type + call_helper(const F &f, const std::index_sequence &, + std::tuple tup, std::weak_ptr ptr) { + return f(ptr, std::move(std::get(tup))...); + } - template - static - typename std::enable_if, Args...)>::type>::value>::type - call(const F & f, std::weak_ptr ptr, std::string & result, std::tuple tp) { - call_helper(f, std::make_index_sequence{}, std::move(tp), ptr); - result = msgpack_codec::pack_args_str(result_code::OK); - } + template + static typename std::enable_if, Args...)>::type>::value>::type + call(const F &f, std::weak_ptr ptr, std::string &result, + std::tuple tp) { + call_helper(f, std::make_index_sequence{}, std::move(tp), + ptr); + result = msgpack_codec::pack_args_str(result_code::OK); + } - template - static - typename std::enable_if, Args...)>::type>::value>::type - call(const F & f, std::weak_ptr ptr, std::string & result, std::tuple tp) { - auto r = call_helper(f, std::make_index_sequence{}, std::move(tp), ptr); - msgpack_codec codec; - result = msgpack_codec::pack_args_str(result_code::OK, r); - } + template + static typename std::enable_if, Args...)>::type>::value>::type + call(const F &f, std::weak_ptr ptr, std::string &result, + std::tuple tp) { + auto r = call_helper(f, std::make_index_sequence{}, + std::move(tp), ptr); + msgpack_codec codec; + result = msgpack_codec::pack_args_str(result_code::OK, r); + } - template - static typename std::result_of, Args...)>::type call_member_helper( - const F & f, Self * self, const std::index_sequence&, - std::tuple tup, std::weak_ptr ptr = std::shared_ptr{ nullptr }) { - return (*self.*f)(ptr, std::move(std::get(tup))...); - } + template + static + typename std::result_of, Args...)>::type + call_member_helper(const F &f, Self *self, + const std::index_sequence &, + std::tuple tup, + std::weak_ptr ptr = + std::shared_ptr{nullptr}) { + return (*self.*f)(ptr, std::move(std::get(tup))...); + } - template - static typename std::enable_if< - std::is_void, Args...)>::type>::value>::type - call_member(const F & f, Self * self, std::weak_ptr ptr, std::string & result, - std::tuple tp) { - call_member_helper(f, self, typename std::make_index_sequence{}, std::move(tp), ptr); - result = msgpack_codec::pack_args_str(result_code::OK); - } + template + static typename std::enable_if, Args...)>::type>::value>::type + call_member(const F &f, Self *self, std::weak_ptr ptr, + std::string &result, std::tuple tp) { + call_member_helper(f, self, + typename std::make_index_sequence{}, + std::move(tp), ptr); + result = msgpack_codec::pack_args_str(result_code::OK); + } - template - static typename std::enable_if< - !std::is_void, Args...)>::type>::value>::type - call_member(const F & f, Self * self, std::weak_ptr ptr, std::string & result, - std::tuple tp) { - auto r = - call_member_helper(f, self, typename std::make_index_sequence{}, std::move(tp), ptr); - result = msgpack_codec::pack_args_str(result_code::OK, r); - } + template + static typename std::enable_if, Args...)>::type>::value>::type + call_member(const F &f, Self *self, std::weak_ptr ptr, + std::string &result, std::tuple tp) { + auto r = call_member_helper( + f, self, typename std::make_index_sequence{}, + std::move(tp), ptr); + result = msgpack_codec::pack_args_str(result_code::OK, r); + } - template - struct invoker { - template - static inline void apply(const Function& func, std::weak_ptr conn, const char* data, size_t size, - std::string& result, ExecMode& exe_model) { - using args_tuple = typename function_traits::args_tuple_2nd; - exe_model = ExecMode::sync; - msgpack_codec codec; - try { - auto tp = codec.unpack(data, size); - call(func, conn, result, std::move(tp)); - exe_model = model; - } - catch (std::invalid_argument & e) { - result = codec.pack_args_str(result_code::FAIL, e.what()); - } - catch (const std::exception & e) { - result = codec.pack_args_str(result_code::FAIL, e.what()); - } - } + template struct invoker { + template + static inline void apply(const Function &func, + std::weak_ptr conn, const char *data, + size_t size, std::string &result, + ExecMode &exe_model) { + using args_tuple = typename function_traits::args_tuple_2nd; + exe_model = ExecMode::sync; + msgpack_codec codec; + try { + auto tp = codec.unpack(data, size); + call(func, conn, result, std::move(tp)); + exe_model = model; + } catch (std::invalid_argument &e) { + result = codec.pack_args_str(result_code::FAIL, e.what()); + } catch (const std::exception &e) { + result = codec.pack_args_str(result_code::FAIL, e.what()); + } + } - template - static inline void apply_member(const Function& func, Self* self, std::weak_ptr conn, - const char* data, size_t size, std::string& result, - ExecMode& exe_model) { - using args_tuple = typename function_traits::args_tuple_2nd; - exe_model = ExecMode::sync; - msgpack_codec codec; - try { - auto tp = codec.unpack(data, size); - call_member(func, self, conn, result, std::move(tp)); - exe_model = model; - } - catch (std::invalid_argument & e) { - result = codec.pack_args_str(result_code::FAIL, e.what()); - } - catch (const std::exception & e) { - result = codec.pack_args_str(result_code::FAIL, e.what()); - } - } - }; + template + static inline void apply_member(const Function &func, Self *self, + std::weak_ptr conn, + const char *data, size_t size, + std::string &result, ExecMode &exe_model) { + using args_tuple = typename function_traits::args_tuple_2nd; + exe_model = ExecMode::sync; + msgpack_codec codec; + try { + auto tp = codec.unpack(data, size); + call_member(func, self, conn, result, std::move(tp)); + exe_model = model; + } catch (std::invalid_argument &e) { + result = codec.pack_args_str(result_code::FAIL, e.what()); + } catch (const std::exception &e) { + result = codec.pack_args_str(result_code::FAIL, e.what()); + } + } + }; - template - void register_nonmember_func(std::string const& name, Function f) { - this->map_invokers_[name] = { std::bind(&invoker::template apply, std::move(f), std::placeholders::_1, - std::placeholders::_2, std::placeholders::_3, - std::placeholders::_4, std::placeholders::_5) }; - } + template + void register_nonmember_func(std::string const &name, Function f) { + this->map_invokers_[name] = {std::bind( + &invoker::template apply, std::move(f), + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, + std::placeholders::_4, std::placeholders::_5)}; + } - template - void register_member_func(const std::string& name, const Function& f, Self* self) { - this->map_invokers_[name] = { std::bind(&invoker::template apply_member, - f, self, std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5) }; - } + template + void register_member_func(const std::string &name, const Function &f, + Self *self) { + this->map_invokers_[name] = {std::bind( + &invoker::template apply_member, f, self, + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, + std::placeholders::_4, std::placeholders::_5)}; + } - std::unordered_map, const char*, size_t, std::string&, ExecMode& model)>> - map_invokers_; - }; - } // namespace rpc_service -} // namespace rest_rpc + std::unordered_map< + std::string, std::function, const char *, + size_t, std::string &, ExecMode &model)>> + map_invokers_; +}; +} // namespace rpc_service +} // namespace rest_rpc -#endif // REST_RPC_ROUTER_H_ +#endif // REST_RPC_ROUTER_H_ diff --git a/include/rest_rpc/rpc_client.hpp b/include/rest_rpc/rpc_client.hpp index e11297e..82fd751 100644 --- a/include/rest_rpc/rpc_client.hpp +++ b/include/rest_rpc/rpc_client.hpp @@ -1,21 +1,21 @@ #pragma once -#include -#include -#include -#include -#include -#include "use_asio.hpp" #include "client_util.hpp" #include "const_vars.h" #include "meta_util.hpp" +#include "use_asio.hpp" +#include #include +#include +#include +#include +#include using namespace rest_rpc::rpc_service; namespace rest_rpc { /** - * The type to indicate the language of the client. + * The type to indicate the language of the client. */ enum class client_language_t { CPP = 0, @@ -192,7 +192,7 @@ public: // sync call #if __cplusplus > 201402L template - auto call(const std::string &rpc_name, Args &&... args) { + auto call(const std::string &rpc_name, Args &&...args) { std::future future = async_call(rpc_name, std::forward(args)...); auto status = future.wait_for(std::chrono::milliseconds(TIMEOUT)); @@ -209,13 +209,13 @@ public: } template - auto call(const std::string &rpc_name, Args &&... args) { + auto call(const std::string &rpc_name, Args &&...args) { return call(rpc_name, std::forward(args)...); } #else template typename std::enable_if::value>::type - call(const std::string &rpc_name, Args &&... args) { + call(const std::string &rpc_name, Args &&...args) { std::future future = async_call(rpc_name, std::forward(args)...); auto status = future.wait_for(std::chrono::milliseconds(TIMEOUT)); @@ -229,13 +229,13 @@ public: template typename std::enable_if::value>::type - call(const std::string &rpc_name, Args &&... args) { + call(const std::string &rpc_name, Args &&...args) { call(rpc_name, std::forward(args)...); } template typename std::enable_if::value, T>::type - call(const std::string &rpc_name, Args &&... args) { + call(const std::string &rpc_name, Args &&...args) { std::future future = async_call(rpc_name, std::forward(args)...); auto status = future.wait_for(std::chrono::milliseconds(TIMEOUT)); @@ -249,14 +249,14 @@ public: template typename std::enable_if::value, T>::type - call(const std::string &rpc_name, Args &&... args) { + call(const std::string &rpc_name, Args &&...args) { return call(rpc_name, std::forward(args)...); } #endif template std::future async_call(const std::string &rpc_name, - Args &&... args) { + Args &&...args) { auto p = std::make_shared>(); std::future future = p->get_future(); @@ -275,9 +275,9 @@ public: } /** - * This internal_async_call is used for other language client. - * We use callback to handle the result is received, so we should not - * add the future to the future map. + * This internal_async_call is used for other language client. + * We use callback to handle the result is received, so we should not + * add the future to the future map. */ long internal_async_call(const std::string &encoded_func_name_and_args) { auto p = std::make_shared>(); @@ -298,7 +298,7 @@ public: void async_call(const std::string &rpc_name, std::function cb, - Args &&... args) { + Args &&...args) { if (!has_connected_) { if (cb) cb(boost::asio::error::make_error_code( @@ -503,7 +503,8 @@ private: if (!ec) { // const uint32_t body_len = *((uint32_t*)(head_)); // auto req_id = *((std::uint64_t*)(head_ + sizeof(int32_t))); - // auto req_type = *(request_type*)(head_ + sizeof(int32_t) + sizeof(int64_t)); + // auto req_type = *(request_type*)(head_ + sizeof(int32_t) + + // sizeof(int64_t)); rpc_header *header = (rpc_header *)(head_); const uint32_t body_len = header->body_len; if (body_len > 0 && body_len < MAX_BUF_LEN) { @@ -776,7 +777,8 @@ private: ssl_context); // verify peer TODO #else - assert(is_ssl()); // please add definition CINATRA_ENABLE_SSL, not allowed coming in this branch + assert(is_ssl()); // please add definition CINATRA_ENABLE_SSL, not allowed + // coming in this branch #endif } @@ -869,4 +871,4 @@ private: client_language_t client_language_ = client_language_t::CPP; std::function on_result_received_callback_; }; -} +} // namespace rest_rpc diff --git a/include/rest_rpc/rpc_server.h b/include/rest_rpc/rpc_server.h index 2b0ed99..685facb 100644 --- a/include/rest_rpc/rpc_server.h +++ b/include/rest_rpc/rpc_server.h @@ -1,226 +1,231 @@ #ifndef REST_RPC_RPC_SERVER_H_ #define REST_RPC_RPC_SERVER_H_ -#include -#include -#include #include "connection.h" #include "io_service_pool.h" #include "router.h" +#include +#include +#include using boost::asio::ip::tcp; namespace rest_rpc { - namespace rpc_service { - using rpc_conn = std::weak_ptr; - class rpc_server : private asio::noncopyable { - public: - rpc_server(unsigned short port, size_t size, size_t timeout_seconds = 15, size_t check_seconds = 10) - : io_service_pool_(size), - acceptor_(io_service_pool_.get_io_service(), tcp::endpoint(tcp::v4(), port)), - timeout_seconds_(timeout_seconds), - check_seconds_(check_seconds) { - do_accept(); - check_thread_ = std::make_shared([this] { clean(); }); - pub_sub_thread_ = std::make_shared([this] { clean_sub_pub(); }); - } +namespace rpc_service { +using rpc_conn = std::weak_ptr; +class rpc_server : private asio::noncopyable { +public: + rpc_server(unsigned short port, size_t size, size_t timeout_seconds = 15, + size_t check_seconds = 10) + : io_service_pool_(size), acceptor_(io_service_pool_.get_io_service(), + tcp::endpoint(tcp::v4(), port)), + timeout_seconds_(timeout_seconds), check_seconds_(check_seconds) { + do_accept(); + check_thread_ = std::make_shared([this] { clean(); }); + pub_sub_thread_ = + std::make_shared([this] { clean_sub_pub(); }); + } - rpc_server(unsigned short port, size_t size, ssl_configure ssl_conf, size_t timeout_seconds = 15, size_t check_seconds = 10) : - rpc_server(port, size, timeout_seconds, check_seconds) { + rpc_server(unsigned short port, size_t size, ssl_configure ssl_conf, + size_t timeout_seconds = 15, size_t check_seconds = 10) + : rpc_server(port, size, timeout_seconds, check_seconds) { #ifdef CINATRA_ENABLE_SSL - ssl_conf_ = std::move(ssl_conf); + ssl_conf_ = std::move(ssl_conf); #else - assert(false);//please add definition CINATRA_ENABLE_SSL, not allowed coming in this branch + assert(false); // please add definition CINATRA_ENABLE_SSL, not allowed + // coming in this branch #endif - } + } - ~rpc_server() { - { - std::unique_lock lock(mtx_); - stop_check_ = true; - cv_.notify_all(); - } - check_thread_->join(); + ~rpc_server() { + { + std::unique_lock lock(mtx_); + stop_check_ = true; + cv_.notify_all(); + } + check_thread_->join(); - { - std::unique_lock lock(sub_mtx_); - stop_check_pub_sub_ = true; - sub_cv_.notify_all(); - } - pub_sub_thread_->join(); + { + std::unique_lock lock(sub_mtx_); + stop_check_pub_sub_ = true; + sub_cv_.notify_all(); + } + pub_sub_thread_->join(); - io_service_pool_.stop(); - if(thd_){ - thd_->join(); - } - } + io_service_pool_.stop(); + if (thd_) { + thd_->join(); + } + } - void async_run() { - thd_ = std::make_shared([this] { io_service_pool_.run(); }); - } + void async_run() { + thd_ = std::make_shared([this] { io_service_pool_.run(); }); + } - void run() { - io_service_pool_.run(); - } + void run() { io_service_pool_.run(); } - template - void register_handler(std::string const& name, const Function& f) { - router_.register_handler(name, f); - } + template + void register_handler(std::string const &name, const Function &f) { + router_.register_handler(name, f); + } - template - void register_handler(std::string const& name, const Function& f, Self* self) { - router_.register_handler(name, f, self); - } + template + void register_handler(std::string const &name, const Function &f, + Self *self) { + router_.register_handler(name, f, self); + } - void set_conn_timeout_callback(std::function callback) { - conn_timeout_callback_ = std::move(callback); - } + void set_conn_timeout_callback(std::function callback) { + conn_timeout_callback_ = std::move(callback); + } - template - void publish(const std::string& key, T data) { - publish(key, "", std::move(data)); - } + template void publish(const std::string &key, T data) { + publish(key, "", std::move(data)); + } - template - void publish_by_token(const std::string& key, std::string token, T data) { - publish(key, std::move(token), std::move(data)); - } + template + void publish_by_token(const std::string &key, std::string token, T data) { + publish(key, std::move(token), std::move(data)); + } - std::set get_token_list() { - std::unique_lock lock(sub_mtx_); - return token_list_; - } + std::set get_token_list() { + std::unique_lock lock(sub_mtx_); + return token_list_; + } - private: - void do_accept() { - conn_.reset(new connection(io_service_pool_.get_io_service(), timeout_seconds_, router_)); - conn_->set_callback([this](std::string key, std::string token, std::weak_ptr conn) { - std::unique_lock lock(sub_mtx_); - sub_map_.emplace(std::move(key) + token, conn); - if (!token.empty()) { - token_list_.emplace(std::move(token)); - } - }); +private: + void do_accept() { + conn_.reset(new connection(io_service_pool_.get_io_service(), + timeout_seconds_, router_)); + conn_->set_callback([this](std::string key, std::string token, + std::weak_ptr conn) { + std::unique_lock lock(sub_mtx_); + sub_map_.emplace(std::move(key) + token, conn); + if (!token.empty()) { + token_list_.emplace(std::move(token)); + } + }); - acceptor_.async_accept(conn_->socket(), [this](boost::system::error_code ec) { - if (ec) { - //LOG(INFO) << "acceptor error: " << ec.message(); - } - else { + acceptor_.async_accept(conn_->socket(), + [this](boost::system::error_code ec) { + if (ec) { + // LOG(INFO) << "acceptor error: " << + // ec.message(); + } else { #ifdef CINATRA_ENABLE_SSL - if (!ssl_conf_.cert_file.empty()) { - conn_->init_ssl_context(ssl_conf_); - } + if (!ssl_conf_.cert_file.empty()) { + conn_->init_ssl_context(ssl_conf_); + } #endif - conn_->start(); - std::unique_lock lock(mtx_); - conn_->set_conn_id(conn_id_); - connections_.emplace(conn_id_++, conn_); - } + conn_->start(); + std::unique_lock lock(mtx_); + conn_->set_conn_id(conn_id_); + connections_.emplace(conn_id_++, conn_); + } - do_accept(); - }); - } + do_accept(); + }); + } - void clean() { - while (!stop_check_) { - std::unique_lock lock(mtx_); - cv_.wait_for(lock, std::chrono::seconds(check_seconds_)); + void clean() { + while (!stop_check_) { + std::unique_lock lock(mtx_); + cv_.wait_for(lock, std::chrono::seconds(check_seconds_)); - for (auto it = connections_.cbegin(); it != connections_.cend();) { - if (it->second->has_closed()) { - if (conn_timeout_callback_) { - conn_timeout_callback_(it->second->conn_id()); - } - it = connections_.erase(it); - } - else { - ++it; - } - } - } - } + for (auto it = connections_.cbegin(); it != connections_.cend();) { + if (it->second->has_closed()) { + if (conn_timeout_callback_) { + conn_timeout_callback_(it->second->conn_id()); + } + it = connections_.erase(it); + } else { + ++it; + } + } + } + } - void clean_sub_pub() { - while (!stop_check_pub_sub_) { - std::unique_lock lock(sub_mtx_); - sub_cv_.wait_for(lock, std::chrono::seconds(10)); + void clean_sub_pub() { + while (!stop_check_pub_sub_) { + std::unique_lock lock(sub_mtx_); + sub_cv_.wait_for(lock, std::chrono::seconds(10)); - for (auto it = sub_map_.cbegin(); it != sub_map_.cend();) { - auto conn = it->second.lock(); - if (conn == nullptr || conn->has_closed()) { - it = sub_map_.erase(it); - } - else { - ++it; - } - } - } - } + for (auto it = sub_map_.cbegin(); it != sub_map_.cend();) { + auto conn = it->second.lock(); + if (conn == nullptr || conn->has_closed()) { + it = sub_map_.erase(it); + } else { + ++it; + } + } + } + } - template - void publish(std::string key, std::string token, T data) { - { - std::unique_lock lock(sub_mtx_); - if (sub_map_.empty()) - return; - } + template + void publish(std::string key, std::string token, T data) { + { + std::unique_lock lock(sub_mtx_); + if (sub_map_.empty()) + return; + } - std::shared_ptr shared_data = get_shared_data(std::move(data)); - std::unique_lock lock(sub_mtx_); - auto range = sub_map_.equal_range(key + token); - for (auto it = range.first; it != range.second; ++it) { - auto conn = it->second.lock(); - if (conn == nullptr || conn->has_closed()) { - continue; - } + std::shared_ptr shared_data = + get_shared_data(std::move(data)); + std::unique_lock lock(sub_mtx_); + auto range = sub_map_.equal_range(key + token); + for (auto it = range.first; it != range.second; ++it) { + auto conn = it->second.lock(); + if (conn == nullptr || conn->has_closed()) { + continue; + } - conn->publish(key + token, *shared_data); - } - } + conn->publish(key + token, *shared_data); + } + } - template - typename std::enable_if::value, std::shared_ptr>::type - get_shared_data(std::string data) { - return std::make_shared(std::move(data)); - } + template + typename std::enable_if::value, + std::shared_ptr>::type + get_shared_data(std::string data) { + return std::make_shared(std::move(data)); + } - template - typename std::enable_if::value, std::shared_ptr>::type - get_shared_data(T data) { - msgpack_codec codec; - auto buf = codec.pack(std::move(data)); - return std::make_shared(buf.data(), buf.size()); - } + template + typename std::enable_if::value, + std::shared_ptr>::type + get_shared_data(T data) { + msgpack_codec codec; + auto buf = codec.pack(std::move(data)); + return std::make_shared(buf.data(), buf.size()); + } - io_service_pool io_service_pool_; - tcp::acceptor acceptor_; - std::shared_ptr conn_; - std::shared_ptr thd_; - std::size_t timeout_seconds_; + io_service_pool io_service_pool_; + tcp::acceptor acceptor_; + std::shared_ptr conn_; + std::shared_ptr thd_; + std::size_t timeout_seconds_; - std::unordered_map> connections_; - int64_t conn_id_ = 0; - std::mutex mtx_; - std::shared_ptr check_thread_; - size_t check_seconds_; - bool stop_check_ = false; - std::condition_variable cv_; + std::unordered_map> connections_; + int64_t conn_id_ = 0; + std::mutex mtx_; + std::shared_ptr check_thread_; + size_t check_seconds_; + bool stop_check_ = false; + std::condition_variable cv_; - std::function conn_timeout_callback_; - std::unordered_multimap> sub_map_; - std::set token_list_; - std::mutex sub_mtx_; - std::condition_variable sub_cv_; + std::function conn_timeout_callback_; + std::unordered_multimap> sub_map_; + std::set token_list_; + std::mutex sub_mtx_; + std::condition_variable sub_cv_; - std::shared_ptr pub_sub_thread_; - bool stop_check_pub_sub_ = false; + std::shared_ptr pub_sub_thread_; + bool stop_check_pub_sub_ = false; - ssl_configure ssl_conf_; - router router_; - }; - } // namespace rpc_service -} // namespace rest_rpc + ssl_configure ssl_conf_; + router router_; +}; +} // namespace rpc_service +} // namespace rest_rpc -#endif // REST_RPC_RPC_SERVER_H_ \ No newline at end of file +#endif // REST_RPC_RPC_SERVER_H_ \ No newline at end of file diff --git a/include/rest_rpc/string_view.hpp b/include/rest_rpc/string_view.hpp index 840599e..b204695 100644 --- a/include/rest_rpc/string_view.hpp +++ b/include/rest_rpc/string_view.hpp @@ -3,94 +3,104 @@ #ifndef NONSTD_SV_LITE_H_INCLUDED #define NONSTD_SV_LITE_H_INCLUDED -#define string_view_lite_MAJOR 1 -#define string_view_lite_MINOR 2 -#define string_view_lite_PATCH 0 +#define string_view_lite_MAJOR 1 +#define string_view_lite_MINOR 2 +#define string_view_lite_PATCH 0 -#define string_view_lite_VERSION nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY(string_view_lite_MINOR) "." nssv_STRINGIFY(string_view_lite_PATCH) +#define string_view_lite_VERSION \ + nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY( \ + string_view_lite_MINOR) "." nssv_STRINGIFY(string_view_lite_PATCH) -#define nssv_STRINGIFY( x ) nssv_STRINGIFY_( x ) -#define nssv_STRINGIFY_( x ) #x +#define nssv_STRINGIFY(x) nssv_STRINGIFY_(x) +#define nssv_STRINGIFY_(x) #x // string-view lite configuration: -#define nssv_STRING_VIEW_DEFAULT 0 -#define nssv_STRING_VIEW_NONSTD 1 -#define nssv_STRING_VIEW_STD 2 +#define nssv_STRING_VIEW_DEFAULT 0 +#define nssv_STRING_VIEW_NONSTD 1 +#define nssv_STRING_VIEW_STD 2 -#if !defined( nssv_CONFIG_SELECT_STRING_VIEW ) -# define nssv_CONFIG_SELECT_STRING_VIEW ( nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD ) +#if !defined(nssv_CONFIG_SELECT_STRING_VIEW) +#define nssv_CONFIG_SELECT_STRING_VIEW \ + (nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD) #endif -#if defined( nssv_CONFIG_SELECT_STD_STRING_VIEW ) || defined( nssv_CONFIG_SELECT_NONSTD_STRING_VIEW ) -# error nssv_CONFIG_SELECT_STD_STRING_VIEW and nssv_CONFIG_SELECT_NONSTD_STRING_VIEW are deprecated and removed, please use nssv_CONFIG_SELECT_STRING_VIEW=nssv_STRING_VIEW_... +#if defined(nssv_CONFIG_SELECT_STD_STRING_VIEW) || \ + defined(nssv_CONFIG_SELECT_NONSTD_STRING_VIEW) +#error nssv_CONFIG_SELECT_STD_STRING_VIEW and nssv_CONFIG_SELECT_NONSTD_STRING_VIEW are deprecated and removed, please use nssv_CONFIG_SELECT_STRING_VIEW=nssv_STRING_VIEW_... #endif -#ifndef nssv_CONFIG_STD_SV_OPERATOR -# define nssv_CONFIG_STD_SV_OPERATOR 0 +#ifndef nssv_CONFIG_STD_SV_OPERATOR +#define nssv_CONFIG_STD_SV_OPERATOR 0 #endif -#ifndef nssv_CONFIG_USR_SV_OPERATOR -# define nssv_CONFIG_USR_SV_OPERATOR 1 +#ifndef nssv_CONFIG_USR_SV_OPERATOR +#define nssv_CONFIG_USR_SV_OPERATOR 1 #endif -#ifdef nssv_CONFIG_CONVERSION_STD_STRING -# define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS nssv_CONFIG_CONVERSION_STD_STRING -# define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS nssv_CONFIG_CONVERSION_STD_STRING +#ifdef nssv_CONFIG_CONVERSION_STD_STRING +#define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS \ + nssv_CONFIG_CONVERSION_STD_STRING +#define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS \ + nssv_CONFIG_CONVERSION_STD_STRING #endif -#ifndef nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS -# define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS 1 +#ifndef nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS +#define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS 1 #endif -#ifndef nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS -# define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS 1 +#ifndef nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS +#define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS 1 #endif // Control presence of exception handling (try and auto discover): #ifndef nssv_CONFIG_NO_EXCEPTIONS -# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND) -# define nssv_CONFIG_NO_EXCEPTIONS 0 -# else -# define nssv_CONFIG_NO_EXCEPTIONS 1 -# endif +#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND) +#define nssv_CONFIG_NO_EXCEPTIONS 0 +#else +#define nssv_CONFIG_NO_EXCEPTIONS 1 +#endif #endif // C++ language version detection (C++20 is speculative): // Note: VC14.0/1900 (VS2015) lacks too much from C++14. -#ifndef nssv_CPLUSPLUS -# if defined(_MSVC_LANG ) && !defined(__clang__) -# define nssv_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG ) -# else -# define nssv_CPLUSPLUS __cplusplus -# endif +#ifndef nssv_CPLUSPLUS +#if defined(_MSVC_LANG) && !defined(__clang__) +#define nssv_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG) +#else +#define nssv_CPLUSPLUS __cplusplus +#endif #endif -#define nssv_CPP98_OR_GREATER ( nssv_CPLUSPLUS >= 199711L ) -#define nssv_CPP11_OR_GREATER ( nssv_CPLUSPLUS >= 201103L ) -#define nssv_CPP11_OR_GREATER_ ( nssv_CPLUSPLUS >= 201103L ) -#define nssv_CPP14_OR_GREATER ( nssv_CPLUSPLUS >= 201402L ) -#define nssv_CPP17_OR_GREATER ( nssv_CPLUSPLUS >= 201703L ) -#define nssv_CPP20_OR_GREATER ( nssv_CPLUSPLUS >= 202000L ) +#define nssv_CPP98_OR_GREATER (nssv_CPLUSPLUS >= 199711L) +#define nssv_CPP11_OR_GREATER (nssv_CPLUSPLUS >= 201103L) +#define nssv_CPP11_OR_GREATER_ (nssv_CPLUSPLUS >= 201103L) +#define nssv_CPP14_OR_GREATER (nssv_CPLUSPLUS >= 201402L) +#define nssv_CPP17_OR_GREATER (nssv_CPLUSPLUS >= 201703L) +#define nssv_CPP20_OR_GREATER (nssv_CPLUSPLUS >= 202000L) // use C++17 std::string_view if available and requested: -#if nssv_CPP17_OR_GREATER && defined(__has_include ) -# if __has_include( ) -# define nssv_HAVE_STD_STRING_VIEW 1 -# else -# define nssv_HAVE_STD_STRING_VIEW 0 -# endif +#if nssv_CPP17_OR_GREATER && defined(__has_include) +#if __has_include( ) +#define nssv_HAVE_STD_STRING_VIEW 1 #else -# define nssv_HAVE_STD_STRING_VIEW 0 +#define nssv_HAVE_STD_STRING_VIEW 0 +#endif +#else +#define nssv_HAVE_STD_STRING_VIEW 0 #endif -#define nssv_USES_STD_STRING_VIEW ( (nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_STD) || ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_DEFAULT) && nssv_HAVE_STD_STRING_VIEW) ) +#define nssv_USES_STD_STRING_VIEW \ + ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_STD) || \ + ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_DEFAULT) && \ + nssv_HAVE_STD_STRING_VIEW)) -#define nssv_HAVE_STARTS_WITH ( nssv_CPP20_OR_GREATER || !nssv_USES_STD_STRING_VIEW ) -#define nssv_HAVE_ENDS_WITH nssv_HAVE_STARTS_WITH +#define nssv_HAVE_STARTS_WITH \ + (nssv_CPP20_OR_GREATER || !nssv_USES_STD_STRING_VIEW) +#define nssv_HAVE_ENDS_WITH nssv_HAVE_STARTS_WITH // // Use C++17 std::string_view: @@ -106,54 +116,58 @@ namespace nonstd { - template< class CharT, class Traits, class Allocator = std::allocator > - std::basic_string - to_string(std::basic_string_view v, Allocator const& a = Allocator()) { - return std::basic_string(v.begin(), v.end(), a); - } +template > +std::basic_string +to_string(std::basic_string_view v, + Allocator const &a = Allocator()) { + return std::basic_string(v.begin(), v.end(), a); +} - template< class CharT, class Traits, class Allocator > - std::basic_string_view - to_string_view(std::basic_string const& s) { - return std::basic_string_view(s.data(), s.size()); - } +template +std::basic_string_view +to_string_view(std::basic_string const &s) { + return std::basic_string_view(s.data(), s.size()); +} - // Literal operators sv and _sv: +// Literal operators sv and _sv: #if nssv_CONFIG_STD_SV_OPERATOR - using namespace std::literals::string_view_literals; +using namespace std::literals::string_view_literals; #endif #if nssv_CONFIG_USR_SV_OPERATOR - inline namespace literals { - inline namespace string_view_literals { +inline namespace literals { +inline namespace string_view_literals { +constexpr std::string_view operator"" _sv(const char *str, + size_t len) noexcept // (1) +{ + return std::string_view{str, len}; +} - constexpr std::string_view operator "" _sv(const char* str, size_t len) noexcept // (1) - { - return std::string_view{ str, len }; - } +constexpr std::u16string_view operator"" _sv(const char16_t *str, + size_t len) noexcept // (2) +{ + return std::u16string_view{str, len}; +} - constexpr std::u16string_view operator "" _sv(const char16_t* str, size_t len) noexcept // (2) - { - return std::u16string_view{ str, len }; - } +constexpr std::u32string_view operator"" _sv(const char32_t *str, + size_t len) noexcept // (3) +{ + return std::u32string_view{str, len}; +} - constexpr std::u32string_view operator "" _sv(const char32_t* str, size_t len) noexcept // (3) - { - return std::u32string_view{ str, len }; - } +constexpr std::wstring_view operator"" _sv(const wchar_t *str, + size_t len) noexcept // (4) +{ + return std::wstring_view{str, len}; +} - constexpr std::wstring_view operator "" _sv(const wchar_t* str, size_t len) noexcept // (4) - { - return std::wstring_view{ str, len }; - } - - } - } // namespace literals::string_view_literals +} // namespace string_view_literals +} // namespace literals #endif // nssv_CONFIG_USR_SV_OPERATOR @@ -163,22 +177,22 @@ namespace nonstd { namespace nonstd { - using std::string_view; - using std::wstring_view; - using std::u16string_view; - using std::u32string_view; - using std::basic_string_view; +using std::basic_string_view; +using std::string_view; +using std::u16string_view; +using std::u32string_view; +using std::wstring_view; - // literal "sv" and "_sv", see above +// literal "sv" and "_sv", see above - using std::operator==; - using std::operator!=; - using std::operator<; - using std::operator<=; - using std::operator>; - using std::operator>=; +using std::operator==; +using std::operator!=; +using std::operator<; +using std::operator<=; +using std::operator>; +using std::operator>=; - using std::operator<<; +using std::operator<<; } // namespace nonstd @@ -201,117 +215,127 @@ namespace nonstd { // MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) // MSVC++ 14.1 _MSC_VER >= 1910 (Visual Studio 2017) -#if defined(_MSC_VER ) && !defined(__clang__) -# define nssv_COMPILER_MSVC_VER (_MSC_VER ) -# define nssv_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) ) +#if defined(_MSC_VER) && !defined(__clang__) +#define nssv_COMPILER_MSVC_VER (_MSC_VER) +#define nssv_COMPILER_MSVC_VERSION \ + (_MSC_VER / 10 - 10 * (5 + (_MSC_VER < 1900))) #else -# define nssv_COMPILER_MSVC_VER 0 -# define nssv_COMPILER_MSVC_VERSION 0 +#define nssv_COMPILER_MSVC_VER 0 +#define nssv_COMPILER_MSVC_VERSION 0 #endif -#define nssv_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) ) +#define nssv_COMPILER_VERSION(major, minor, patch) \ + (10 * (10 * (major) + (minor)) + (patch)) #if defined(__clang__) -# define nssv_COMPILER_CLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) +#define nssv_COMPILER_CLANG_VERSION \ + nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) #else -# define nssv_COMPILER_CLANG_VERSION 0 +#define nssv_COMPILER_CLANG_VERSION 0 #endif #if defined(__GNUC__) && !defined(__clang__) -# define nssv_COMPILER_GNUC_VERSION nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#define nssv_COMPILER_GNUC_VERSION \ + nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) #else -# define nssv_COMPILER_GNUC_VERSION 0 +#define nssv_COMPILER_GNUC_VERSION 0 #endif // half-open range [lo..hi): -#define nssv_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) ) +#define nssv_BETWEEN(v, lo, hi) ((lo) <= (v) && (v) < (hi)) // Presence of language and library features: #ifdef _HAS_CPP0X -# define nssv_HAS_CPP0X _HAS_CPP0X +#define nssv_HAS_CPP0X _HAS_CPP0X #else -# define nssv_HAS_CPP0X 0 +#define nssv_HAS_CPP0X 0 #endif // Unless defined otherwise below, consider VC14 as C++11 for variant-lite: #if nssv_COMPILER_MSVC_VER >= 1900 -# undef nssv_CPP11_OR_GREATER -# define nssv_CPP11_OR_GREATER 1 +#undef nssv_CPP11_OR_GREATER +#define nssv_CPP11_OR_GREATER 1 #endif -#define nssv_CPP11_90 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1500) -#define nssv_CPP11_100 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1600) -#define nssv_CPP11_110 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1700) -#define nssv_CPP11_120 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1800) -#define nssv_CPP11_140 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1900) -#define nssv_CPP11_141 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1910) +#define nssv_CPP11_90 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1500) +#define nssv_CPP11_100 \ + (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1600) +#define nssv_CPP11_110 \ + (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1700) +#define nssv_CPP11_120 \ + (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1800) +#define nssv_CPP11_140 \ + (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1900) +#define nssv_CPP11_141 \ + (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1910) -#define nssv_CPP14_000 (nssv_CPP14_OR_GREATER) -#define nssv_CPP17_000 (nssv_CPP17_OR_GREATER) +#define nssv_CPP14_000 (nssv_CPP14_OR_GREATER) +#define nssv_CPP17_000 (nssv_CPP17_OR_GREATER) // Presence of C++11 language features: -#define nssv_HAVE_CONSTEXPR_11 nssv_CPP11_140 -#define nssv_HAVE_EXPLICIT_CONVERSION nssv_CPP11_140 -#define nssv_HAVE_INLINE_NAMESPACE nssv_CPP11_140 -#define nssv_HAVE_NOEXCEPT nssv_CPP11_140 -#define nssv_HAVE_NULLPTR nssv_CPP11_100 -#define nssv_HAVE_REF_QUALIFIER nssv_CPP11_140 -#define nssv_HAVE_UNICODE_LITERALS nssv_CPP11_140 +#define nssv_HAVE_CONSTEXPR_11 nssv_CPP11_140 +#define nssv_HAVE_EXPLICIT_CONVERSION nssv_CPP11_140 +#define nssv_HAVE_INLINE_NAMESPACE nssv_CPP11_140 +#define nssv_HAVE_NOEXCEPT nssv_CPP11_140 +#define nssv_HAVE_NULLPTR nssv_CPP11_100 +#define nssv_HAVE_REF_QUALIFIER nssv_CPP11_140 +#define nssv_HAVE_UNICODE_LITERALS nssv_CPP11_140 #define nssv_HAVE_USER_DEFINED_LITERALS nssv_CPP11_140 -#define nssv_HAVE_WCHAR16_T nssv_CPP11_100 -#define nssv_HAVE_WCHAR32_T nssv_CPP11_100 +#define nssv_HAVE_WCHAR16_T nssv_CPP11_100 +#define nssv_HAVE_WCHAR32_T nssv_CPP11_100 -#if ! ( ( nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION ) || nssv_BETWEEN( nssv_COMPILER_CLANG_VERSION, 300, 400 ) ) -# define nssv_HAVE_STD_DEFINED_LITERALS nssv_CPP11_140 +#if !((nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION) || \ + nssv_BETWEEN(nssv_COMPILER_CLANG_VERSION, 300, 400)) +#define nssv_HAVE_STD_DEFINED_LITERALS nssv_CPP11_140 #else -# define nssv_HAVE_STD_DEFINED_LITERALS 0 +#define nssv_HAVE_STD_DEFINED_LITERALS 0 #endif // Presence of C++14 language features: -#define nssv_HAVE_CONSTEXPR_14 nssv_CPP14_000 +#define nssv_HAVE_CONSTEXPR_14 nssv_CPP14_000 // Presence of C++17 language features: -#define nssv_HAVE_NODISCARD nssv_CPP17_000 +#define nssv_HAVE_NODISCARD nssv_CPP17_000 // Presence of C++ library features: -#define nssv_HAVE_STD_HASH nssv_CPP11_120 +#define nssv_HAVE_STD_HASH nssv_CPP11_120 // C++ feature usage: #if nssv_HAVE_CONSTEXPR_11 -# define nssv_constexpr constexpr +#define nssv_constexpr constexpr #else -# define nssv_constexpr /*constexpr*/ +#define nssv_constexpr /*constexpr*/ #endif -#if nssv_HAVE_CONSTEXPR_14 -# define nssv_constexpr14 constexpr +#if nssv_HAVE_CONSTEXPR_14 +#define nssv_constexpr14 constexpr #else -# define nssv_constexpr14 /*constexpr*/ +#define nssv_constexpr14 /*constexpr*/ #endif #if nssv_HAVE_EXPLICIT_CONVERSION -# define nssv_explicit explicit +#define nssv_explicit explicit #else -# define nssv_explicit /*explicit*/ +#define nssv_explicit /*explicit*/ #endif #if nssv_HAVE_INLINE_NAMESPACE -# define nssv_inline_ns inline +#define nssv_inline_ns inline #else -# define nssv_inline_ns /*inline*/ +#define nssv_inline_ns /*inline*/ #endif #if nssv_HAVE_NOEXCEPT -# define nssv_noexcept noexcept +#define nssv_noexcept noexcept #else -# define nssv_noexcept /*noexcept*/ +#define nssv_noexcept /*noexcept*/ #endif //#if nssv_HAVE_REF_QUALIFIER @@ -323,15 +347,15 @@ namespace nonstd { //#endif #if nssv_HAVE_NULLPTR -# define nssv_nullptr nullptr +#define nssv_nullptr nullptr #else -# define nssv_nullptr NULL +#define nssv_nullptr NULL #endif #if nssv_HAVE_NODISCARD -# define nssv_nodiscard [[nodiscard]] +#define nssv_nodiscard [[nodiscard]] #else -# define nssv_nodiscard /*[[nodiscard]]*/ +#define nssv_nodiscard /*[[nodiscard]]*/ #endif // Additional includes: @@ -341,45 +365,47 @@ namespace nonstd { #include #include #include -#include // std::char_traits<> +#include // std::char_traits<> -#if ! nssv_CONFIG_NO_EXCEPTIONS -# include +#if !nssv_CONFIG_NO_EXCEPTIONS +#include #endif #if nssv_CPP11_OR_GREATER -# include +#include #endif // Clang, GNUC, MSVC warning suppression macros: #if defined(__clang__) -# pragma clang diagnostic ignored "-Wreserved-user-defined-literal" -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wuser-defined-literals" +#pragma clang diagnostic ignored "-Wreserved-user-defined-literal" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wuser-defined-literals" #elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wliteral-suffix" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wliteral-suffix" #endif // __clang__ #if nssv_COMPILER_MSVC_VERSION >= 140 -# define nssv_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]] -# define nssv_SUPPRESS_MSVC_WARNING(code, descr) __pragma(warning(suppress: code) ) -# define nssv_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes)) +#define nssv_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]] +#define nssv_SUPPRESS_MSVC_WARNING(code, descr) \ + __pragma(warning(suppress : code)) +#define nssv_DISABLE_MSVC_WARNINGS(codes) \ + __pragma(warning(push)) __pragma(warning(disable : codes)) #else -# define nssv_SUPPRESS_MSGSL_WARNING(expr) -# define nssv_SUPPRESS_MSVC_WARNING(code, descr) -# define nssv_DISABLE_MSVC_WARNINGS(codes) +#define nssv_SUPPRESS_MSGSL_WARNING(expr) +#define nssv_SUPPRESS_MSVC_WARNING(code, descr) +#define nssv_DISABLE_MSVC_WARNINGS(codes) #endif #if defined(__clang__) -# define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") +#define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") #elif defined(__GNUC__) -# define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") +#define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") #elif nssv_COMPILER_MSVC_VERSION >= 140 -# define nssv_RESTORE_WARNINGS() __pragma(warning(pop )) +#define nssv_RESTORE_WARNINGS() __pragma(warning(pop)) #else -# define nssv_RESTORE_WARNINGS() +#define nssv_RESTORE_WARNINGS() #endif // Suppress the following MSVC (GSL) warnings: @@ -390,740 +416,788 @@ namespace nonstd { // - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead nssv_DISABLE_MSVC_WARNINGS(4455 26481 26472) -//nssv_DISABLE_CLANG_WARNINGS( "-Wuser-defined-literals" ) -//nssv_DISABLE_GNUC_WARNINGS( -Wliteral-suffix ) + // nssv_DISABLE_CLANG_WARNINGS( "-Wuser-defined-literals" ) + // nssv_DISABLE_GNUC_WARNINGS( -Wliteral-suffix ) -namespace nonstd { - namespace sv_lite { + namespace nonstd { + namespace sv_lite { #if nssv_CPP11_OR_GREATER - namespace detail { + namespace detail { - // Expect tail call optimization to make length() non-recursive: + // Expect tail call optimization to make length() non-recursive: - template< typename CharT > - inline constexpr std::size_t length(CharT* s, std::size_t result = 0) { - return *s == '\0' ? result : length(s + 1, result + 1); - } + template + inline constexpr std::size_t length(CharT *s, std::size_t result = 0) { + return *s == '\0' ? result : length(s + 1, result + 1); + } - } // namespace detail + } // namespace detail #endif // nssv_CPP11_OR_GREATER - template - < - class CharT, - class Traits = std::char_traits - > - class basic_string_view; + template > + class basic_string_view; - // - // basic_string_view: - // + // + // basic_string_view: + // - template - < - class CharT, - class Traits /* = std::char_traits */ - > - class basic_string_view { - public: - // Member types: + template */ + > + class basic_string_view { + public: + // Member types: - typedef Traits traits_type; - typedef CharT value_type; + typedef Traits traits_type; + typedef CharT value_type; - typedef CharT* pointer; - typedef CharT const* const_pointer; - typedef CharT& reference; - typedef CharT const& const_reference; + typedef CharT *pointer; + typedef CharT const *const_pointer; + typedef CharT &reference; + typedef CharT const &const_reference; - typedef const_pointer iterator; - typedef const_pointer const_iterator; - typedef std::reverse_iterator< const_iterator > reverse_iterator; - typedef std::reverse_iterator< const_iterator > const_reverse_iterator; + typedef const_pointer iterator; + typedef const_pointer const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; - // 24.4.2.1 Construction and assignment: + // 24.4.2.1 Construction and assignment: - nssv_constexpr basic_string_view() nssv_noexcept - : data_(nssv_nullptr) - , size_(0) { - } + nssv_constexpr basic_string_view() nssv_noexcept : data_(nssv_nullptr), + size_(0) {} #if nssv_CPP11_OR_GREATER - nssv_constexpr basic_string_view(basic_string_view const& other) nssv_noexcept = default; + nssv_constexpr + basic_string_view(basic_string_view const &other) nssv_noexcept = default; #else - nssv_constexpr basic_string_view(basic_string_view const& other) nssv_noexcept - : data_(other.data_) - , size_(other.size_) { - } + nssv_constexpr + basic_string_view(basic_string_view const &other) nssv_noexcept + : data_(other.data_), + size_(other.size_) {} #endif - nssv_constexpr basic_string_view(CharT const* s, size_type count) nssv_noexcept // non-standard noexcept - : data_(s) - , size_(count) { - } + nssv_constexpr basic_string_view(CharT const *s, size_type count) + nssv_noexcept // non-standard noexcept + : data_(s), + size_(count) {} - nssv_constexpr basic_string_view(CharT const* s) nssv_noexcept // non-standard noexcept - : data_(s) + nssv_constexpr + basic_string_view(CharT const *s) nssv_noexcept // non-standard noexcept + : data_(s) #if nssv_CPP17_OR_GREATER - , size_(Traits::length(s)) + , + size_(Traits::length(s)) #elif nssv_CPP11_OR_GREATER - , size_(detail::length(s)) + , + size_(detail::length(s)) #else - , size_(Traits::length(s)) + , + size_(Traits::length(s)) #endif - { - } + { + } - // Assignment: + // Assignment: #if nssv_CPP11_OR_GREATER - nssv_constexpr14 basic_string_view& operator=(basic_string_view const& other) nssv_noexcept = default; + nssv_constexpr14 basic_string_view & + operator=(basic_string_view const &other) nssv_noexcept = default; #else - nssv_constexpr14 basic_string_view& operator=(basic_string_view const& other) nssv_noexcept { - data_ = other.data_; - size_ = other.size_; - return *this; - } + nssv_constexpr14 basic_string_view & + operator=(basic_string_view const &other) nssv_noexcept { + data_ = other.data_; + size_ = other.size_; + return *this; + } #endif - // 24.4.2.2 Iterator support: + // 24.4.2.2 Iterator support: - nssv_constexpr const_iterator begin() const nssv_noexcept { return data_; } - nssv_constexpr const_iterator end() const nssv_noexcept { return data_ + size_; } + nssv_constexpr const_iterator begin() const nssv_noexcept { return data_; } + nssv_constexpr const_iterator end() const nssv_noexcept { + return data_ + size_; + } - nssv_constexpr const_iterator cbegin() const nssv_noexcept { return begin(); } - nssv_constexpr const_iterator cend() const nssv_noexcept { return end(); } + nssv_constexpr const_iterator cbegin() const nssv_noexcept { + return begin(); + } + nssv_constexpr const_iterator cend() const nssv_noexcept { return end(); } - nssv_constexpr const_reverse_iterator rbegin() const nssv_noexcept { return const_reverse_iterator(end()); } - nssv_constexpr const_reverse_iterator rend() const nssv_noexcept { return const_reverse_iterator(begin()); } + nssv_constexpr const_reverse_iterator rbegin() const nssv_noexcept { + return const_reverse_iterator(end()); + } + nssv_constexpr const_reverse_iterator rend() const nssv_noexcept { + return const_reverse_iterator(begin()); + } - nssv_constexpr const_reverse_iterator crbegin() const nssv_noexcept { return rbegin(); } - nssv_constexpr const_reverse_iterator crend() const nssv_noexcept { return rend(); } + nssv_constexpr const_reverse_iterator crbegin() const nssv_noexcept { + return rbegin(); + } + nssv_constexpr const_reverse_iterator crend() const nssv_noexcept { + return rend(); + } - // 24.4.2.3 Capacity: + // 24.4.2.3 Capacity: - nssv_constexpr size_type size() const nssv_noexcept { return size_; } - nssv_constexpr size_type length() const nssv_noexcept { return size_; } - nssv_constexpr size_type max_size() const nssv_noexcept { return (std::numeric_limits< size_type >::max)(); } + nssv_constexpr size_type size() const nssv_noexcept { return size_; } + nssv_constexpr size_type length() const nssv_noexcept { return size_; } + nssv_constexpr size_type max_size() const nssv_noexcept { + return (std::numeric_limits::max)(); + } - // since C++20 - nssv_nodiscard nssv_constexpr bool empty() const nssv_noexcept { - return 0 == size_; - } + // since C++20 + nssv_nodiscard nssv_constexpr bool empty() const nssv_noexcept { + return 0 == size_; + } - // 24.4.2.4 Element access: + // 24.4.2.4 Element access: - nssv_constexpr const_reference operator[](size_type pos) const { - return data_at(pos); - } + nssv_constexpr const_reference operator[](size_type pos) const { + return data_at(pos); + } - nssv_constexpr14 const_reference at(size_type pos) const { + nssv_constexpr14 const_reference at(size_type pos) const { #if nssv_CONFIG_NO_EXCEPTIONS - assert(pos < size()); + assert(pos < size()); #else - if (pos >= size()) { - throw std::out_of_range("nonstd::string_view::at()"); - } + if (pos >= size()) { + throw std::out_of_range("nonstd::string_view::at()"); + } #endif - return data_at(pos); - } + return data_at(pos); + } - nssv_constexpr const_reference front() const { return data_at(0); } - nssv_constexpr const_reference back() const { return data_at(size() - 1); } + nssv_constexpr const_reference front() const { return data_at(0); } + nssv_constexpr const_reference back() const { return data_at(size() - 1); } - nssv_constexpr const_pointer data() const nssv_noexcept { return data_; } + nssv_constexpr const_pointer data() const nssv_noexcept { return data_; } - // 24.4.2.5 Modifiers: + // 24.4.2.5 Modifiers: - nssv_constexpr14 void remove_prefix(size_type n) { - assert(n <= size()); - data_ += n; - size_ -= n; - } + nssv_constexpr14 void remove_prefix(size_type n) { + assert(n <= size()); + data_ += n; + size_ -= n; + } - nssv_constexpr14 void remove_suffix(size_type n) { - assert(n <= size()); - size_ -= n; - } + nssv_constexpr14 void remove_suffix(size_type n) { + assert(n <= size()); + size_ -= n; + } - nssv_constexpr14 void swap(basic_string_view & other) nssv_noexcept { - using std::swap; - swap(data_, other.data_); - swap(size_, other.size_); - } + nssv_constexpr14 void swap(basic_string_view &other) nssv_noexcept { + using std::swap; + swap(data_, other.data_); + swap(size_, other.size_); + } - // 24.4.2.6 String operations: + // 24.4.2.6 String operations: - size_type copy(CharT * dest, size_type n, size_type pos = 0) const { + size_type copy(CharT *dest, size_type n, size_type pos = 0) const { #if nssv_CONFIG_NO_EXCEPTIONS - assert(pos <= size()); + assert(pos <= size()); #else - if (pos > size()) { - throw std::out_of_range("nonstd::string_view::copy()"); - } + if (pos > size()) { + throw std::out_of_range("nonstd::string_view::copy()"); + } #endif - const size_type rlen = (std::min)(n, size() - pos); + const size_type rlen = (std::min)(n, size() - pos); - (void)Traits::copy(dest, data() + pos, rlen); + (void)Traits::copy(dest, data() + pos, rlen); - return rlen; - } + return rlen; + } - nssv_constexpr14 basic_string_view substr(size_type pos = 0, size_type n = npos) const { + nssv_constexpr14 basic_string_view substr(size_type pos = 0, + size_type n = npos) const { #if nssv_CONFIG_NO_EXCEPTIONS - assert(pos <= size()); + assert(pos <= size()); #else - if (pos > size()) { - throw std::out_of_range("nonstd::string_view::substr()"); - } + if (pos > size()) { + throw std::out_of_range("nonstd::string_view::substr()"); + } #endif - return basic_string_view(data() + pos, (std::min)(n, size() - pos)); - } + return basic_string_view(data() + pos, (std::min)(n, size() - pos)); + } - // compare(), 6x: + // compare(), 6x: - nssv_constexpr14 int compare(basic_string_view other) const nssv_noexcept // (1) - { - if (const int result = Traits::compare(data(), other.data(), (std::min)(size(), other.size()))) { - return result; - } + nssv_constexpr14 int + compare(basic_string_view other) const nssv_noexcept // (1) + { + if (const int result = Traits::compare( + data(), other.data(), (std::min)(size(), other.size()))) { + return result; + } - return size() == other.size() ? 0 : size() < other.size() ? -1 : 1; - } + return size() == other.size() ? 0 : size() < other.size() ? -1 : 1; + } - nssv_constexpr int compare(size_type pos1, size_type n1, basic_string_view other) const // (2) - { - return substr(pos1, n1).compare(other); - } + nssv_constexpr int compare(size_type pos1, size_type n1, + basic_string_view other) const // (2) + { + return substr(pos1, n1).compare(other); + } - nssv_constexpr int compare(size_type pos1, size_type n1, basic_string_view other, size_type pos2, size_type n2) const // (3) - { - return substr(pos1, n1).compare(other.substr(pos2, n2)); - } + nssv_constexpr int compare(size_type pos1, size_type n1, + basic_string_view other, size_type pos2, + size_type n2) const // (3) + { + return substr(pos1, n1).compare(other.substr(pos2, n2)); + } - nssv_constexpr int compare(CharT const* s) const // (4) - { - return compare(basic_string_view(s)); - } + nssv_constexpr int compare(CharT const *s) const // (4) + { + return compare(basic_string_view(s)); + } - nssv_constexpr int compare(size_type pos1, size_type n1, CharT const* s) const // (5) - { - return substr(pos1, n1).compare(basic_string_view(s)); - } + nssv_constexpr int compare(size_type pos1, size_type n1, + CharT const *s) const // (5) + { + return substr(pos1, n1).compare(basic_string_view(s)); + } - nssv_constexpr int compare(size_type pos1, size_type n1, CharT const* s, size_type n2) const // (6) - { - return substr(pos1, n1).compare(basic_string_view(s, n2)); - } + nssv_constexpr int compare(size_type pos1, size_type n1, CharT const *s, + size_type n2) const // (6) + { + return substr(pos1, n1).compare(basic_string_view(s, n2)); + } - // 24.4.2.7 Searching: + // 24.4.2.7 Searching: - // starts_with(), 3x, since C++20: + // starts_with(), 3x, since C++20: - nssv_constexpr bool starts_with(basic_string_view v) const nssv_noexcept // (1) - { - return size() >= v.size() && compare(0, v.size(), v) == 0; - } + nssv_constexpr bool + starts_with(basic_string_view v) const nssv_noexcept // (1) + { + return size() >= v.size() && compare(0, v.size(), v) == 0; + } - nssv_constexpr bool starts_with(CharT c) const nssv_noexcept // (2) - { - return starts_with(basic_string_view(&c, 1)); - } + nssv_constexpr bool starts_with(CharT c) const nssv_noexcept // (2) + { + return starts_with(basic_string_view(&c, 1)); + } - nssv_constexpr bool starts_with(CharT const* s) const // (3) - { - return starts_with(basic_string_view(s)); - } + nssv_constexpr bool starts_with(CharT const *s) const // (3) + { + return starts_with(basic_string_view(s)); + } - // ends_with(), 3x, since C++20: + // ends_with(), 3x, since C++20: - nssv_constexpr bool ends_with(basic_string_view v) const nssv_noexcept // (1) - { - return size() >= v.size() && compare(size() - v.size(), npos, v) == 0; - } + nssv_constexpr bool + ends_with(basic_string_view v) const nssv_noexcept // (1) + { + return size() >= v.size() && compare(size() - v.size(), npos, v) == 0; + } - nssv_constexpr bool ends_with(CharT c) const nssv_noexcept // (2) - { - return ends_with(basic_string_view(&c, 1)); - } + nssv_constexpr bool ends_with(CharT c) const nssv_noexcept // (2) + { + return ends_with(basic_string_view(&c, 1)); + } - nssv_constexpr bool ends_with(CharT const* s) const // (3) - { - return ends_with(basic_string_view(s)); - } + nssv_constexpr bool ends_with(CharT const *s) const // (3) + { + return ends_with(basic_string_view(s)); + } - // find(), 4x: + // find(), 4x: - nssv_constexpr14 size_type find(basic_string_view v, size_type pos = 0) const nssv_noexcept // (1) - { - return assert(v.size() == 0 || v.data() != nssv_nullptr) - , pos >= size() - ? npos - : to_pos(std::search(cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq)); - } + nssv_constexpr14 size_type + find(basic_string_view v, size_type pos = 0) const nssv_noexcept // (1) + { + return assert(v.size() == 0 || v.data() != nssv_nullptr), + pos >= size() + ? npos + : to_pos(std::search(cbegin() + pos, cend(), v.cbegin(), + v.cend(), Traits::eq)); + } - nssv_constexpr14 size_type find(CharT c, size_type pos = 0) const nssv_noexcept // (2) - { - return find(basic_string_view(&c, 1), pos); - } + nssv_constexpr14 size_type + find(CharT c, size_type pos = 0) const nssv_noexcept // (2) + { + return find(basic_string_view(&c, 1), pos); + } - nssv_constexpr14 size_type find(CharT const* s, size_type pos, size_type n) const // (3) - { - return find(basic_string_view(s, n), pos); - } + nssv_constexpr14 size_type find(CharT const *s, size_type pos, + size_type n) const // (3) + { + return find(basic_string_view(s, n), pos); + } - nssv_constexpr14 size_type find(CharT const* s, size_type pos = 0) const // (4) - { - return find(basic_string_view(s), pos); - } + nssv_constexpr14 size_type find(CharT const *s, + size_type pos = 0) const // (4) + { + return find(basic_string_view(s), pos); + } - // rfind(), 4x: + // rfind(), 4x: - nssv_constexpr14 size_type rfind(basic_string_view v, size_type pos = npos) const nssv_noexcept // (1) - { - if (size() < v.size()) { - return npos; - } + nssv_constexpr14 size_type + rfind(basic_string_view v, size_type pos = npos) const nssv_noexcept // (1) + { + if (size() < v.size()) { + return npos; + } - if (v.empty()) { - return (std::min)(size(), pos); - } + if (v.empty()) { + return (std::min)(size(), pos); + } - const_iterator last = cbegin() + (std::min)(size() - v.size(), pos) + v.size(); - const_iterator result = std::find_end(cbegin(), last, v.cbegin(), v.cend(), Traits::eq); + const_iterator last = + cbegin() + (std::min)(size() - v.size(), pos) + v.size(); + const_iterator result = + std::find_end(cbegin(), last, v.cbegin(), v.cend(), Traits::eq); - return result != last ? size_type(result - cbegin()) : npos; - } + return result != last ? size_type(result - cbegin()) : npos; + } - nssv_constexpr14 size_type rfind(CharT c, size_type pos = npos) const nssv_noexcept // (2) - { - return rfind(basic_string_view(&c, 1), pos); - } + nssv_constexpr14 size_type + rfind(CharT c, size_type pos = npos) const nssv_noexcept // (2) + { + return rfind(basic_string_view(&c, 1), pos); + } - nssv_constexpr14 size_type rfind(CharT const* s, size_type pos, size_type n) const // (3) - { - return rfind(basic_string_view(s, n), pos); - } + nssv_constexpr14 size_type rfind(CharT const *s, size_type pos, + size_type n) const // (3) + { + return rfind(basic_string_view(s, n), pos); + } - nssv_constexpr14 size_type rfind(CharT const* s, size_type pos = npos) const // (4) - { - return rfind(basic_string_view(s), pos); - } + nssv_constexpr14 size_type rfind(CharT const *s, + size_type pos = npos) const // (4) + { + return rfind(basic_string_view(s), pos); + } - // find_first_of(), 4x: + // find_first_of(), 4x: - nssv_constexpr size_type find_first_of(basic_string_view v, size_type pos = 0) const nssv_noexcept // (1) - { - return pos >= size() - ? npos - : to_pos(std::find_first_of(cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq)); - } + nssv_constexpr size_type find_first_of( + basic_string_view v, size_type pos = 0) const nssv_noexcept // (1) + { + return pos >= size() + ? npos + : to_pos(std::find_first_of(cbegin() + pos, cend(), v.cbegin(), + v.cend(), Traits::eq)); + } - nssv_constexpr size_type find_first_of(CharT c, size_type pos = 0) const nssv_noexcept // (2) - { - return find_first_of(basic_string_view(&c, 1), pos); - } + nssv_constexpr size_type + find_first_of(CharT c, size_type pos = 0) const nssv_noexcept // (2) + { + return find_first_of(basic_string_view(&c, 1), pos); + } - nssv_constexpr size_type find_first_of(CharT const* s, size_type pos, size_type n) const // (3) - { - return find_first_of(basic_string_view(s, n), pos); - } + nssv_constexpr size_type find_first_of(CharT const *s, size_type pos, + size_type n) const // (3) + { + return find_first_of(basic_string_view(s, n), pos); + } - nssv_constexpr size_type find_first_of(CharT const* s, size_type pos = 0) const // (4) - { - return find_first_of(basic_string_view(s), pos); - } + nssv_constexpr size_type find_first_of(CharT const *s, + size_type pos = 0) const // (4) + { + return find_first_of(basic_string_view(s), pos); + } - // find_last_of(), 4x: + // find_last_of(), 4x: - nssv_constexpr size_type find_last_of(basic_string_view v, size_type pos = npos) const nssv_noexcept // (1) - { - return empty() - ? npos - : pos >= size() - ? find_last_of(v, size() - 1) - : to_pos(std::find_first_of(const_reverse_iterator(cbegin() + pos + 1), crend(), v.cbegin(), v.cend(), Traits::eq)); - } + nssv_constexpr size_type find_last_of( + basic_string_view v, size_type pos = npos) const nssv_noexcept // (1) + { + return empty() ? npos + : pos >= size() ? find_last_of(v, size() - 1) + : to_pos(std::find_first_of( + const_reverse_iterator(cbegin() + pos + 1), + crend(), v.cbegin(), v.cend(), Traits::eq)); + } - nssv_constexpr size_type find_last_of(CharT c, size_type pos = npos) const nssv_noexcept // (2) - { - return find_last_of(basic_string_view(&c, 1), pos); - } + nssv_constexpr size_type + find_last_of(CharT c, size_type pos = npos) const nssv_noexcept // (2) + { + return find_last_of(basic_string_view(&c, 1), pos); + } - nssv_constexpr size_type find_last_of(CharT const* s, size_type pos, size_type count) const // (3) - { - return find_last_of(basic_string_view(s, count), pos); - } + nssv_constexpr size_type find_last_of(CharT const *s, size_type pos, + size_type count) const // (3) + { + return find_last_of(basic_string_view(s, count), pos); + } - nssv_constexpr size_type find_last_of(CharT const* s, size_type pos = npos) const // (4) - { - return find_last_of(basic_string_view(s), pos); - } + nssv_constexpr size_type find_last_of(CharT const *s, + size_type pos = npos) const // (4) + { + return find_last_of(basic_string_view(s), pos); + } - // find_first_not_of(), 4x: + // find_first_not_of(), 4x: - nssv_constexpr size_type find_first_not_of(basic_string_view v, size_type pos = 0) const nssv_noexcept // (1) - { - return pos >= size() - ? npos - : to_pos(std::find_if(cbegin() + pos, cend(), not_in_view(v))); - } + nssv_constexpr size_type find_first_not_of( + basic_string_view v, size_type pos = 0) const nssv_noexcept // (1) + { + return pos >= size() + ? npos + : to_pos(std::find_if(cbegin() + pos, cend(), not_in_view(v))); + } - nssv_constexpr size_type find_first_not_of(CharT c, size_type pos = 0) const nssv_noexcept // (2) - { - return find_first_not_of(basic_string_view(&c, 1), pos); - } + nssv_constexpr size_type + find_first_not_of(CharT c, size_type pos = 0) const nssv_noexcept // (2) + { + return find_first_not_of(basic_string_view(&c, 1), pos); + } - nssv_constexpr size_type find_first_not_of(CharT const* s, size_type pos, size_type count) const // (3) - { - return find_first_not_of(basic_string_view(s, count), pos); - } + nssv_constexpr size_type find_first_not_of(CharT const *s, size_type pos, + size_type count) const // (3) + { + return find_first_not_of(basic_string_view(s, count), pos); + } - nssv_constexpr size_type find_first_not_of(CharT const* s, size_type pos = 0) const // (4) - { - return find_first_not_of(basic_string_view(s), pos); - } + nssv_constexpr size_type find_first_not_of(CharT const *s, + size_type pos = 0) const // (4) + { + return find_first_not_of(basic_string_view(s), pos); + } - // find_last_not_of(), 4x: + // find_last_not_of(), 4x: - nssv_constexpr size_type find_last_not_of(basic_string_view v, size_type pos = npos) const nssv_noexcept // (1) - { - return empty() - ? npos - : pos >= size() - ? find_last_not_of(v, size() - 1) - : to_pos(std::find_if(const_reverse_iterator(cbegin() + pos + 1), crend(), not_in_view(v))); - } + nssv_constexpr size_type find_last_not_of( + basic_string_view v, size_type pos = npos) const nssv_noexcept // (1) + { + return empty() ? npos + : pos >= size() ? find_last_not_of(v, size() - 1) + : to_pos(std::find_if( + const_reverse_iterator(cbegin() + pos + 1), + crend(), not_in_view(v))); + } - nssv_constexpr size_type find_last_not_of(CharT c, size_type pos = npos) const nssv_noexcept // (2) - { - return find_last_not_of(basic_string_view(&c, 1), pos); - } + nssv_constexpr size_type + find_last_not_of(CharT c, size_type pos = npos) const nssv_noexcept // (2) + { + return find_last_not_of(basic_string_view(&c, 1), pos); + } - nssv_constexpr size_type find_last_not_of(CharT const* s, size_type pos, size_type count) const // (3) - { - return find_last_not_of(basic_string_view(s, count), pos); - } + nssv_constexpr size_type find_last_not_of(CharT const *s, size_type pos, + size_type count) const // (3) + { + return find_last_not_of(basic_string_view(s, count), pos); + } - nssv_constexpr size_type find_last_not_of(CharT const* s, size_type pos = npos) const // (4) - { - return find_last_not_of(basic_string_view(s), pos); - } + nssv_constexpr size_type find_last_not_of(CharT const *s, + size_type pos = npos) const // (4) + { + return find_last_not_of(basic_string_view(s), pos); + } - // Constants: + // Constants: #if nssv_CPP17_OR_GREATER - static nssv_constexpr size_type npos = size_type(-1); + static nssv_constexpr size_type npos = size_type(-1); #elif nssv_CPP11_OR_GREATER - enum : size_type { npos = size_type(-1) }; + enum : size_type { npos = size_type(-1) }; #else - enum { npos = size_type(-1) }; + enum { npos = size_type(-1) }; #endif - private: - struct not_in_view { - const basic_string_view v; + private: + struct not_in_view { + const basic_string_view v; - nssv_constexpr explicit not_in_view(basic_string_view v) : v(v) {} + nssv_constexpr explicit not_in_view(basic_string_view v) : v(v) {} - nssv_constexpr bool operator()(CharT c) const { - return npos == v.find_first_of(c); - } - }; + nssv_constexpr bool operator()(CharT c) const { + return npos == v.find_first_of(c); + } + }; - nssv_constexpr size_type to_pos(const_iterator it) const { - return it == cend() ? npos : size_type(it - cbegin()); - } + nssv_constexpr size_type to_pos(const_iterator it) const { + return it == cend() ? npos : size_type(it - cbegin()); + } - nssv_constexpr size_type to_pos(const_reverse_iterator it) const { - return it == crend() ? npos : size_type(crend() - it - 1); - } + nssv_constexpr size_type to_pos(const_reverse_iterator it) const { + return it == crend() ? npos : size_type(crend() - it - 1); + } - nssv_constexpr const_reference data_at(size_type pos) const { -#if nssv_BETWEEN( nssv_COMPILER_GNUC_VERSION, 1, 500 ) - return data_[pos]; + nssv_constexpr const_reference data_at(size_type pos) const { +#if nssv_BETWEEN(nssv_COMPILER_GNUC_VERSION, 1, 500) + return data_[pos]; #else - return assert(pos < size()), data_[pos]; + return assert(pos < size()), data_[pos]; #endif - } + } - private: - const_pointer data_; - size_type size_; + private: + const_pointer data_; + size_type size_; - public: + public: #if nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS - template< class Allocator > - basic_string_view(std::basic_string const& s) nssv_noexcept - : data_(s.data()) - , size_(s.size()) { - } + template + basic_string_view(std::basic_string const &s) + nssv_noexcept : data_(s.data()), + size_(s.size()) {} #if nssv_HAVE_EXPLICIT_CONVERSION - template< class Allocator > - explicit operator std::basic_string() const { - return to_string(Allocator()); - } + template + explicit operator std::basic_string() const { + return to_string(Allocator()); + } #endif // nssv_HAVE_EXPLICIT_CONVERSION #if nssv_CPP11_OR_GREATER - template< class Allocator = std::allocator > - std::basic_string - to_string(Allocator const& a = Allocator()) const { - return std::basic_string(begin(), end(), a); - } + template > + std::basic_string + to_string(Allocator const &a = Allocator()) const { + return std::basic_string(begin(), end(), a); + } #else - std::basic_string - to_string() const { - return std::basic_string(begin(), end()); - } + std::basic_string to_string() const { + return std::basic_string(begin(), end()); + } - template< class Allocator > - std::basic_string - to_string(Allocator const& a) const { - return std::basic_string(begin(), end(), a); - } + template + std::basic_string + to_string(Allocator const &a) const { + return std::basic_string(begin(), end(), a); + } #endif // nssv_CPP11_OR_GREATER #endif // nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS - }; + }; - // - // Non-member functions: - // + // + // Non-member functions: + // - // 24.4.3 Non-member comparison functions: - // lexicographically compare two string views (function template): + // 24.4.3 Non-member comparison functions: + // lexicographically compare two string views (function template): - template< class CharT, class Traits > - nssv_constexpr bool operator== ( - basic_string_view lhs, - basic_string_view rhs) nssv_noexcept { - return lhs.compare(rhs) == 0; - } + template + nssv_constexpr bool + operator==(basic_string_view lhs, + basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) == 0; + } - template< class CharT, class Traits > - nssv_constexpr bool operator!= ( - basic_string_view lhs, - basic_string_view rhs) nssv_noexcept { - return lhs.compare(rhs) != 0; - } + template + nssv_constexpr bool + operator!=(basic_string_view lhs, + basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) != 0; + } - template< class CharT, class Traits > - nssv_constexpr bool operator< ( - basic_string_view lhs, - basic_string_view rhs) nssv_noexcept { - return lhs.compare(rhs) < 0; - } + template + nssv_constexpr bool + operator<(basic_string_view lhs, + basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) < 0; + } - template< class CharT, class Traits > - nssv_constexpr bool operator<= ( - basic_string_view lhs, - basic_string_view rhs) nssv_noexcept { - return lhs.compare(rhs) <= 0; - } + template + nssv_constexpr bool + operator<=(basic_string_view lhs, + basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) <= 0; + } - template< class CharT, class Traits > - nssv_constexpr bool operator> ( - basic_string_view lhs, - basic_string_view rhs) nssv_noexcept { - return lhs.compare(rhs) > 0; - } + template + nssv_constexpr bool + operator>(basic_string_view lhs, + basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) > 0; + } - template< class CharT, class Traits > - nssv_constexpr bool operator>= ( - basic_string_view lhs, - basic_string_view rhs) nssv_noexcept { - return lhs.compare(rhs) >= 0; - } + template + nssv_constexpr bool + operator>=(basic_string_view lhs, + basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) >= 0; + } - // Let S be basic_string_view, and sv be an instance of S. - // Implementations shall provide sufficient additional overloads marked - // constexpr and noexcept so that an object t with an implicit conversion - // to S can be compared according to Table 67. + // Let S be basic_string_view, and sv be an instance of S. + // Implementations shall provide sufficient additional overloads marked + // constexpr and noexcept so that an object t with an implicit conversion + // to S can be compared according to Table 67. -#if nssv_CPP11_OR_GREATER && ! nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 100, 141 ) +#if nssv_CPP11_OR_GREATER && !nssv_BETWEEN(nssv_COMPILER_MSVC_VERSION, 100, 141) -#define nssv_BASIC_STRING_VIEW_I(T,U) typename std::decay< basic_string_view >::type +#define nssv_BASIC_STRING_VIEW_I(T, U) \ + typename std::decay>::type -#if nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 140, 150 ) -# define nssv_MSVC_ORDER(x) , int=x +#if nssv_BETWEEN(nssv_COMPILER_MSVC_VERSION, 140, 150) +#define nssv_MSVC_ORDER(x) , int = x #else -# define nssv_MSVC_ORDER(x) /*, int=x*/ +#define nssv_MSVC_ORDER(x) /*, int=x*/ #endif -// == + // == - template< class CharT, class Traits nssv_MSVC_ORDER(1) > - nssv_constexpr bool operator==( - basic_string_view lhs, - nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { - return lhs.compare(rhs) == 0; - } + template + nssv_constexpr bool operator==(basic_string_view lhs, + nssv_BASIC_STRING_VIEW_I(CharT, Traits) + rhs) nssv_noexcept { + return lhs.compare(rhs) == 0; + } - template< class CharT, class Traits nssv_MSVC_ORDER(2) > - nssv_constexpr bool operator==( - nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, - basic_string_view rhs) nssv_noexcept { - return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; - } + template + nssv_constexpr bool + operator==(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, + basic_string_view rhs) nssv_noexcept { + return lhs.size() == rhs.size() && lhs.compare(rhs) == 0; + } - // != + // != - template< class CharT, class Traits nssv_MSVC_ORDER(1) > - nssv_constexpr bool operator!= ( - basic_string_view < CharT, Traits > lhs, - nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { - return lhs.size() != rhs.size() || lhs.compare(rhs) != 0; - } + template + nssv_constexpr bool operator!=(basic_string_view lhs, + nssv_BASIC_STRING_VIEW_I(CharT, Traits) + rhs) nssv_noexcept { + return lhs.size() != rhs.size() || lhs.compare(rhs) != 0; + } - template< class CharT, class Traits nssv_MSVC_ORDER(2) > - nssv_constexpr bool operator!= ( - nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, - basic_string_view < CharT, Traits > rhs) nssv_noexcept { - return lhs.compare(rhs) != 0; - } + template + nssv_constexpr bool + operator!=(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, + basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) != 0; + } - // < + // < - template< class CharT, class Traits nssv_MSVC_ORDER(1) > - nssv_constexpr bool operator< ( - basic_string_view < CharT, Traits > lhs, - nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { - return lhs.compare(rhs) < 0; - } + template + nssv_constexpr bool operator<(basic_string_view lhs, + nssv_BASIC_STRING_VIEW_I(CharT, Traits) + rhs) nssv_noexcept { + return lhs.compare(rhs) < 0; + } - template< class CharT, class Traits nssv_MSVC_ORDER(2) > - nssv_constexpr bool operator< ( - nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, - basic_string_view < CharT, Traits > rhs) nssv_noexcept { - return lhs.compare(rhs) < 0; - } + template + nssv_constexpr bool + operator<(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, + basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) < 0; + } - // <= + // <= - template< class CharT, class Traits nssv_MSVC_ORDER(1) > - nssv_constexpr bool operator<= ( - basic_string_view < CharT, Traits > lhs, - nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { - return lhs.compare(rhs) <= 0; - } + template + nssv_constexpr bool operator<=(basic_string_view lhs, + nssv_BASIC_STRING_VIEW_I(CharT, Traits) + rhs) nssv_noexcept { + return lhs.compare(rhs) <= 0; + } - template< class CharT, class Traits nssv_MSVC_ORDER(2) > - nssv_constexpr bool operator<= ( - nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, - basic_string_view < CharT, Traits > rhs) nssv_noexcept { - return lhs.compare(rhs) <= 0; - } + template + nssv_constexpr bool + operator<=(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, + basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) <= 0; + } - // > + // > - template< class CharT, class Traits nssv_MSVC_ORDER(1) > - nssv_constexpr bool operator> ( - basic_string_view < CharT, Traits > lhs, - nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { - return lhs.compare(rhs) > 0; - } + template + nssv_constexpr bool operator>(basic_string_view lhs, + nssv_BASIC_STRING_VIEW_I(CharT, Traits) + rhs) nssv_noexcept { + return lhs.compare(rhs) > 0; + } - template< class CharT, class Traits nssv_MSVC_ORDER(2) > - nssv_constexpr bool operator> ( - nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, - basic_string_view < CharT, Traits > rhs) nssv_noexcept { - return lhs.compare(rhs) > 0; - } + template + nssv_constexpr bool + operator>(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, + basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) > 0; + } - // >= + // >= - template< class CharT, class Traits nssv_MSVC_ORDER(1) > - nssv_constexpr bool operator>= ( - basic_string_view < CharT, Traits > lhs, - nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs) nssv_noexcept { - return lhs.compare(rhs) >= 0; - } + template + nssv_constexpr bool operator>=(basic_string_view lhs, + nssv_BASIC_STRING_VIEW_I(CharT, Traits) + rhs) nssv_noexcept { + return lhs.compare(rhs) >= 0; + } - template< class CharT, class Traits nssv_MSVC_ORDER(2) > - nssv_constexpr bool operator>= ( - nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, - basic_string_view < CharT, Traits > rhs) nssv_noexcept { - return lhs.compare(rhs) >= 0; - } + template + nssv_constexpr bool + operator>=(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs, + basic_string_view rhs) nssv_noexcept { + return lhs.compare(rhs) >= 0; + } #undef nssv_MSVC_ORDER #undef nssv_BASIC_STRING_VIEW_I #endif // nssv_CPP11_OR_GREATER - // 24.4.4 Inserters and extractors: + // 24.4.4 Inserters and extractors: - namespace detail { + namespace detail { - template< class Stream > - void write_padding(Stream& os, std::streamsize n) { - for (std::streamsize i = 0; i < n; ++i) - os.rdbuf()->sputc(os.fill()); - } + template void write_padding(Stream &os, std::streamsize n) { + for (std::streamsize i = 0; i < n; ++i) + os.rdbuf()->sputc(os.fill()); + } - template< class Stream, class View > - Stream& write_to_stream(Stream & os, View const& sv) { - typename Stream::sentry sentry(os); + template + Stream &write_to_stream(Stream &os, View const &sv) { + typename Stream::sentry sentry(os); - if (!os) - return os; + if (!os) + return os; - const std::streamsize length = static_cast(sv.length()); + const std::streamsize length = static_cast(sv.length()); - // Whether, and how, to pad: - const bool pad = (length < os.width()); - const bool left_pad = pad && (os.flags() & std::ios_base::adjustfield) == std::ios_base::right; + // Whether, and how, to pad: + const bool pad = (length < os.width()); + const bool left_pad = pad && (os.flags() & std::ios_base::adjustfield) == + std::ios_base::right; - if (left_pad) - write_padding(os, os.width() - length); + if (left_pad) + write_padding(os, os.width() - length); - // Write span characters: - os.rdbuf()->sputn(sv.begin(), length); + // Write span characters: + os.rdbuf()->sputn(sv.begin(), length); - if (pad && !left_pad) - write_padding(os, os.width() - length); + if (pad && !left_pad) + write_padding(os, os.width() - length); - // Reset output stream width: - os.width(0); + // Reset output stream width: + os.width(0); - return os; - } + return os; + } - } // namespace detail + } // namespace detail - template< class CharT, class Traits > - std::basic_ostream& - operator<<( - std::basic_ostream & os, - basic_string_view sv) { - return detail::write_to_stream(os, sv); - } + template + std::basic_ostream & + operator<<(std::basic_ostream &os, + basic_string_view sv) { + return detail::write_to_stream(os, sv); + } - // Several typedefs for common character types are provided: + // Several typedefs for common character types are provided: - typedef basic_string_view string_view; - typedef basic_string_view wstring_view; + typedef basic_string_view string_view; + typedef basic_string_view wstring_view; #if nssv_HAVE_WCHAR16_T - typedef basic_string_view u16string_view; - typedef basic_string_view u32string_view; + typedef basic_string_view u16string_view; + typedef basic_string_view u32string_view; #endif - } + } // namespace sv_lite } // namespace nonstd::sv_lite // @@ -1133,60 +1207,67 @@ namespace nonstd { #if nssv_HAVE_USER_DEFINED_LITERALS namespace nonstd { - nssv_inline_ns namespace literals { - nssv_inline_ns namespace string_view_literals { +nssv_inline_ns namespace literals { + nssv_inline_ns namespace string_view_literals { #if nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS - nssv_constexpr nonstd::sv_lite::string_view operator "" sv(const char* str, size_t len) nssv_noexcept // (1) - { - return nonstd::sv_lite::string_view{ str, len }; - } + nssv_constexpr nonstd::sv_lite::string_view operator"" sv( + const char *str, size_t len) nssv_noexcept // (1) + { + return nonstd::sv_lite::string_view{str, len}; + } - nssv_constexpr nonstd::sv_lite::u16string_view operator "" sv(const char16_t* str, size_t len) nssv_noexcept // (2) - { - return nonstd::sv_lite::u16string_view{ str, len }; - } + nssv_constexpr nonstd::sv_lite::u16string_view operator"" sv( + const char16_t *str, size_t len) nssv_noexcept // (2) + { + return nonstd::sv_lite::u16string_view{str, len}; + } - nssv_constexpr nonstd::sv_lite::u32string_view operator "" sv(const char32_t* str, size_t len) nssv_noexcept // (3) - { - return nonstd::sv_lite::u32string_view{ str, len }; - } + nssv_constexpr nonstd::sv_lite::u32string_view operator"" sv( + const char32_t *str, size_t len) nssv_noexcept // (3) + { + return nonstd::sv_lite::u32string_view{str, len}; + } - nssv_constexpr nonstd::sv_lite::wstring_view operator "" sv(const wchar_t* str, size_t len) nssv_noexcept // (4) - { - return nonstd::sv_lite::wstring_view{ str, len }; - } + nssv_constexpr nonstd::sv_lite::wstring_view operator"" sv( + const wchar_t *str, size_t len) nssv_noexcept // (4) + { + return nonstd::sv_lite::wstring_view{str, len}; + } #endif // nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS #if nssv_CONFIG_USR_SV_OPERATOR - nssv_constexpr nonstd::sv_lite::string_view operator "" _sv(const char* str, size_t len) nssv_noexcept // (1) - { - return nonstd::sv_lite::string_view{ str, len }; - } + nssv_constexpr nonstd::sv_lite::string_view operator"" _sv( + const char *str, size_t len) nssv_noexcept // (1) + { + return nonstd::sv_lite::string_view{str, len}; + } - nssv_constexpr nonstd::sv_lite::u16string_view operator "" _sv(const char16_t* str, size_t len) nssv_noexcept // (2) - { - return nonstd::sv_lite::u16string_view{ str, len }; - } + nssv_constexpr nonstd::sv_lite::u16string_view operator"" _sv( + const char16_t *str, size_t len) nssv_noexcept // (2) + { + return nonstd::sv_lite::u16string_view{str, len}; + } - nssv_constexpr nonstd::sv_lite::u32string_view operator "" _sv(const char32_t* str, size_t len) nssv_noexcept // (3) - { - return nonstd::sv_lite::u32string_view{ str, len }; - } + nssv_constexpr nonstd::sv_lite::u32string_view operator"" _sv( + const char32_t *str, size_t len) nssv_noexcept // (3) + { + return nonstd::sv_lite::u32string_view{str, len}; + } - nssv_constexpr nonstd::sv_lite::wstring_view operator "" _sv(const wchar_t* str, size_t len) nssv_noexcept // (4) - { - return nonstd::sv_lite::wstring_view{ str, len }; - } + nssv_constexpr nonstd::sv_lite::wstring_view operator"" _sv( + const wchar_t *str, size_t len) nssv_noexcept // (4) + { + return nonstd::sv_lite::wstring_view{str, len}; + } #endif // nssv_CONFIG_USR_SV_OPERATOR - - } - } -} // namespace nonstd::literals::string_view_literals + } +} +} // namespace nonstd #endif @@ -1197,42 +1278,42 @@ namespace nonstd { #if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS namespace nonstd { - namespace sv_lite { +namespace sv_lite { - // Exclude MSVC 14 (19.00): it yields ambiguous to_string(): +// Exclude MSVC 14 (19.00): it yields ambiguous to_string(): #if nssv_CPP11_OR_GREATER && nssv_COMPILER_MSVC_VERSION != 140 - template< class CharT, class Traits, class Allocator = std::allocator > - std::basic_string - to_string(basic_string_view v, Allocator const& a = Allocator()) { - return std::basic_string(v.begin(), v.end(), a); - } +template > +std::basic_string +to_string(basic_string_view v, + Allocator const &a = Allocator()) { + return std::basic_string(v.begin(), v.end(), a); +} #else - template< class CharT, class Traits > - std::basic_string - to_string(basic_string_view v) { - return std::basic_string(v.begin(), v.end()); - } +template +std::basic_string to_string(basic_string_view v) { + return std::basic_string(v.begin(), v.end()); +} - template< class CharT, class Traits, class Allocator > - std::basic_string - to_string(basic_string_view v, Allocator const& a) { - return std::basic_string(v.begin(), v.end(), a); - } +template +std::basic_string +to_string(basic_string_view v, Allocator const &a) { + return std::basic_string(v.begin(), v.end(), a); +} #endif // nssv_CPP11_OR_GREATER - template< class CharT, class Traits, class Allocator > - basic_string_view - to_string_view(std::basic_string const& s) { - return basic_string_view(s.data(), s.size()); - } +template +basic_string_view +to_string_view(std::basic_string const &s) { + return basic_string_view(s.data(), s.size()); +} - } -} // namespace nonstd::sv_lite +} // namespace sv_lite +} // namespace nonstd #endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS @@ -1242,31 +1323,31 @@ namespace nonstd { namespace nonstd { - using sv_lite::basic_string_view; - using sv_lite::string_view; - using sv_lite::wstring_view; +using sv_lite::basic_string_view; +using sv_lite::string_view; +using sv_lite::wstring_view; #if nssv_HAVE_WCHAR16_T - using sv_lite::u16string_view; +using sv_lite::u16string_view; #endif #if nssv_HAVE_WCHAR32_T - using sv_lite::u32string_view; +using sv_lite::u32string_view; #endif - // literal "sv" +// literal "sv" - using sv_lite::operator==; - using sv_lite::operator!=; - using sv_lite::operator<; - using sv_lite::operator<=; - using sv_lite::operator>; - using sv_lite::operator>=; +using sv_lite::operator==; +using sv_lite::operator!=; +using sv_lite::operator<; +using sv_lite::operator<=; +using sv_lite::operator>; +using sv_lite::operator>=; - using sv_lite::operator<<; +using sv_lite::operator<<; #if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS - using sv_lite::to_string; - using sv_lite::to_string_view; +using sv_lite::to_string; +using sv_lite::to_string_view; #endif } // namespace nonstd @@ -1282,37 +1363,33 @@ namespace nonstd { namespace std { - template<> - struct hash< nonstd::string_view > { - public: - std::size_t operator()(nonstd::string_view v) const nssv_noexcept { - return std::hash()(std::string(v.data(), v.size())); - } - }; +template <> struct hash { +public: + std::size_t operator()(nonstd::string_view v) const nssv_noexcept { + return std::hash()(std::string(v.data(), v.size())); + } +}; - template<> - struct hash< nonstd::wstring_view > { - public: - std::size_t operator()(nonstd::wstring_view v) const nssv_noexcept { - return std::hash()(std::wstring(v.data(), v.size())); - } - }; +template <> struct hash { +public: + std::size_t operator()(nonstd::wstring_view v) const nssv_noexcept { + return std::hash()(std::wstring(v.data(), v.size())); + } +}; - template<> - struct hash< nonstd::u16string_view > { - public: - std::size_t operator()(nonstd::u16string_view v) const nssv_noexcept { - return std::hash()(std::u16string(v.data(), v.size())); - } - }; +template <> struct hash { +public: + std::size_t operator()(nonstd::u16string_view v) const nssv_noexcept { + return std::hash()(std::u16string(v.data(), v.size())); + } +}; - template<> - struct hash< nonstd::u32string_view > { - public: - std::size_t operator()(nonstd::u32string_view v) const nssv_noexcept { - return std::hash()(std::u32string(v.data(), v.size())); - } - }; +template <> struct hash { +public: + std::size_t operator()(nonstd::u32string_view v) const nssv_noexcept { + return std::hash()(std::u32string(v.data(), v.size())); + } +}; } // namespace std diff --git a/include/rest_rpc/use_asio.hpp b/include/rest_rpc/use_asio.hpp index 3ca808e..995158c 100644 --- a/include/rest_rpc/use_asio.hpp +++ b/include/rest_rpc/use_asio.hpp @@ -1,24 +1,23 @@ #pragma once #if defined(ASIO_STANDALONE) -//MSVC : define environment path 'ASIO_STANDALONE_INCLUDE', e.g. 'E:\bdlibs\asio-1.10.6\include' +// MSVC : define environment path 'ASIO_STANDALONE_INCLUDE', e.g. +// 'E:\bdlibs\asio-1.10.6\include' #include #ifdef CINATRA_ENABLE_SSL #include #endif -#include #include -namespace boost -{ - namespace asio - { - using namespace ::asio; - } - namespace system { - using ::std::error_code; - } +#include +namespace boost { +namespace asio { +using namespace ::asio; } +namespace system { +using ::std::error_code; +} +} // namespace boost #else #include #ifdef CINATRA_ENABLE_SSL @@ -47,7 +46,7 @@ using string_view = boost::string_view; #ifdef CINATRA_ENABLE_SSL #if __cplusplus > 201402L -#if defined (__GNUC__) +#if defined(__GNUC__) #if __GNUC__ < 8 #include namespace rpcfs = std::experimental::filesystem;