Compare commits
10 Commits
b8c3ed6b7d
...
32c2c860d9
Author | SHA1 | Date | |
---|---|---|---|
|
32c2c860d9 | ||
2ad8209814 | |||
264ac80d2b | |||
88bc6c11a1 | |||
e81337c3aa | |||
72acf69550 | |||
|
e05d90f1b3 | ||
edeb230c46 | |||
df14b67695 | |||
20750d1a80 |
2
.vscode/c_cpp_properties.json
vendored
2
.vscode/c_cpp_properties.json
vendored
@ -4,7 +4,7 @@
|
|||||||
"name": "Linux",
|
"name": "Linux",
|
||||||
"includePath": [
|
"includePath": [
|
||||||
"${workspaceFolder}/**",
|
"${workspaceFolder}/**",
|
||||||
"/opt/Libraries/boost_1_84_0/include"
|
"/opt/Libraries/boost_1_85_0/include"
|
||||||
],
|
],
|
||||||
"defines": [],
|
"defines": [],
|
||||||
"compilerPath": "/usr/bin/gcc",
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
@ -3,7 +3,6 @@ add_library(DataStructure
|
|||||||
ArrayList.h
|
ArrayList.h
|
||||||
BinaryTree.h
|
BinaryTree.h
|
||||||
BinarySearchTree.h
|
BinarySearchTree.h
|
||||||
CircularDoublyLinkedList.h
|
|
||||||
CircularLinkedList.h
|
CircularLinkedList.h
|
||||||
DoublyLinkedList.h
|
DoublyLinkedList.h
|
||||||
DynamicArray.h
|
DynamicArray.h
|
||||||
|
@ -1,141 +0,0 @@
|
|||||||
#ifndef DUALCIRCULARLIST_H
|
|
||||||
#define DUALCIRCULARLIST_H
|
|
||||||
|
|
||||||
#include "DoublyLinkedList.h"
|
|
||||||
|
|
||||||
namespace Kylin {
|
|
||||||
template <typename T>
|
|
||||||
class CircularDoublyLinkedList : public DoublyLinkedList<T> {
|
|
||||||
using Node = typename DoublyLinkedList<T>::Node;
|
|
||||||
using Iterator = typename DoublyLinkedList<T>::Iterator;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static constexpr size_t npos = static_cast<size_t>(-1);
|
|
||||||
CircularDoublyLinkedList() {
|
|
||||||
this->m_header.next = reinterpret_cast<Node *>(&(this->m_header));
|
|
||||||
this->m_header.prev = reinterpret_cast<Node *>(&(this->m_header));
|
|
||||||
this->m_last = reinterpret_cast<Node *>(&this->m_header);
|
|
||||||
}
|
|
||||||
|
|
||||||
CircularDoublyLinkedList(std::initializer_list<T> init) {
|
|
||||||
this->m_header.next = reinterpret_cast<Node *>(&(this->m_header));
|
|
||||||
this->m_header.prev = reinterpret_cast<Node *>(&(this->m_header));
|
|
||||||
this->m_last = reinterpret_cast<Node *>(&this->m_header);
|
|
||||||
for (auto &value : init) append(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
CircularDoublyLinkedList(const CircularDoublyLinkedList &other) {
|
|
||||||
this->m_header.next = reinterpret_cast<Node *>(&(this->m_header));
|
|
||||||
this->m_header.prev = reinterpret_cast<Node *>(&(this->m_header));
|
|
||||||
this->m_last = reinterpret_cast<Node *>(&this->m_header);
|
|
||||||
|
|
||||||
auto sourceNode = other.m_header.next;
|
|
||||||
auto targetNode = reinterpret_cast<Node *>(&this->m_header);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < other.m_size; i++) {
|
|
||||||
auto newNode = this->create();
|
|
||||||
if (newNode == nullptr) THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create node ...");
|
|
||||||
newNode->value = sourceNode->value;
|
|
||||||
newNode->prev = targetNode;
|
|
||||||
newNode->next = targetNode->next;
|
|
||||||
|
|
||||||
targetNode->next = newNode;
|
|
||||||
targetNode = newNode;
|
|
||||||
sourceNode = sourceNode->next;
|
|
||||||
this->m_size++;
|
|
||||||
this->m_last = targetNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CircularDoublyLinkedList(CircularDoublyLinkedList &&other) {
|
|
||||||
this->m_size = other.m_size;
|
|
||||||
this->m_header = other.m_header;
|
|
||||||
this->m_last = other.m_last;
|
|
||||||
|
|
||||||
other.m_size = 0;
|
|
||||||
other.m_header.next = nullptr;
|
|
||||||
other.m_last = reinterpret_cast<Node *>(&other.m_header);
|
|
||||||
}
|
|
||||||
|
|
||||||
void insert(size_t index, const T &value) override {
|
|
||||||
index = index % (this->m_size + 1);
|
|
||||||
if (index == this->m_size) return append(value);
|
|
||||||
auto node = this->create();
|
|
||||||
if (node == nullptr) THROW_EXCEPTION(NoEnoughMemoryException, "No momery to insert new element...");
|
|
||||||
|
|
||||||
node->value = value;
|
|
||||||
|
|
||||||
auto prev = position(index);
|
|
||||||
auto next = prev->next;
|
|
||||||
|
|
||||||
node->next = next;
|
|
||||||
node->prev = prev;
|
|
||||||
|
|
||||||
prev->next = node;
|
|
||||||
next->prev = node;
|
|
||||||
|
|
||||||
this->m_size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void append(const T &value) {
|
|
||||||
auto node = this->create();
|
|
||||||
if (node == nullptr) THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create node ...");
|
|
||||||
node->value = value;
|
|
||||||
|
|
||||||
node->prev = this->m_last;
|
|
||||||
node->next = this->m_last->next;
|
|
||||||
|
|
||||||
this->m_last->next->prev = node;
|
|
||||||
this->m_last->next = node;
|
|
||||||
|
|
||||||
this->m_last = node;
|
|
||||||
this->m_size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeAt(size_t index) override {
|
|
||||||
index = mod(index);
|
|
||||||
auto prev = position(index);
|
|
||||||
auto toDel = prev->next;
|
|
||||||
auto next = toDel->next;
|
|
||||||
|
|
||||||
prev->next = next;
|
|
||||||
next->prev = prev;
|
|
||||||
|
|
||||||
this->destroy(toDel);
|
|
||||||
|
|
||||||
this->m_size--;
|
|
||||||
}
|
|
||||||
|
|
||||||
T &last() override {
|
|
||||||
if (this->m_size <= 0) THROW_EXCEPTION(InvalidOperationException, "There is no element in the container.");
|
|
||||||
return this->m_header.prev->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() override {
|
|
||||||
while (this->m_size > 0) {
|
|
||||||
removeAt(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Iterator end() override { return Iterator(reinterpret_cast<Node *>(&this->m_header)); }
|
|
||||||
|
|
||||||
Iterator end() const override { return Iterator(reinterpret_cast<Node *>(&this->m_header)); }
|
|
||||||
|
|
||||||
~CircularDoublyLinkedList() { clear(); }
|
|
||||||
|
|
||||||
T &operator[](size_t index) override {
|
|
||||||
index = mod(index);
|
|
||||||
return position(index)->next->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
size_t mod(size_t index) const { return (this->m_size == 0) ? 0 : (index % this->m_size); }
|
|
||||||
Node *position(size_t index) const override {
|
|
||||||
auto node = reinterpret_cast<Node *>(&(this->m_header));
|
|
||||||
for (size_t i = 0; i < index; i++) {
|
|
||||||
node = node->next;
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace Kylin
|
|
||||||
#endif // DUALCIRCULARLIST_H
|
|
@ -28,7 +28,7 @@ target_include_directories(mbedtls-${MBEDTLS_VERSION}
|
|||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(Encrypt
|
target_link_libraries(Encrypt
|
||||||
PRIVATE mbedtls-${MBEDTLS_VERSION}
|
PUBLIC mbedtls-${MBEDTLS_VERSION}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
project(HttpProxy
|
project(HttpProxy
|
||||||
DESCRIPTION "router api is copy of boost_1_84_0/libs/url/example/router"
|
DESCRIPTION "router api is copy of boost_1_84_0/libs/url/example/router
|
||||||
|
root_certificates.hpp is copy of boost_1_84_0/libs/beast/example/common/root_certificates.hpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
find_package(Boost COMPONENTS url REQUIRED)
|
find_package(Boost COMPONENTS url REQUIRED)
|
||||||
@ -9,18 +10,23 @@ add_library(HttpProxy
|
|||||||
ProxyHttpSession.h ProxyHttpSession.cpp
|
ProxyHttpSession.h ProxyHttpSession.cpp
|
||||||
ProxyListener.h ProxyListener.cpp
|
ProxyListener.h ProxyListener.cpp
|
||||||
ProxyTcpSession.h ProxyTcpSession.cpp
|
ProxyTcpSession.h ProxyTcpSession.cpp
|
||||||
|
root_certificates.hpp
|
||||||
|
router.hpp
|
||||||
detail/impl/router.cpp
|
detail/impl/router.cpp
|
||||||
impl/matches.cpp
|
impl/matches.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(HttpProxy
|
target_include_directories(HttpProxy
|
||||||
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
|
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
PRIVATE ${OpenSSL_INCLUDE_DIR}
|
PRIVATE ${OPENSSL_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_directories(HttpProxy
|
||||||
|
PUBLIC ${OPENSSL_LIBRARY_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(HttpProxy
|
target_link_libraries(HttpProxy
|
||||||
PUBLIC ${Boost_LIBRARIES}
|
PUBLIC ${Boost_LIBRARIES}
|
||||||
PUBLIC Universal
|
PUBLIC Universal
|
||||||
PRIVATE ${OpenSSL_LIBRARY}
|
PRIVATE ${OPENSSL_LIBRARIES}
|
||||||
)
|
)
|
@ -1,166 +1,32 @@
|
|||||||
#include "NetworkUtility.h"
|
#include "NetworkUtility.h"
|
||||||
#include "BoostLog.h"
|
#include "BoostLog.h"
|
||||||
|
#include "root_certificates.hpp"
|
||||||
#include <boost/beast/core.hpp>
|
#include <boost/beast/core.hpp>
|
||||||
#include <boost/beast/http.hpp>
|
#include <boost/beast/http/dynamic_body.hpp>
|
||||||
#include <boost/beast/ssl.hpp>
|
#include <boost/beast/http/read.hpp>
|
||||||
|
#include <boost/beast/http/write.hpp>
|
||||||
|
#include <boost/beast/ssl/ssl_stream.hpp>
|
||||||
#include <boost/beast/version.hpp>
|
#include <boost/beast/version.hpp>
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
static std::optional<boost::beast::ssl_stream<boost::beast::tcp_stream>>
|
std::string Https::get(boost::asio::io_context &ioContext, const std::string &host, const std::string &port,
|
||||||
makeSslStream(boost::asio::io_context &ioContext, const std::string_view &host, const std::string_view &port,
|
const std::string &url, boost::system::error_code &error, Http::Version version) {
|
||||||
boost::system::error_code &error);
|
Http::Client client(ioContext, Http::SSL, version);
|
||||||
|
return client.get(host, port, url, error);
|
||||||
std::string Https::get(boost::asio::io_context &ioContext, const std::string_view &host, const std::string_view &port,
|
|
||||||
const std::string_view &url, boost::system::error_code &error, Http::Version version) {
|
|
||||||
namespace beast = boost::beast;
|
|
||||||
namespace http = boost::beast::http;
|
|
||||||
|
|
||||||
auto stream = makeSslStream(ioContext, host, port, error);
|
|
||||||
if (!stream) return std::string();
|
|
||||||
|
|
||||||
http::request<http::string_body> req{http::verb::get, url, static_cast<unsigned>(version)};
|
|
||||||
req.set(http::field::host, host);
|
|
||||||
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
|
||||||
http::write(*stream, req, error);
|
|
||||||
if (error) {
|
|
||||||
// LOG(error) << error.message();
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
beast::flat_buffer buffer;
|
|
||||||
http::response_parser<http::dynamic_body> parser;
|
|
||||||
parser.body_limit(std::numeric_limits<std::uint64_t>::max());
|
|
||||||
http::read(*stream, buffer, parser, error);
|
|
||||||
if (error) {
|
|
||||||
LOG(error) << error.message();
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
beast::error_code ec;
|
|
||||||
stream->shutdown(ec);
|
|
||||||
return boost::beast::buffers_to_string(parser.get().body().data());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Https::post(boost::asio::io_context &ioContext, const std::string_view &host, const std::string_view &port,
|
std::string Https::post(boost::asio::io_context &ioContext, const std::string &host, const std::string &port,
|
||||||
const std::string_view &url, const std::string_view &body, boost::system::error_code &error,
|
const std::string &url, const std::string &body, boost::system::error_code &error,
|
||||||
Http::Version version) {
|
Http::Version version) {
|
||||||
|
|
||||||
namespace beast = boost::beast;
|
Http::Client client(ioContext, Http::SSL, version);
|
||||||
namespace http = boost::beast::http;
|
return client.post(host, port, url, body, error);
|
||||||
|
|
||||||
auto stream = makeSslStream(ioContext, host, port, error);
|
|
||||||
if (!stream) return std::string();
|
|
||||||
|
|
||||||
http::request<http::string_body> req{http::verb::post, url.data(), static_cast<unsigned>(version)};
|
|
||||||
req.set(http::field::host, host);
|
|
||||||
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
|
||||||
req.body() = body;
|
|
||||||
req.prepare_payload();
|
|
||||||
http::write(*stream, req, error);
|
|
||||||
if (error) {
|
|
||||||
LOG(error) << error.message();
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
beast::flat_buffer buffer;
|
|
||||||
http::response<boost::beast::http::dynamic_body> response;
|
|
||||||
http::read(*stream, buffer, response, error);
|
|
||||||
if (error) {
|
|
||||||
LOG(error) << error.message();
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
beast::error_code ec;
|
|
||||||
stream->shutdown(ec);
|
|
||||||
return boost::beast::buffers_to_string(response.body().data());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Https::put(boost::asio::io_context &ioContext, const std::string &host, const std::string &port,
|
std::string Https::put(boost::asio::io_context &ioContext, const std::string &host, const std::string &port,
|
||||||
const std::string &url, const std::string &body, boost::system::error_code &error,
|
const std::string &url, const std::string &body, boost::system::error_code &error,
|
||||||
Http::Version version) {
|
Http::Version version) {
|
||||||
namespace beast = boost::beast;
|
Http::Client client(ioContext, Http::SSL, version);
|
||||||
namespace http = boost::beast::http;
|
return client.put(host, port, url, body, error);
|
||||||
|
|
||||||
auto stream = makeSslStream(ioContext, host, port, error);
|
|
||||||
if (!stream) return std::string();
|
|
||||||
|
|
||||||
http::request<http::string_body> req{http::verb::put, url.data(), static_cast<unsigned>(version)};
|
|
||||||
req.set(http::field::host, host);
|
|
||||||
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
|
||||||
req.body() = body;
|
|
||||||
req.prepare_payload();
|
|
||||||
http::write(*stream, req, error);
|
|
||||||
if (error) {
|
|
||||||
LOG(error) << error.message();
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
beast::flat_buffer buffer;
|
|
||||||
http::response<boost::beast::http::dynamic_body> response;
|
|
||||||
http::read(*stream, buffer, response, error);
|
|
||||||
if (error) {
|
|
||||||
LOG(error) << error.message();
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
beast::error_code ec;
|
|
||||||
stream->shutdown(ec);
|
|
||||||
return boost::beast::buffers_to_string(response.body().data());
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::optional<boost::beast::ssl_stream<boost::beast::tcp_stream>>
|
|
||||||
makeSslStream(boost::asio::io_context &ioContext, const std::string_view &host, const std::string_view &port,
|
|
||||||
boost::system::error_code &error) {
|
|
||||||
namespace beast = boost::beast;
|
|
||||||
namespace http = boost::beast::http;
|
|
||||||
|
|
||||||
namespace asio = boost::asio; // from <boost/asio.hpp>
|
|
||||||
using tcp = asio::ip::tcp;
|
|
||||||
|
|
||||||
namespace ssl = asio::ssl;
|
|
||||||
|
|
||||||
ssl::context sslContext(ssl::context::sslv23_client);
|
|
||||||
sslContext.set_default_verify_paths(error);
|
|
||||||
if (error) {
|
|
||||||
LOG(error) << error.message();
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::asio::ip::tcp::resolver resolver(ioContext);
|
|
||||||
|
|
||||||
beast::ssl_stream<beast::tcp_stream> stream(ioContext, sslContext);
|
|
||||||
|
|
||||||
auto const results = resolver.resolve(host, port, error);
|
|
||||||
if (error) {
|
|
||||||
LOG(error) << error.message();
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
beast::get_lowest_layer(stream).connect(results);
|
|
||||||
stream.handshake(ssl::stream_base::client);
|
|
||||||
return std::make_optional(std::move(stream));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Http::ParseItem> Http::parseFormData(const std::string_view &buffer) {
|
|
||||||
std::vector<ParseItem> ret;
|
|
||||||
|
|
||||||
auto pos = buffer.find("\r\n");
|
|
||||||
std::string_view m_spliter = buffer.substr(0, pos);
|
|
||||||
|
|
||||||
size_t m_end = buffer.rfind(m_spliter);
|
|
||||||
|
|
||||||
pos = 0;
|
|
||||||
while (pos != m_end) {
|
|
||||||
pos = buffer.find(m_spliter, pos);
|
|
||||||
if (pos == m_end) break;
|
|
||||||
ParseItem item;
|
|
||||||
auto dataSpliterPos = buffer.find("\r\n\r\n", pos);
|
|
||||||
item.begin = dataSpliterPos + 4;
|
|
||||||
item.end = buffer.find(m_spliter, pos + 1) - 2;
|
|
||||||
|
|
||||||
auto meta = buffer.substr(pos, dataSpliterPos - pos);
|
|
||||||
auto beginPos = meta.find("filename=\"") + 10;
|
|
||||||
auto endPos = meta.find("\"", beginPos);
|
|
||||||
item.filename = meta.substr(beginPos, endPos - beginPos);
|
|
||||||
pos++;
|
|
||||||
ret.push_back(item);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Network::htonll(uint64_t val) {
|
uint64_t Network::htonll(uint64_t val) {
|
||||||
@ -200,3 +66,184 @@ Network::~Network() {
|
|||||||
::WSACleanup();
|
::WSACleanup();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Http {
|
||||||
|
|
||||||
|
std::vector<ParseItem> parseFormData(const std::string_view &buffer) {
|
||||||
|
std::vector<ParseItem> ret;
|
||||||
|
|
||||||
|
auto pos = buffer.find("\r\n");
|
||||||
|
std::string_view m_spliter = buffer.substr(0, pos);
|
||||||
|
|
||||||
|
size_t m_end = buffer.rfind(m_spliter);
|
||||||
|
|
||||||
|
pos = 0;
|
||||||
|
while (pos != m_end) {
|
||||||
|
pos = buffer.find(m_spliter, pos);
|
||||||
|
if (pos == m_end) break;
|
||||||
|
ParseItem item;
|
||||||
|
auto dataSpliterPos = buffer.find("\r\n\r\n", pos);
|
||||||
|
item.begin = dataSpliterPos + 4;
|
||||||
|
item.end = buffer.find(m_spliter, pos + 1) - 2;
|
||||||
|
|
||||||
|
auto meta = buffer.substr(pos, dataSpliterPos - pos);
|
||||||
|
auto beginPos = meta.find("filename=\"") + 10;
|
||||||
|
auto endPos = meta.find("\"", beginPos);
|
||||||
|
item.filename = meta.substr(beginPos, endPos - beginPos);
|
||||||
|
pos++;
|
||||||
|
ret.push_back(item);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClientPrivate {
|
||||||
|
public:
|
||||||
|
std::unique_ptr<boost::beast::ssl_stream<boost::beast::tcp_stream>> sslStream;
|
||||||
|
std::unique_ptr<boost::beast::tcp_stream> tcpStream;
|
||||||
|
};
|
||||||
|
|
||||||
|
Client::Client(boost::asio::io_context &ioContext, Type type, Version version)
|
||||||
|
: m_d(new ClientPrivate()), m_ioContext(ioContext) {
|
||||||
|
m_request.version(static_cast<unsigned>(version));
|
||||||
|
using namespace boost::asio;
|
||||||
|
using namespace boost::beast;
|
||||||
|
m_request.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
||||||
|
|
||||||
|
if (type == SSL) {
|
||||||
|
m_sslContext = std::make_shared<ssl::context>(ssl::context::sslv23_client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Client::~Client() {
|
||||||
|
boost::system::error_code error;
|
||||||
|
shutdown(error);
|
||||||
|
if (error) {
|
||||||
|
LOG(error) << error.message();
|
||||||
|
}
|
||||||
|
if (m_d != nullptr) delete m_d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::loadRootCertificates(boost::system::error_code &error) {
|
||||||
|
if (m_sslContext) {
|
||||||
|
load_root_certificates(*m_sslContext, error);
|
||||||
|
if (!error) {
|
||||||
|
m_certificateLocation = CertificateLocation::Default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Client::get(const std::string &host, const std::string &port, const std::string &url,
|
||||||
|
boost::system::error_code &error) {
|
||||||
|
using namespace boost::beast;
|
||||||
|
m_request.method(http::verb::get);
|
||||||
|
m_request.target(url);
|
||||||
|
m_request.set(http::field::host, host);
|
||||||
|
return execute(host, port, m_request, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Client::post(const std::string &host, const std::string &port, const std::string &url,
|
||||||
|
const std::string &body, boost::system::error_code &error) {
|
||||||
|
using namespace boost::beast;
|
||||||
|
m_request.method(http::verb::post);
|
||||||
|
m_request.target(url);
|
||||||
|
m_request.set(http::field::host, host);
|
||||||
|
m_request.body() = body;
|
||||||
|
m_request.prepare_payload();
|
||||||
|
return execute(host, port, m_request, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Client::put(const std::string &host, const std::string &port, const std::string &url,
|
||||||
|
const std::string &body, boost::system::error_code &error) {
|
||||||
|
using namespace boost::beast;
|
||||||
|
m_request.method(http::verb::put);
|
||||||
|
m_request.target(url);
|
||||||
|
m_request.set(http::field::host, host);
|
||||||
|
m_request.body() = body;
|
||||||
|
m_request.prepare_payload();
|
||||||
|
return execute(host, port, m_request, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::addRequestField(boost::beast::http::field name, const std::string &value) {
|
||||||
|
m_request.set(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Client::execute(const std::string &host, const std::string &port, const Request &request,
|
||||||
|
boost::system::error_code &error) {
|
||||||
|
using namespace boost::beast;
|
||||||
|
|
||||||
|
if ((m_host != host) || (m_port != port) || (!m_d->sslStream && !m_d->tcpStream)) {
|
||||||
|
if (m_d->sslStream || m_d->tcpStream) {
|
||||||
|
boost::system::error_code errorCode;
|
||||||
|
shutdown(errorCode);
|
||||||
|
if (errorCode) {
|
||||||
|
LOG(error) << errorCode.message();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connect(host, port, error);
|
||||||
|
if (error) {
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_d->sslStream) {
|
||||||
|
http::write(*m_d->sslStream, request, error);
|
||||||
|
} else if (m_d->tcpStream) {
|
||||||
|
http::write(*m_d->tcpStream, request, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
http::response<http::dynamic_body> response;
|
||||||
|
if (!error) {
|
||||||
|
flat_buffer buffer;
|
||||||
|
if (m_d->sslStream) {
|
||||||
|
http::read(*m_d->sslStream, buffer, response, error);
|
||||||
|
} else if (m_d->tcpStream) {
|
||||||
|
http::read(*m_d->tcpStream, buffer, response, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return boost::beast::buffers_to_string(response.body().data());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::connect(const std::string &host, const std::string &port, boost::system::error_code &error) {
|
||||||
|
using namespace boost::asio::ip;
|
||||||
|
using namespace boost::beast;
|
||||||
|
tcp::resolver resolver(m_ioContext);
|
||||||
|
auto const results = resolver.resolve(host, port, error);
|
||||||
|
if (error) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_sslContext) {
|
||||||
|
if (m_certificateLocation == CertificateLocation::None) {
|
||||||
|
m_sslContext->set_default_verify_paths(error);
|
||||||
|
if (!error) m_certificateLocation = CertificateLocation::SystemDependent;
|
||||||
|
}
|
||||||
|
m_d->sslStream = std::make_unique<ssl_stream<tcp_stream>>(m_ioContext, *m_sslContext);
|
||||||
|
get_lowest_layer(*m_d->sslStream).connect(results, error);
|
||||||
|
if (error) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_d->sslStream->handshake(ssl::stream_base::client, error);
|
||||||
|
} else {
|
||||||
|
m_d->tcpStream = std::make_unique<tcp_stream>(m_ioContext);
|
||||||
|
m_d->tcpStream->connect(results, error);
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_host = host;
|
||||||
|
m_port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::shutdown(boost::system::error_code &error) {
|
||||||
|
using namespace boost::asio::ip;
|
||||||
|
if (m_d->sslStream) {
|
||||||
|
m_d->sslStream->shutdown(error);
|
||||||
|
m_d->sslStream.reset();
|
||||||
|
} else if (m_d->tcpStream) {
|
||||||
|
m_d->tcpStream->socket().shutdown(tcp::socket::shutdown_both, error);
|
||||||
|
m_d->tcpStream.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Http
|
||||||
|
@ -1,12 +1,21 @@
|
|||||||
#ifndef __NETWORKUTILITY_H__
|
#ifndef __NETWORKUTILITY_H__
|
||||||
#define __NETWORKUTILITY_H__
|
#define __NETWORKUTILITY_H__
|
||||||
|
|
||||||
#include "Singleton.h"
|
#include "Singleton.h"
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
|
#include <boost/beast/http/string_body.hpp>
|
||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace asio {
|
||||||
|
namespace ssl {
|
||||||
|
class context;
|
||||||
|
}
|
||||||
|
} // namespace asio
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
class Network {
|
class Network {
|
||||||
friend class Amass::Singleton<Network, Amass::GlobalInstance>;
|
friend class Amass::Singleton<Network, Amass::GlobalInstance>;
|
||||||
|
|
||||||
@ -20,20 +29,30 @@ protected:
|
|||||||
~Network();
|
~Network();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Http {
|
namespace Http {
|
||||||
public:
|
using Request = boost::beast::http::request<boost::beast::http::string_body>;
|
||||||
enum Version : unsigned {
|
enum Type {
|
||||||
|
Transparent,
|
||||||
|
SSL,
|
||||||
|
};
|
||||||
|
enum CertificateLocation {
|
||||||
|
None,
|
||||||
|
Default,
|
||||||
|
SystemDependent,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Version : unsigned {
|
||||||
Version_1_1 = 11,
|
Version_1_1 = 11,
|
||||||
};
|
};
|
||||||
struct ParseItem {
|
struct ParseItem {
|
||||||
std::string filename;
|
std::string filename;
|
||||||
// std::string::const_iterator begin;
|
// std::string::const_iterator begin;
|
||||||
// std::string::const_iterator end;
|
// std::string::const_iterator end;
|
||||||
size_t begin;
|
size_t begin;
|
||||||
size_t end;
|
size_t end;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
*
|
*
|
||||||
* @param buffer
|
* @param buffer
|
||||||
@ -47,18 +66,50 @@ public:
|
|||||||
* ofs.close();
|
* ofs.close();
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
static std::vector<ParseItem> parseFormData(const std::string_view &buffer);
|
static std::vector<ParseItem> parseFormData(const std::string_view &buffer);
|
||||||
|
|
||||||
|
class ClientPrivate;
|
||||||
|
class Client {
|
||||||
|
public:
|
||||||
|
Client(boost::asio::io_context &ioContext, Type type, Version version = Version_1_1);
|
||||||
|
~Client();
|
||||||
|
void loadRootCertificates(boost::system::error_code &error);
|
||||||
|
std::string get(const std::string &host, const std::string &port, const std::string &url,
|
||||||
|
boost::system::error_code &error);
|
||||||
|
std::string post(const std::string &host, const std::string &port, const std::string &url, const std::string &body,
|
||||||
|
boost::system::error_code &error);
|
||||||
|
std::string put(const std::string &host, const std::string &port, const std::string &url, const std::string &body,
|
||||||
|
boost::system::error_code &error);
|
||||||
|
|
||||||
|
void addRequestField(boost::beast::http::field name, const std::string &value);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string execute(const std::string &host, const std::string &port, const Request &request,
|
||||||
|
boost::system::error_code &error);
|
||||||
|
void connect(const std::string &host, const std::string &port, boost::system::error_code &error);
|
||||||
|
void shutdown(boost::system::error_code &error);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ClientPrivate *m_d = nullptr;
|
||||||
|
boost::asio::io_context &m_ioContext;
|
||||||
|
std::shared_ptr<boost::asio::ssl::context> m_sslContext;
|
||||||
|
CertificateLocation m_certificateLocation = CertificateLocation::None;
|
||||||
|
std::string m_host;
|
||||||
|
std::string m_port;
|
||||||
|
Request m_request;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace Http
|
||||||
|
|
||||||
class Https {
|
class Https {
|
||||||
public:
|
public:
|
||||||
static std::string get(boost::asio::io_context &ioContext, const std::string_view &host,
|
static std::string get(boost::asio::io_context &ioContext, const std::string &host, const std::string &port,
|
||||||
const std::string_view &port, const std::string_view &url, boost::system::error_code &error,
|
const std::string &url, boost::system::error_code &error,
|
||||||
Http::Version version = Http::Version_1_1);
|
Http::Version version = Http::Version_1_1);
|
||||||
|
|
||||||
static std::string post(boost::asio::io_context &ioContext, const std::string_view &host,
|
static std::string post(boost::asio::io_context &ioContext, const std::string &host, const std::string &port,
|
||||||
const std::string_view &port, const std::string_view &url, const std::string_view &body,
|
const std::string &url, const std::string &body, boost::system::error_code &error,
|
||||||
boost::system::error_code &error, Http::Version version = Http::Version_1_1);
|
Http::Version version = Http::Version_1_1);
|
||||||
|
|
||||||
static std::string put(boost::asio::io_context &ioContext, const std::string &host, const std::string &port,
|
static std::string put(boost::asio::io_context &ioContext, const std::string &host, const std::string &port,
|
||||||
const std::string &url, const std::string &body, boost::system::error_code &error,
|
const std::string &url, const std::string &body, boost::system::error_code &error,
|
||||||
|
3963
HttpProxy/root_certificates.hpp
Normal file
3963
HttpProxy/root_certificates.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|||||||
add_executable(UnitTest main.cpp
|
add_executable(UnitTest main.cpp
|
||||||
DataStructure/BinarySearchTreeTest.cpp
|
DataStructure/BinarySearchTreeTest.cpp
|
||||||
DataStructure/BinaryTreeTest.cpp
|
DataStructure/BinaryTreeTest.cpp
|
||||||
DataStructure/CircularDoublyLinkedListTest.cpp
|
|
||||||
DataStructure/CircularLinkedListTest.cpp
|
DataStructure/CircularLinkedListTest.cpp
|
||||||
DataStructure/DoublyLinkedListTest.cpp
|
DataStructure/DoublyLinkedListTest.cpp
|
||||||
DataStructure/DynamicArrayListTest.cpp
|
DataStructure/DynamicArrayListTest.cpp
|
||||||
@ -31,6 +30,9 @@ add_executable(UnitTest main.cpp
|
|||||||
HttpProxy/BoostUrlTest.cpp
|
HttpProxy/BoostUrlTest.cpp
|
||||||
|
|
||||||
Universal/BoostLogTest.cpp
|
Universal/BoostLogTest.cpp
|
||||||
|
Universal/DateTimeTest.cpp
|
||||||
|
Universal/MessageManagerTest.cpp
|
||||||
|
Universal/SingletonTest.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_definitions(UnitTest
|
target_compile_definitions(UnitTest
|
||||||
|
@ -1,108 +0,0 @@
|
|||||||
#include "CircularDoublyLinkedList.h"
|
|
||||||
#include <boost/test/unit_test.hpp>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace Kylin;
|
|
||||||
|
|
||||||
class CircularDoublyLinkedListTest {
|
|
||||||
public:
|
|
||||||
CircularDoublyLinkedList<size_t> list{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
|
||||||
};
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE(CircularDoublyLinkedListTestCase)
|
|
||||||
BOOST_FIXTURE_TEST_CASE(At, CircularDoublyLinkedListTest) { BOOST_CHECK_EQUAL(list.at(5), 5); }
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(Size, CircularDoublyLinkedListTest) { BOOST_CHECK_EQUAL(list.size(), 10); }
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(Last, CircularDoublyLinkedListTest) { BOOST_CHECK_EQUAL(list.last(), 9); }
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(EmptyListCallLastCauseException, CircularDoublyLinkedListTest) {
|
|
||||||
CircularDoublyLinkedList<size_t> emptyList;
|
|
||||||
BOOST_CHECK_THROW(emptyList.last(), InvalidOperationException);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(CallLastAfterRemoveLastElement, CircularDoublyLinkedListTest) {
|
|
||||||
list.removeAt(list.size() - 1);
|
|
||||||
BOOST_CHECK_EQUAL(list.last(), 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(RemoveIndexLessThenSize, CircularDoublyLinkedListTest) {
|
|
||||||
list.removeAt(3);
|
|
||||||
BOOST_CHECK_EQUAL(list[3], 4);
|
|
||||||
BOOST_CHECK_EQUAL(list.length(), 9);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(RemoveIndexBigThenSize, CircularDoublyLinkedListTest) {
|
|
||||||
list.removeAt(15);
|
|
||||||
BOOST_CHECK_EQUAL(list[5], 6);
|
|
||||||
BOOST_CHECK_EQUAL(list.length(), 9);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(Clear, CircularDoublyLinkedListTest) {
|
|
||||||
list.clear();
|
|
||||||
BOOST_CHECK_EQUAL(list.length(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(IndexOf, CircularDoublyLinkedListTest) { BOOST_CHECK_EQUAL(list.indexOf(5), 5); }
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(Append, CircularDoublyLinkedListTest) {
|
|
||||||
list.append(198);
|
|
||||||
BOOST_CHECK_EQUAL(list.length(), 11);
|
|
||||||
BOOST_CHECK_EQUAL(list.at(list.size() - 1), 198);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(Swap, CircularDoublyLinkedListTest) {
|
|
||||||
CircularDoublyLinkedList<size_t> list2;
|
|
||||||
for (size_t i = 0; i < 5; i++) {
|
|
||||||
list2.insert(list2.length(), i + 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
list2.swap(list);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(list.size(), 5);
|
|
||||||
BOOST_CHECK_EQUAL(list2.size(), 10);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 5; i++) {
|
|
||||||
BOOST_CHECK_EQUAL(list.at(i), i + 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 10; i++) {
|
|
||||||
BOOST_CHECK_EQUAL(list2.at(i), i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(InsertToIndexLessThenSize, CircularDoublyLinkedListTest) {
|
|
||||||
list.insert(4, 456);
|
|
||||||
BOOST_CHECK_EQUAL(list.length(), 11);
|
|
||||||
BOOST_CHECK_EQUAL(list.at(4), 456);
|
|
||||||
BOOST_CHECK_EQUAL(list.at(5), 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(InsertToIndexEuqalSize, CircularDoublyLinkedListTest) {
|
|
||||||
list.insert(list.size(), 456);
|
|
||||||
BOOST_CHECK_EQUAL(list.length(), 11);
|
|
||||||
BOOST_CHECK_EQUAL(list.at(list.size() - 1), 456);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(CopyConstructor, CircularDoublyLinkedListTest) {
|
|
||||||
auto list2(list);
|
|
||||||
BOOST_CHECK_EQUAL(list2.size(), 10);
|
|
||||||
list[9] = 2; //测试是否为浅拷贝
|
|
||||||
BOOST_CHECK_EQUAL(list2[9], 9);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(MoveConstructor, CircularDoublyLinkedListTest) {
|
|
||||||
auto list2(std::move(list));
|
|
||||||
BOOST_CHECK_EQUAL(list.empty(), true);
|
|
||||||
BOOST_CHECK_EQUAL(list2.size(), 10);
|
|
||||||
BOOST_CHECK_EQUAL(list2[9], 9);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_CASE(Iterator, CircularDoublyLinkedListTest) {
|
|
||||||
size_t i = 0;
|
|
||||||
for (const auto &value : list) {
|
|
||||||
BOOST_CHECK_EQUAL(value, i++);
|
|
||||||
}
|
|
||||||
BOOST_CHECK_EQUAL(list.size(), i);
|
|
||||||
}
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
|
83
UnitTest/Universal/DateTimeTest.cpp
Normal file
83
UnitTest/Universal/DateTimeTest.cpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#include <BoostLog.h>
|
||||||
|
#include <DateTime.h>
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(DateTimeTest, *boost::unit_test::enabled())
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(BasicUse) {
|
||||||
|
std::time_t c_current = std::time(nullptr);
|
||||||
|
auto c_local = localtime(&c_current);
|
||||||
|
|
||||||
|
auto now = DateTime::currentDateTime();
|
||||||
|
BOOST_CHECK_EQUAL(now.year(), c_local->tm_year + 1900);
|
||||||
|
BOOST_CHECK_EQUAL(now.month(), c_local->tm_mon + 1);
|
||||||
|
BOOST_CHECK_EQUAL(now.day(), c_local->tm_mday);
|
||||||
|
BOOST_CHECK_EQUAL(now.hour(), c_local->tm_hour);
|
||||||
|
BOOST_CHECK_EQUAL(now.minute(), c_local->tm_min);
|
||||||
|
BOOST_CHECK_EQUAL(now.second(), c_local->tm_sec);
|
||||||
|
|
||||||
|
// std::cout << "now: " << DateTime::toString(std::chrono::system_clock::now()) << std::endl;
|
||||||
|
// std::cout << "now: " << DateTime::currentDateTime().toString() << std::endl;
|
||||||
|
|
||||||
|
auto day = DateTime::makeDateTime(2018, 8, 15, 13, 14, 59);
|
||||||
|
DateTime r(day);
|
||||||
|
BOOST_CHECK_EQUAL(r.week(), DateTime::Wednesday);
|
||||||
|
BOOST_CHECK_EQUAL(DateTime::toString(day), "2018-08-15 13:14:59");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(IsLeapYearTest) {
|
||||||
|
BOOST_TEST(DateTime::isLeapYear(2008));
|
||||||
|
BOOST_TEST(!DateTime::isLeapYear(2100));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(TomorrowTest) {
|
||||||
|
DateTime day(2018, 8, 15, 13, 14, 59);
|
||||||
|
auto t = day.tomorrow();
|
||||||
|
BOOST_CHECK_EQUAL(t.toString(), "2018-08-16 13:14:59");
|
||||||
|
|
||||||
|
day = DateTime(2018, 12, 31, 13, 14, 59);
|
||||||
|
t = day.tomorrow();
|
||||||
|
BOOST_CHECK_EQUAL(t.toString(), "2019-01-01 13:14:59");
|
||||||
|
|
||||||
|
day = DateTime(2020, 2, 28, 13, 14, 59);
|
||||||
|
t = day.tomorrow();
|
||||||
|
BOOST_CHECK_EQUAL(t.toString(), "2020-02-29 13:14:59");
|
||||||
|
|
||||||
|
day = DateTime(2021, 2, 28, 13, 14, 59);
|
||||||
|
t = day.tomorrow();
|
||||||
|
BOOST_CHECK_EQUAL(t.toString(), "2021-03-01 13:14:59");
|
||||||
|
|
||||||
|
day = DateTime(2021, 10, 25, 22, 31, 59);
|
||||||
|
t = day.tomorrow();
|
||||||
|
BOOST_CHECK_EQUAL(t.toString(), "2021-10-26 22:31:59");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(CurrentMSecsSinceEpoch) {
|
||||||
|
BOOST_CHECK_EQUAL(DateTime::currentMSecsSinceEpoch(),
|
||||||
|
std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now())
|
||||||
|
.time_since_epoch()
|
||||||
|
.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(ParseTimeString) {
|
||||||
|
auto [hour, minute, second] = DateTime::parseTime("12:14:15");
|
||||||
|
BOOST_CHECK_EQUAL(hour, 12);
|
||||||
|
BOOST_CHECK_EQUAL(minute, 14);
|
||||||
|
BOOST_CHECK_EQUAL(second, 15);
|
||||||
|
|
||||||
|
std::tie(hour, minute, second) = DateTime::parseTime("15:12");
|
||||||
|
BOOST_CHECK_EQUAL(hour, 15);
|
||||||
|
BOOST_CHECK_EQUAL(minute, 12);
|
||||||
|
BOOST_CHECK_EQUAL(second, 0);
|
||||||
|
|
||||||
|
std::tie(hour, minute, second) = DateTime::parseTime("00:09:07");
|
||||||
|
BOOST_CHECK_EQUAL(hour, 0);
|
||||||
|
BOOST_CHECK_EQUAL(minute, 9);
|
||||||
|
BOOST_CHECK_EQUAL(second, 7);
|
||||||
|
|
||||||
|
std::tie(hour, minute, second) = DateTime::parseTime("15:12");
|
||||||
|
BOOST_CHECK_EQUAL(hour, 15);
|
||||||
|
BOOST_CHECK_EQUAL(minute, 12);
|
||||||
|
BOOST_CHECK_EQUAL(second, 0);
|
||||||
|
}
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
187
UnitTest/Universal/MessageManagerTest.cpp
Normal file
187
UnitTest/Universal/MessageManagerTest.cpp
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
#include <BoostLog.h>
|
||||||
|
#include <FunctionTraits.h>
|
||||||
|
#include <MessageManager.h>
|
||||||
|
#include <boost/function_types/function_type.hpp>
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
static int test(int a, int b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
public:
|
||||||
|
int test(int a, int b) {
|
||||||
|
result = a + b + 3;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
int result{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(MessageManagerTest, *boost::unit_test::enabled())
|
||||||
|
// returned-function-return-type (* function-name (parameter-list) ) (function-to-return-parameter-list)
|
||||||
|
BOOST_AUTO_TEST_CASE(FunctionTraitsNormalFunctionTest) {
|
||||||
|
using namespace std::placeholders;
|
||||||
|
MessageManager m;
|
||||||
|
|
||||||
|
m.registerTopic("123", [](int a) -> void { a = a + 102; });
|
||||||
|
BOOST_CHECK_EQUAL(m.topicCount<int(int)>("123"), 1);
|
||||||
|
|
||||||
|
Test t;
|
||||||
|
m.registerTopic("123", [&t](int a, int b) { return t.test(a, b); });
|
||||||
|
BOOST_CHECK_EQUAL(m.topicCount<int(int, int)>("123"), 1);
|
||||||
|
|
||||||
|
m.registerTopic("123", std::bind(&Test::test, &t, _1, _2));
|
||||||
|
BOOST_CHECK_EQUAL(m.topicCount<int(int, int)>("123"), 2);
|
||||||
|
|
||||||
|
m.registerTopic("123", &test);
|
||||||
|
BOOST_CHECK_EQUAL(m.topicCount<int(int, int)>("123"), 3);
|
||||||
|
|
||||||
|
m.removeTopic<int(int, int)>("123");
|
||||||
|
BOOST_CHECK_EQUAL(m.topicCount<int(int, int)>("123"), 0);
|
||||||
|
|
||||||
|
m.registerTopic("123", [](const std::string &title) {});
|
||||||
|
|
||||||
|
m.registerTopic(
|
||||||
|
"123", [](int type, const std::string &title, const std::string &message, const std::function<void()> &yes) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(SyncMessage) {
|
||||||
|
using namespace std::placeholders;
|
||||||
|
MessageManager manager;
|
||||||
|
|
||||||
|
int result1 = 0;
|
||||||
|
std::thread::id id;
|
||||||
|
manager.registerTopic("123", [&result1](int a) {
|
||||||
|
result1 += a;
|
||||||
|
return a + 102;
|
||||||
|
});
|
||||||
|
int result2 = 0;
|
||||||
|
manager.registerTopic("123", [&result2](const int &a) {
|
||||||
|
result2 = a + 102;
|
||||||
|
return result2;
|
||||||
|
});
|
||||||
|
manager.sendMessage("123", 5);
|
||||||
|
BOOST_CHECK_EQUAL(result1, 5);
|
||||||
|
BOOST_CHECK_EQUAL(result2, 107);
|
||||||
|
|
||||||
|
int result3 = 0;
|
||||||
|
manager.registerTopic("123", [&result3](int a, int b) {
|
||||||
|
result3 = a + b;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
Test t;
|
||||||
|
manager.registerTopic("123", std::bind(&Test::test, &t, _1, _2));
|
||||||
|
manager.sendMessage("123", 12, 13);
|
||||||
|
BOOST_CHECK_EQUAL(result3, 25);
|
||||||
|
BOOST_CHECK_EQUAL(t.result, 28);
|
||||||
|
|
||||||
|
int result4 = 0;
|
||||||
|
manager.registerTopic("123", [&result4]() {
|
||||||
|
result4 = 102;
|
||||||
|
return result4;
|
||||||
|
});
|
||||||
|
manager.sendMessage("123");
|
||||||
|
BOOST_CHECK_EQUAL(result4, 102);
|
||||||
|
|
||||||
|
constexpr auto magic = "MagicString";
|
||||||
|
std::string result5;
|
||||||
|
manager.registerTopic("test", [&result5](const std::string &text) { result5 = text; });
|
||||||
|
// manager.sendMessage<std::string>("test", magic); // 编译不通过
|
||||||
|
|
||||||
|
// manager.sendMessage("test", magic); // const char*无法匹配到std::string
|
||||||
|
// BOOST_CHECK_EQUAL(result5, magic);
|
||||||
|
// result5.clear();
|
||||||
|
|
||||||
|
manager.sendMessage<void(const std::string &), std::string>("test", magic);
|
||||||
|
BOOST_CHECK_EQUAL(result5, magic);
|
||||||
|
result5.clear();
|
||||||
|
|
||||||
|
manager.sendMessage<void(const std::string &)>("test", std::string(magic));
|
||||||
|
BOOST_CHECK_EQUAL(result5, magic);
|
||||||
|
result5.clear();
|
||||||
|
|
||||||
|
manager.sendMessage<void(std::string)>("test", magic);
|
||||||
|
BOOST_CHECK_EQUAL(result5, magic);
|
||||||
|
result5.clear();
|
||||||
|
|
||||||
|
manager.sendMessage("test", std::string(magic));
|
||||||
|
BOOST_CHECK_EQUAL(result5, magic);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(SyncMessageWithVoidArg) {
|
||||||
|
MessageManager manager;
|
||||||
|
constexpr auto Topic = MessageManager::Message<>("test1");
|
||||||
|
int result = 0;
|
||||||
|
manager.registerTopic("test1", [&result]() -> void { result = 250; });
|
||||||
|
manager.sendMessage("test1");
|
||||||
|
BOOST_CHECK_EQUAL(result, 250);
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
manager.sendMessage(Topic);
|
||||||
|
BOOST_CHECK_EQUAL(result, 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(AsyncMessage) {
|
||||||
|
int result = 0;
|
||||||
|
std::thread::id id;
|
||||||
|
auto test1 = [&result, &id](int a, int b) -> void {
|
||||||
|
result = a + b;
|
||||||
|
id = std::this_thread::get_id();
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageManager manager;
|
||||||
|
manager.registerTopic("test1", test1);
|
||||||
|
manager.sendAsyncMessage("test1", 2, 6);
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||||
|
BOOST_CHECK_EQUAL(result, 8);
|
||||||
|
BOOST_CHECK_NE(std::this_thread::get_id(), id);
|
||||||
|
|
||||||
|
constexpr auto magic = "MagicString";
|
||||||
|
manager.registerTopic("StringCompare", [magic](const std::string &text) { BOOST_CHECK_EQUAL(text, magic); });
|
||||||
|
{
|
||||||
|
std::string string(magic);
|
||||||
|
manager.sendAsyncMessage("StringCompare", string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(AsyncMessageImplictConversion) {
|
||||||
|
float result1 = 0;
|
||||||
|
auto test1 = [&result1](int a, int b) -> void { result1 = a + b; };
|
||||||
|
|
||||||
|
float result2 = 0;
|
||||||
|
auto test2 = [&result2](int a, int b) -> void { result2 = a + b; };
|
||||||
|
|
||||||
|
MessageManager manager;
|
||||||
|
|
||||||
|
manager.registerTopic("test1", test1);
|
||||||
|
manager.registerTopic("test2", test2);
|
||||||
|
manager.sendAsyncMessage<decltype(test1)>("test1", 2.6, 6);
|
||||||
|
manager.sendAsyncMessage("test2", (int)3.6, 6);
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||||
|
BOOST_CHECK_EQUAL(result1, 8);
|
||||||
|
BOOST_CHECK_EQUAL(result2, 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(DefineTopicUseMessage) {
|
||||||
|
constexpr auto TestTopic1 = MessageManager::Message<int, int>("TestTopic1");
|
||||||
|
int result1 = 0;
|
||||||
|
auto test1 = [&result1](int a, int b) -> void { result1 = a + b; };
|
||||||
|
MessageManager manager;
|
||||||
|
manager.registerTopic(TestTopic1, test1);
|
||||||
|
manager.sendMessage(TestTopic1, 2, 3);
|
||||||
|
BOOST_CHECK_EQUAL(result1, 5);
|
||||||
|
|
||||||
|
std::string result2;
|
||||||
|
constexpr auto TestTopic2 = MessageManager::Message<const std::string &>("TestTopic2");
|
||||||
|
auto test2 = [&result2](const std::string &text) -> void { result2 = text; };
|
||||||
|
manager.registerTopic(TestTopic2, test2);
|
||||||
|
manager.sendMessage(TestTopic2, std::string("hello"));
|
||||||
|
std::string message("hello");
|
||||||
|
// manager.sendMessage(TestTopic2, message);
|
||||||
|
// manager.sendMessage(TestTopic2, "hello");
|
||||||
|
BOOST_CHECK_EQUAL(result2, "hello");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
39
UnitTest/Universal/SingletonTest.cpp
Normal file
39
UnitTest/Universal/SingletonTest.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include "Singleton.h"
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
public:
|
||||||
|
size_t index;
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(LocalInstance) {
|
||||||
|
auto test = Amass::Singleton<Test>::instance();
|
||||||
|
BOOST_TEST(!test);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto local = Amass::Singleton<Test>::instance<Amass::Construct>();
|
||||||
|
BOOST_TEST(local);
|
||||||
|
|
||||||
|
auto refer = Amass::Singleton<Test>::instance();
|
||||||
|
BOOST_TEST(refer);
|
||||||
|
}
|
||||||
|
|
||||||
|
test = Amass::Singleton<Test>::instance();
|
||||||
|
BOOST_TEST(!test);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(GlobalInstance) {
|
||||||
|
auto test = Amass::Singleton<Test, Amass::GlobalInstance>::instance();
|
||||||
|
BOOST_TEST(test);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto local = Amass::Singleton<Test, Amass::GlobalInstance>::instance();
|
||||||
|
BOOST_TEST(local);
|
||||||
|
|
||||||
|
auto refer = Amass::Singleton<Test, Amass::GlobalInstance>::instance();
|
||||||
|
BOOST_TEST(refer);
|
||||||
|
}
|
||||||
|
|
||||||
|
test = Amass::Singleton<Test, Amass::GlobalInstance>::instance();
|
||||||
|
BOOST_TEST(test);
|
||||||
|
}
|
90
Universal/ApplicationSettings.h
Normal file
90
Universal/ApplicationSettings.h
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#ifndef __APPLICATIONSETTINGS_H__
|
||||||
|
#define __APPLICATIONSETTINGS_H__
|
||||||
|
|
||||||
|
#include "BoostLog.h"
|
||||||
|
#include <boost/asio/steady_timer.hpp>
|
||||||
|
#include <boost/preprocessor/seq/for_each.hpp>
|
||||||
|
#include <boost/preprocessor/tuple/to_seq.hpp>
|
||||||
|
#include <boost/property_tree/ini_parser.hpp>
|
||||||
|
#include <boost/property_tree/ptree.hpp>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
template <typename Child>
|
||||||
|
class ApplicationSettings {
|
||||||
|
#define BUILD_SETTING_FIELD(Category, Type, Name, DefaultValue) \
|
||||||
|
inline void set##Name(const Type &value) { \
|
||||||
|
std::lock_guard locker(m_mutex); \
|
||||||
|
m_ptree.put(#Category "." #Name, value); \
|
||||||
|
m_needSave = true; \
|
||||||
|
} \
|
||||||
|
inline Type get##Name() const { \
|
||||||
|
std::lock_guard locker(m_mutex); \
|
||||||
|
return m_ptree.get<Type>(#Category "." #Name, DefaultValue); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BUILD_STATUS(Type, Name, DefaultValue) BUILD_SETTING_FIELD(Status, Type, Name, DefaultValue)
|
||||||
|
#define BUILD_SETTING(Type, Name, DefaultValue) BUILD_SETTING_FIELD(Settings, Type, Name, DefaultValue)
|
||||||
|
#define INITIALIZE_FIELD(Name) set##Name(get##Name());
|
||||||
|
|
||||||
|
#define MACRO(r, data, elem) INITIALIZE_FIELD(elem)
|
||||||
|
|
||||||
|
#define INITIALIZE_FIELDS(...) \
|
||||||
|
inline void initializeFileds() final { \
|
||||||
|
BOOST_PP_SEQ_FOR_EACH(MACRO, _, BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))) \
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ApplicationSettings(const std::string &path) : m_path(path) {
|
||||||
|
if (std::filesystem::exists(path)) {
|
||||||
|
try {
|
||||||
|
boost::property_tree::read_ini(path, m_ptree);
|
||||||
|
} catch (const boost::property_tree::ini_parser_error &e) {
|
||||||
|
LOG(error) << e.what();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
static_cast<Child *>(this)->initializeFileds();
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void startCheckInterval(boost::asio::io_context &ioContext, uint32_t seconds) {
|
||||||
|
m_timer = std::make_unique<boost::asio::steady_timer>(ioContext);
|
||||||
|
m_interval = seconds;
|
||||||
|
run();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void save() {
|
||||||
|
if (!m_needSave) return;
|
||||||
|
try {
|
||||||
|
std::lock_guard locker(m_mutex);
|
||||||
|
boost::property_tree::write_ini(m_path, m_ptree);
|
||||||
|
m_needSave = false;
|
||||||
|
} catch (const boost::property_tree::ini_parser_error &e) {
|
||||||
|
LOG(error) << e.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void run() {
|
||||||
|
m_timer->expires_after(std::chrono::seconds(m_interval));
|
||||||
|
m_timer->async_wait([this](const boost::system::error_code &error) {
|
||||||
|
if (error) {
|
||||||
|
LOG(error) << error.message();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
save();
|
||||||
|
run();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
virtual void initializeFileds() {
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::property_tree::ptree m_ptree;
|
||||||
|
bool m_needSave = false;
|
||||||
|
mutable std::mutex m_mutex;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_path;
|
||||||
|
std::unique_ptr<boost::asio::steady_timer> m_timer;
|
||||||
|
uint32_t m_interval;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __APPLICATIONSETTINGS_H__
|
@ -7,16 +7,11 @@
|
|||||||
#include "AndroidBoostLog.h"
|
#include "AndroidBoostLog.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BOOST_LOG_GLOBAL_LOGGER_INIT(location_logger, LocationLogger<boost::log::trivial::severity_level>) {
|
|
||||||
LocationLogger<boost::log::trivial::severity_level> lg;
|
|
||||||
auto consoleSink = boost::log::add_console_log();
|
|
||||||
consoleSink->set_formatter(&boost::log::defaultFormatter);
|
|
||||||
boost::log::add_common_attributes();
|
|
||||||
return lg;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace log {
|
namespace log {
|
||||||
|
static bool enableConsole = true;
|
||||||
|
static decltype(boost::log::add_console_log()) console;
|
||||||
|
|
||||||
void initialize(const std::string &filename, const std::string &target, boost::log::trivial::severity_level filter) {
|
void initialize(const std::string &filename, const std::string &target, boost::log::trivial::severity_level filter) {
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
using namespace boost::log;
|
using namespace boost::log;
|
||||||
@ -67,5 +62,23 @@ void defaultFormatter(const boost::log::record_view &record, boost::log::formatt
|
|||||||
ostream << record[expressions::smessage];
|
ostream << record[expressions::smessage];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void removeConsoleLog() {
|
||||||
|
if (console) {
|
||||||
|
boost::log::core::get()->remove_sink(console);
|
||||||
|
console.reset();
|
||||||
|
}
|
||||||
|
enableConsole = false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace log
|
} // namespace log
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
|
||||||
|
BOOST_LOG_GLOBAL_LOGGER_INIT(location_logger, LocationLogger<boost::log::trivial::severity_level>) {
|
||||||
|
LocationLogger<boost::log::trivial::severity_level> lg;
|
||||||
|
boost::log::add_common_attributes();
|
||||||
|
if (boost::log::enableConsole) {
|
||||||
|
boost::log::console = boost::log::add_console_log();
|
||||||
|
boost::log::console->set_formatter(&boost::log::defaultFormatter);
|
||||||
|
}
|
||||||
|
return lg;
|
||||||
|
}
|
||||||
|
@ -66,16 +66,19 @@ void initialize(const std::string &filename = "logs/app", const std::string &tar
|
|||||||
trivial::severity_level filter = static_cast<trivial::severity_level>(LOG_FILTER_LEVEL));
|
trivial::severity_level filter = static_cast<trivial::severity_level>(LOG_FILTER_LEVEL));
|
||||||
|
|
||||||
void defaultFormatter(boost::log::record_view const &record, boost::log::formatting_ostream &ostream);
|
void defaultFormatter(boost::log::record_view const &record, boost::log::formatting_ostream &ostream);
|
||||||
|
void removeConsoleLog();
|
||||||
} // namespace log
|
} // namespace log
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
|
||||||
namespace AmassKeywords {
|
namespace AmassKeywords {
|
||||||
|
|
||||||
BOOST_PARAMETER_KEYWORD(FilenameNS, FilenameTag)
|
BOOST_PARAMETER_KEYWORD(FilenameNS, FilenameTag)
|
||||||
|
BOOST_PARAMETER_KEYWORD(FunctionNS, FunctionTag)
|
||||||
BOOST_PARAMETER_KEYWORD(LineNS, LineTag)
|
BOOST_PARAMETER_KEYWORD(LineNS, LineTag)
|
||||||
BOOST_PARAMETER_KEYWORD(CategoryNS, CategoryTag)
|
BOOST_PARAMETER_KEYWORD(CategoryNS, CategoryTag)
|
||||||
|
|
||||||
BOOST_LOG_ATTRIBUTE_KEYWORD(filename, "Filename", std::string)
|
BOOST_LOG_ATTRIBUTE_KEYWORD(filename, "Filename", std::string)
|
||||||
|
BOOST_LOG_ATTRIBUTE_KEYWORD(function, "Function", std::string)
|
||||||
BOOST_LOG_ATTRIBUTE_KEYWORD(line, "Line", size_t)
|
BOOST_LOG_ATTRIBUTE_KEYWORD(line, "Line", size_t)
|
||||||
BOOST_LOG_ATTRIBUTE_KEYWORD(category, "Category", std::string)
|
BOOST_LOG_ATTRIBUTE_KEYWORD(category, "Category", std::string)
|
||||||
|
|
||||||
@ -138,6 +141,28 @@ protected:
|
|||||||
|
|
||||||
struct FilenameTagger : public boost::mpl::quote1<FilenameTaggerFeature> {};
|
struct FilenameTagger : public boost::mpl::quote1<FilenameTaggerFeature> {};
|
||||||
|
|
||||||
|
template <typename BaseT>
|
||||||
|
class FunctionTaggerFeature : public BaseT {
|
||||||
|
public:
|
||||||
|
typedef typename BaseT::char_type char_type;
|
||||||
|
typedef typename BaseT::threading_model threading_model;
|
||||||
|
FunctionTaggerFeature() = default;
|
||||||
|
FunctionTaggerFeature(const FunctionTaggerFeature &obj);
|
||||||
|
|
||||||
|
template <typename ArgsT>
|
||||||
|
FunctionTaggerFeature(const ArgsT &args);
|
||||||
|
|
||||||
|
typedef typename boost::log::strictest_lock<boost::lock_guard<threading_model>, typename BaseT::open_record_lock,
|
||||||
|
typename BaseT::add_attribute_lock,
|
||||||
|
typename BaseT::remove_attribute_lock>::type open_record_lock;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
template <typename ArgsT>
|
||||||
|
boost::log::record open_record_unlocked(const ArgsT &args);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FunctionTagger : public boost::mpl::quote1<FunctionTaggerFeature> {};
|
||||||
|
|
||||||
template <typename BaseT>
|
template <typename BaseT>
|
||||||
class LineTaggerFeature : public BaseT {
|
class LineTaggerFeature : public BaseT {
|
||||||
public:
|
public:
|
||||||
@ -164,8 +189,8 @@ template <typename LevelT = int>
|
|||||||
class LocationLogger
|
class LocationLogger
|
||||||
: public boost::log::sources::basic_composite_logger<
|
: public boost::log::sources::basic_composite_logger<
|
||||||
char, LocationLogger<LevelT>, boost::log::sources::multi_thread_model<boost::log::aux::light_rw_mutex>,
|
char, LocationLogger<LevelT>, boost::log::sources::multi_thread_model<boost::log::aux::light_rw_mutex>,
|
||||||
boost::log::sources::features<boost::log::sources::severity<LevelT>, FilenameTagger, LineTagger,
|
boost::log::sources::features<boost::log::sources::severity<LevelT>, FilenameTagger, FunctionTagger,
|
||||||
CategoryTagger>> {
|
LineTagger, CategoryTagger>> {
|
||||||
typedef typename LocationLogger::logger_base base_type;
|
typedef typename LocationLogger::logger_base base_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -180,12 +205,14 @@ BOOST_LOG_GLOBAL_LOGGER(location_logger, LocationLogger<boost::log::trivial::sev
|
|||||||
BOOST_LOG_STREAM_WITH_PARAMS(::location_logger::get(),\
|
BOOST_LOG_STREAM_WITH_PARAMS(::location_logger::get(),\
|
||||||
(::boost::log::keywords::severity = ::boost::log::trivial::lvl) \
|
(::boost::log::keywords::severity = ::boost::log::trivial::lvl) \
|
||||||
(AmassKeywords::FilenameTag = (AmassKeywords::fileName(__FILE__))) \
|
(AmassKeywords::FilenameTag = (AmassKeywords::fileName(__FILE__))) \
|
||||||
|
(AmassKeywords::FunctionTag = __func__) \
|
||||||
(AmassKeywords::LineTag = __LINE__))
|
(AmassKeywords::LineTag = __LINE__))
|
||||||
|
|
||||||
#define LOG_CAT( lvl, cat) \
|
#define LOG_CAT( lvl, cat) \
|
||||||
BOOST_LOG_STREAM_WITH_PARAMS(::location_logger::get(),\
|
BOOST_LOG_STREAM_WITH_PARAMS(::location_logger::get(),\
|
||||||
(::boost::log::keywords::severity = ::boost::log::trivial::lvl) \
|
(::boost::log::keywords::severity = ::boost::log::trivial::lvl) \
|
||||||
(AmassKeywords::FilenameTag = (AmassKeywords::fileName(__FILE__))) \
|
(AmassKeywords::FilenameTag = (AmassKeywords::fileName(__FILE__))) \
|
||||||
|
(AmassKeywords::FunctionTag = __func__) \
|
||||||
(AmassKeywords::LineTag = __LINE__) \
|
(AmassKeywords::LineTag = __LINE__) \
|
||||||
(AmassKeywords::CategoryTag = #cat))
|
(AmassKeywords::CategoryTag = #cat))
|
||||||
|
|
||||||
|
@ -125,6 +125,36 @@ boost::log::record FilenameTaggerFeature<BaseT>::open_record_unlocked(const Args
|
|||||||
return BaseT::open_record_unlocked(args);
|
return BaseT::open_record_unlocked(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename BaseT>
|
||||||
|
FunctionTaggerFeature<BaseT>::FunctionTaggerFeature(const FunctionTaggerFeature &obj)
|
||||||
|
: BaseT(static_cast<const BaseT &>(obj)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename BaseT>
|
||||||
|
template <typename ArgsT>
|
||||||
|
FunctionTaggerFeature<BaseT>::FunctionTaggerFeature(const ArgsT &args) : BaseT(args) {}
|
||||||
|
|
||||||
|
template <typename BaseT>
|
||||||
|
template <typename ArgsT>
|
||||||
|
boost::log::record FunctionTaggerFeature<BaseT>::open_record_unlocked(const ArgsT &args) {
|
||||||
|
std::string tag_value = args[AmassKeywords::FunctionTag | std::string()];
|
||||||
|
boost::log::attribute_set &attrs = BaseT::attributes();
|
||||||
|
boost::log::attribute_set::iterator tag = attrs.end();
|
||||||
|
if (!tag_value.empty()) {
|
||||||
|
// Add the tag as a new attribute
|
||||||
|
std::pair<boost::log::attribute_set::iterator, bool> res =
|
||||||
|
BaseT::add_attribute_unlocked("Function", boost::log::attributes::constant<std::string>(tag_value));
|
||||||
|
if (res.second) tag = res.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_SCOPE_EXIT_TPL((&tag)(&attrs)) {
|
||||||
|
if (tag != attrs.end()) attrs.erase(tag);
|
||||||
|
}
|
||||||
|
BOOST_SCOPE_EXIT_END
|
||||||
|
|
||||||
|
return BaseT::open_record_unlocked(args);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename BaseT>
|
template <typename BaseT>
|
||||||
template <typename ArgsT>
|
template <typename ArgsT>
|
||||||
LineTaggerFeature<BaseT>::LineTaggerFeature(const ArgsT &args) : BaseT(args) {}
|
LineTaggerFeature<BaseT>::LineTaggerFeature(const ArgsT &args) : BaseT(args) {}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
find_package(Boost REQUIRED COMPONENTS log log_setup program_options)
|
find_package(Boost REQUIRED COMPONENTS log log_setup program_options)
|
||||||
|
|
||||||
add_library(Universal
|
add_library(Universal
|
||||||
|
ApplicationSettings.h
|
||||||
BoostLog.h BoostLog.inl BoostLog.cpp
|
BoostLog.h BoostLog.inl BoostLog.cpp
|
||||||
BufferUtility.h BufferUtility.cpp
|
BufferUtility.h BufferUtility.cpp
|
||||||
DateTime.h DateTime.cpp
|
DateTime.h DateTime.cpp
|
||||||
@ -14,6 +15,10 @@ add_library(Universal
|
|||||||
StringUtility.h StringUtility.cpp
|
StringUtility.h StringUtility.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set_property(TARGET Universal
|
||||||
|
PROPERTY POSITION_INDEPENDENT_CODE ON
|
||||||
|
)
|
||||||
|
|
||||||
if(CMAKE_VERSION VERSION_LESS 3.20)
|
if(CMAKE_VERSION VERSION_LESS 3.20)
|
||||||
get_filename_component(KYLIN_CORE_INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
|
get_filename_component(KYLIN_CORE_INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
|
||||||
if(NOT Boost_USE_STATIC_LIBS)
|
if(NOT Boost_USE_STATIC_LIBS)
|
||||||
|
@ -36,6 +36,11 @@ public:
|
|||||||
std::chrono::time_point<std::chrono::system_clock> operator()();
|
std::chrono::time_point<std::chrono::system_clock> operator()();
|
||||||
std::string toString(const std::string_view &format = "%F %T") const;
|
std::string toString(const std::string_view &format = "%F %T") const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 2023-10-12 12:10:23 then return 2023-10-13 12:10:23
|
||||||
|
*
|
||||||
|
* @return DateTime
|
||||||
|
*/
|
||||||
DateTime tomorrow();
|
DateTime tomorrow();
|
||||||
|
|
||||||
// Returns the number of milliseconds since 1970-01-01T00:00:00 Universal Coordinated Time. This number is like the
|
// Returns the number of milliseconds since 1970-01-01T00:00:00 Universal Coordinated Time. This number is like the
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "IoContext.h"
|
#include "IoContext.h"
|
||||||
#include <boost/asio/executor_work_guard.hpp>
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
#include <boost/scope_exit.hpp>
|
#include <boost/scope_exit.hpp>
|
||||||
|
#include <boost/stacktrace.hpp>
|
||||||
|
|
||||||
IoContext::~IoContext() {
|
IoContext::~IoContext() {
|
||||||
m_ioContext->stop();
|
m_ioContext->stop();
|
||||||
@ -23,6 +24,7 @@ void IoContext::runIoContext() {
|
|||||||
} catch (const boost::exception &e) {
|
} catch (const boost::exception &e) {
|
||||||
LOG(error) << boost::diagnostic_information(e);
|
LOG(error) << boost::diagnostic_information(e);
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
LOG(error) << e.what();
|
boost::stacktrace::stacktrace trace = boost::stacktrace::stacktrace::from_current_exception();
|
||||||
|
LOG(error) << e.what() << ", trace:\n" << trace;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#include "StringUtility.h"
|
#include "StringUtility.h"
|
||||||
#include "BoostLog.h"
|
#include "BoostLog.h"
|
||||||
#include <algorithm>
|
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <Windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Amass {
|
namespace Amass {
|
||||||
|
|
||||||
@ -54,6 +56,18 @@ std::wstring stringToWString(const std::string &string) {
|
|||||||
return converter.from_bytes(string);
|
return converter.from_bytes(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string wstringToString(const std::wstring &string) {
|
||||||
|
#ifdef WIN32
|
||||||
|
int sizeNeeded = WideCharToMultiByte(CP_UTF8, 0, string.c_str(), string.size(), NULL, 0, NULL, NULL);
|
||||||
|
std::string ret(sizeNeeded, 0);
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, string.c_str(), string.size(), &ret[0], sizeNeeded, NULL, NULL);
|
||||||
|
#else
|
||||||
|
std::string ret;
|
||||||
|
assert(false && "not implement.");
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool equal(std::string_view lhs, std::string_view rhs, bool caseSensitivity) {
|
bool equal(std::string_view lhs, std::string_view rhs, bool caseSensitivity) {
|
||||||
auto n = lhs.size();
|
auto n = lhs.size();
|
||||||
if (rhs.size() != n) return false;
|
if (rhs.size() != n) return false;
|
||||||
@ -82,5 +96,25 @@ slow:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string UTF8ToGBK(const std::string &utf8Str) {
|
||||||
|
int wideStrLen = MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, NULL, 0);
|
||||||
|
if (wideStrLen == 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring wideStr(wideStrLen, 0);
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, &wideStr[0], wideStrLen);
|
||||||
|
|
||||||
|
int gbkStrLen = WideCharToMultiByte(CP_ACP, 0, wideStr.c_str(), -1, NULL, 0, NULL, NULL);
|
||||||
|
if (gbkStrLen == 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string gbkStr(gbkStrLen, 0);
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, wideStr.c_str(), -1, &gbkStr[0], gbkStrLen, NULL, NULL);
|
||||||
|
|
||||||
|
return gbkStr;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace StringUtility
|
} // namespace StringUtility
|
||||||
} // namespace Amass
|
} // namespace Amass
|
||||||
|
@ -60,6 +60,8 @@ size_t utf8Length(const std::string &text);
|
|||||||
std::string_view utf8At(const std::string &text, size_t index);
|
std::string_view utf8At(const std::string &text, size_t index);
|
||||||
size_t utf8CharacterByteSize(const char *character);
|
size_t utf8CharacterByteSize(const char *character);
|
||||||
std::wstring stringToWString(const std::string &string);
|
std::wstring stringToWString(const std::string &string);
|
||||||
|
std::string wstringToString(const std::wstring &string);
|
||||||
|
std::string UTF8ToGBK(const std::string &utf8Str);
|
||||||
|
|
||||||
} // namespace StringUtility
|
} // namespace StringUtility
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
base_path=$(pwd)
|
base_path=$(pwd)
|
||||||
qt_prefix_path="/opt/Qt/6.6.1/gcc_64"
|
qt_prefix_path="/opt/Qt/6.6.2/gcc_64"
|
||||||
libraries_root="/opt/Libraries"
|
libraries_root="/opt/Libraries"
|
||||||
if [ $base_path==/home/* ]; then
|
if [ $base_path == /home/* ]; then
|
||||||
build_path=${base_path}/build
|
build_path=${base_path}/build
|
||||||
else
|
else
|
||||||
build_path=/tmp/build
|
build_path=/tmp/build
|
||||||
@ -35,7 +35,7 @@ elif [ -d "/opt/Qt/5.15.2/gcc_64" ]; then
|
|||||||
-DQt5Svg_DIR=${qt_prefix_path}/lib/cmake/Qt5Svg "
|
-DQt5Svg_DIR=${qt_prefix_path}/lib/cmake/Qt5Svg "
|
||||||
else
|
else
|
||||||
cmake_qt_parameters=""
|
cmake_qt_parameters=""
|
||||||
echo "please install qt6.6.1 or qt5.15.2 ..."
|
echo "please install qt6.6.2 or qt5.15.2 ..."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
function cmake_scan() {
|
function cmake_scan() {
|
||||||
@ -48,7 +48,7 @@ function cmake_scan() {
|
|||||||
-B ${build_path} \
|
-B ${build_path} \
|
||||||
-DCMAKE_BUILD_TYPE=Debug \
|
-DCMAKE_BUILD_TYPE=Debug \
|
||||||
-DUNIT_TEST=ON \
|
-DUNIT_TEST=ON \
|
||||||
-DBOOST_ROOT=${libraries_root}/boost_1_84_0 \
|
-DBOOST_ROOT=${libraries_root}/boost_1_85_0 \
|
||||||
-DZeroMQ_ROOT=${libraries_root}/zeromq-4.3.4_debug \
|
-DZeroMQ_ROOT=${libraries_root}/zeromq-4.3.4_debug \
|
||||||
${cmake_qt_parameters}
|
${cmake_qt_parameters}
|
||||||
}
|
}
|
||||||
@ -66,7 +66,7 @@ function build() {
|
|||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
build/UnitTest/UnitTest
|
$build_path/UnitTest/UnitTest
|
||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
|
Loading…
Reference in New Issue
Block a user