mirror of
https://gitee.com/zyjblog/oatpp.git
synced 2024-12-22 22:16:37 +08:00
commit
06190194ca
@ -40,8 +40,6 @@ add_library(oatpp
|
||||
oatpp/core/collection/LinkedList.hpp
|
||||
oatpp/core/collection/ListMap.cpp
|
||||
oatpp/core/collection/ListMap.hpp
|
||||
oatpp/core/concurrency/Runnable.cpp
|
||||
oatpp/core/concurrency/Runnable.hpp
|
||||
oatpp/core/concurrency/SpinLock.cpp
|
||||
oatpp/core/concurrency/SpinLock.hpp
|
||||
oatpp/core/concurrency/Thread.cpp
|
||||
|
@ -25,7 +25,22 @@
|
||||
#include "Checker.hpp"
|
||||
|
||||
namespace oatpp { namespace test {
|
||||
|
||||
|
||||
PerformanceChecker::PerformanceChecker(const char* tag)
|
||||
: m_tag(tag)
|
||||
, m_ticks(oatpp::base::Environment::getMicroTickCount())
|
||||
{}
|
||||
|
||||
PerformanceChecker::~PerformanceChecker(){
|
||||
v_int64 elapsedTicks = oatpp::base::Environment::getMicroTickCount() - m_ticks;
|
||||
OATPP_LOGD(m_tag, "%d(micro)", elapsedTicks);
|
||||
}
|
||||
|
||||
v_int64 PerformanceChecker::getElapsedTicks(){
|
||||
return oatpp::base::Environment::getMicroTickCount() - m_ticks;
|
||||
}
|
||||
|
||||
|
||||
ThreadLocalObjectsChecker::ThreadLocalObjectsChecker(const char* tag)
|
||||
: m_tag(tag)
|
||||
, m_objectsCount(oatpp::base::Environment::getThreadLocalObjectsCount())
|
||||
|
@ -28,28 +28,40 @@
|
||||
#include "oatpp/core/base/Environment.hpp"
|
||||
|
||||
namespace oatpp { namespace test {
|
||||
|
||||
|
||||
/**
|
||||
* Helper class to check performance of code block.
|
||||
*/
|
||||
class PerformanceChecker {
|
||||
private:
|
||||
const char* m_tag;
|
||||
v_int64 m_ticks;
|
||||
public:
|
||||
PerformanceChecker(const char* tag)
|
||||
: m_tag(tag)
|
||||
, m_ticks(oatpp::base::Environment::getMicroTickCount())
|
||||
{}
|
||||
|
||||
~PerformanceChecker(){
|
||||
v_int64 elapsedTicks = oatpp::base::Environment::getMicroTickCount() - m_ticks;
|
||||
OATPP_LOGD(m_tag, "%d(micro)", elapsedTicks);
|
||||
}
|
||||
|
||||
v_int64 getElapsedTicks(){
|
||||
return oatpp::base::Environment::getMicroTickCount() - m_ticks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param tag - log tag.
|
||||
*/
|
||||
PerformanceChecker(const char* tag);
|
||||
|
||||
/**
|
||||
* Non virtual destructor.
|
||||
* Will print time elapsed ticks on destruction.
|
||||
*/
|
||||
~PerformanceChecker();
|
||||
|
||||
/**
|
||||
* Get elapsed time from checker creation.
|
||||
* @return - ticks in microseconds.
|
||||
*/
|
||||
v_int64 getElapsedTicks();
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper class to check block of code on memory leaks.
|
||||
* Checks &id:oatpp::base::Countable; objects, and objects allocated on memory pools.
|
||||
*/
|
||||
class ThreadLocalObjectsChecker {
|
||||
private:
|
||||
class MemoryPoolData {
|
||||
@ -63,7 +75,17 @@ private:
|
||||
v_counter m_objectsCount;
|
||||
v_counter m_objectsCreated;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param tag - log tag.
|
||||
*/
|
||||
ThreadLocalObjectsChecker(const char* tag);
|
||||
|
||||
/**
|
||||
* Non virtual destructor.
|
||||
* Will halt program execution if memory leaks detected.
|
||||
*/
|
||||
~ThreadLocalObjectsChecker();
|
||||
};
|
||||
|
||||
|
@ -62,6 +62,9 @@ void UnitTest::run(v_int32 times) {
|
||||
OATPP_LOGD("Pool", "name: '%s' [%d(objs)]", pool->getName().c_str(), pool->getObjectsCount());
|
||||
it ++;
|
||||
}
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,27 +28,51 @@
|
||||
#include "oatpp/core/base/Environment.hpp"
|
||||
|
||||
namespace oatpp { namespace test {
|
||||
|
||||
|
||||
/**
|
||||
* Base class for unit tests.
|
||||
*/
|
||||
class UnitTest{
|
||||
protected:
|
||||
const char* const TAG;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param testTAG - tag used for logs.
|
||||
*/
|
||||
UnitTest(const char* testTAG)
|
||||
: TAG(testTAG)
|
||||
{}
|
||||
|
||||
virtual ~UnitTest(){
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default virtual destructor.
|
||||
*/
|
||||
virtual ~UnitTest() = default;
|
||||
|
||||
/**
|
||||
* Run this test repeatedly for specified number of times.
|
||||
* @param times - number of times to run this test.
|
||||
*/
|
||||
void run(v_int32 times);
|
||||
|
||||
/**
|
||||
* Run this test.
|
||||
*/
|
||||
void run(){
|
||||
run(1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Override this method. It should contain test logic.
|
||||
*/
|
||||
virtual void onRun() = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Run this test repeatedly for specified number of times.
|
||||
* @tparam T - Test class.
|
||||
* @param times - number of times to run this test.
|
||||
*/
|
||||
template<class T>
|
||||
static void runTest(v_int32 times){
|
||||
T test;
|
||||
@ -57,7 +81,13 @@ public:
|
||||
|
||||
};
|
||||
|
||||
#define OATPP_RUN_TEST(TEST) oatpp::test::UnitTest::runTest<TEST>(1)
|
||||
/**
|
||||
* Convenience macro to run test. <br>
|
||||
* Usage Example:<br>
|
||||
* `OATPP_RUN_TEST(oatpp::test::web::FullTest);`
|
||||
*/
|
||||
#define OATPP_RUN_TEST(TEST) \
|
||||
oatpp::test::UnitTest::runTest<TEST>(1)
|
||||
|
||||
}}
|
||||
|
||||
|
@ -30,9 +30,16 @@
|
||||
#include "oatpp/encoding/Hex.hpp"
|
||||
|
||||
namespace oatpp { namespace algorithm {
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of CRC-32. Cyclic redundancy check algorithm.
|
||||
*/
|
||||
class CRC32 {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Precalculated table
|
||||
*/
|
||||
static const p_word32 TABLE_04C11DB7;
|
||||
public:
|
||||
|
||||
@ -42,7 +49,17 @@ public:
|
||||
* Generates v_word32 table[256] for polynomial
|
||||
*/
|
||||
static p_word32 generateTable(v_word32 poly);
|
||||
|
||||
|
||||
/**
|
||||
* Calculate CRC32 value for buffer of defined size
|
||||
* @param buffer
|
||||
* @param size
|
||||
* @param crc
|
||||
* @param initValue
|
||||
* @param xorOut
|
||||
* @param table
|
||||
* @return - CRC32 value (v_word32)
|
||||
*/
|
||||
static v_word32 calc(const void *buffer, v_int32 size, v_word32 crc = 0, v_word32 initValue = 0xFFFFFFFF, v_word32 xorOut = 0xFFFFFFFF, p_word32 table = TABLE_04C11DB7);
|
||||
|
||||
};
|
||||
|
@ -22,6 +22,26 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/**[info]
|
||||
* This file contains "defines" for ApiClient code generating macro. <br>
|
||||
* Usage:<br>
|
||||
*
|
||||
* ```cpp
|
||||
* #include OATPP_CODEGEN_BEGIN(ApiClient)
|
||||
* ...
|
||||
* // Generated API-Calls.
|
||||
* ...
|
||||
* #include OATPP_CODEGEN_END(ApiClient)
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* *For details see:*
|
||||
* <ul>
|
||||
* <li>[ApiClient component](https://oatpp.io/docs/components/api-client/)</li>
|
||||
* <li>&id:oatpp::web::client::ApiClient;</li>
|
||||
* </ul>
|
||||
*/
|
||||
|
||||
#include "oatpp/core/macro/basic.hpp"
|
||||
#include "oatpp/core/macro/codegen.hpp"
|
||||
|
||||
@ -41,6 +61,10 @@
|
||||
|
||||
// INIT
|
||||
|
||||
/**
|
||||
* Codegen macoro to be used in classes extending &id:oatpp::web::client::ApiClient; to generate required fields/methods/constructors for ApiClient.
|
||||
* @param NAME - name of the ApiClient class.
|
||||
*/
|
||||
#define API_CLIENT_INIT(NAME) \
|
||||
public: \
|
||||
NAME(const std::shared_ptr<oatpp::web::client::RequestExecutor>& requestExecutor, \
|
||||
@ -176,6 +200,13 @@ OATPP_MACRO_FOREACH(OATPP_MACRO_API_CLIENT_PARAM_DECL, LIST) \
|
||||
#define OATPP_API_CALL__(X, NAME, METHOD, PATH, LIST) OATPP_API_CALL_(X, NAME, METHOD, PATH, LIST)
|
||||
#define OATPP_API_CALL___(NAME, METHOD, PATH, LIST) OATPP_API_CALL__(OATPP_MACRO_HAS_ARGS LIST, NAME, METHOD, PATH, LIST)
|
||||
|
||||
/**
|
||||
* Codegen macoro to be used in `oatpp::web::client::ApiClient` to generate REST API-Calls.
|
||||
* @param METHOD - Http method ("GET", "POST", "PUT", etc.)
|
||||
* @param PATH - Path to endpoint (without host)
|
||||
* @param NAME - Name of the generated method
|
||||
* @return - std::shared_ptr to &id:oatpp::web::protocol::http::incoming::Response;
|
||||
*/
|
||||
#define API_CALL(METHOD, PATH, NAME, ...) \
|
||||
OATPP_API_CALL___(NAME, METHOD, PATH, (__VA_ARGS__))
|
||||
|
||||
@ -239,5 +270,12 @@ oatpp::async::Action NAME(\
|
||||
#define OATPP_API_CALL_ASYNC__(X, NAME, METHOD, PATH, LIST) OATPP_API_CALL_ASYNC_(X, NAME, METHOD, PATH, LIST)
|
||||
#define OATPP_API_CALL_ASYNC___(NAME, METHOD, PATH, LIST) OATPP_API_CALL_ASYNC__(OATPP_MACRO_HAS_ARGS LIST, NAME, METHOD, PATH, LIST)
|
||||
|
||||
/**
|
||||
* Codegen macoro to be used in `oatpp::web::client::ApiClient` to generate Asynchronous REST API-Calls.
|
||||
* @param METHOD - Http method ("GET", "POST", "PUT", etc.)
|
||||
* @param PATH - Path to endpoint (without host)
|
||||
* @param NAME - Name of the generated method
|
||||
* @return - &id:oatpp::async::Action;
|
||||
*/
|
||||
#define API_CALL_ASYNC(METHOD, PATH, NAME, ...) \
|
||||
OATPP_API_CALL_ASYNC___(NAME, METHOD, PATH, (__VA_ARGS__))
|
||||
|
@ -21,6 +21,27 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/**[info]
|
||||
* This file contains "defines" for ApiController code generating macro. <br>
|
||||
* Usage:<br>
|
||||
*
|
||||
* ```cpp
|
||||
* #include OATPP_CODEGEN_BEGIN(ApiController)
|
||||
* ...
|
||||
* // Generated Endpoints.
|
||||
* ...
|
||||
* #include OATPP_CODEGEN_END(ApiController)
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* *For details see:*
|
||||
* <ul>
|
||||
* <li>[ApiController component](https://oatpp.io/docs/components/api-controller/)</li>
|
||||
* <li>&id:oatpp::web::server::api::ApiController;</li>
|
||||
* </ul>
|
||||
*/
|
||||
|
||||
#include "oatpp/core/macro/basic.hpp"
|
||||
#include "oatpp/core/macro/codegen.hpp"
|
||||
|
||||
@ -390,12 +411,19 @@ OATPP_MACRO_API_CONTROLLER_ENDPOINT_(X, NAME, METHOD, PATH, LIST)
|
||||
#define OATPP_MACRO_API_CONTROLLER_ENDPOINT___(NAME, METHOD, PATH, LIST) \
|
||||
OATPP_MACRO_API_CONTROLLER_ENDPOINT__(OATPP_MACRO_HAS_ARGS LIST, NAME, METHOD, PATH, LIST)
|
||||
|
||||
/**
|
||||
* Codegen macoro to be used in `oatpp::web::server::api::ApiController` to generate Endpoint.
|
||||
* @param METHOD - Http method ("GET", "POST", "PUT", etc.).
|
||||
* @param PATH - Path to endpoint (without host).
|
||||
* @param NAME - Name of the generated method.
|
||||
* @return - std::shared_ptr to &id:oatpp::web::protocol::http::outgoing::Response;.
|
||||
*/
|
||||
#define ENDPOINT(METHOD, PATH, NAME, ...) \
|
||||
OATPP_MACRO_API_CONTROLLER_ENDPOINT___(NAME, METHOD, PATH, (__VA_ARGS__))
|
||||
|
||||
// ENDPOINT ASYNC MACRO // ------------------------------------------------------
|
||||
|
||||
/**
|
||||
/*
|
||||
* 1 - Method to obtain endpoint call function ptr
|
||||
* 2 - Endpoint info singleton
|
||||
*/
|
||||
@ -414,7 +442,7 @@ std::shared_ptr<Endpoint::Info> Z__EDNPOINT_INFO_GET_INSTANCE_##NAME() { \
|
||||
return info; \
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* 1 - Endpoint info instance
|
||||
* 2 - Endpoint instance
|
||||
*/
|
||||
@ -434,7 +462,13 @@ const std::shared_ptr<Endpoint> Z__ENDPOINT_##NAME = createEndpoint(m_endpoints,
|
||||
Z__ENDPOINT_METHOD_##NAME(this), \
|
||||
Z__CREATE_ENDPOINT_INFO_##NAME());
|
||||
|
||||
|
||||
/**
|
||||
* Codegen macoro to be used in `oatpp::web::server::api::ApiController` to generate Asynchronous Endpoint.
|
||||
* @param METHOD - Http method ("GET", "POST", "PUT", etc.).
|
||||
* @param PATH - Path to endpoint (without host).
|
||||
* @param NAME - Name of the generated method.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
#define ENDPOINT_ASYNC(METHOD, PATH, NAME) \
|
||||
OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL_DEFAULTS(NAME, METHOD, PATH) \
|
||||
OATPP_MACRO_API_CONTROLLER_ENDPOINT_ASYNC_DECL(NAME, METHOD, PATH) \
|
||||
@ -448,6 +482,10 @@ oatpp::async::Action Z__PROXY_METHOD_##NAME(oatpp::async::AbstractCoroutine* par
|
||||
\
|
||||
class NAME : public HandlerCoroutine<NAME, __ControllerType>
|
||||
|
||||
/**
|
||||
* Auxiliary codegen macro for `ENDPOINT_ASYNC` to generate correct constructor for Asynchronous Endpoint Coroutine.
|
||||
* @NAME - Name of the endpoint. Exact the same name as was passed to `ENDPOINT_ASYNC` macro.
|
||||
*/
|
||||
#define ENDPOINT_ASYNC_INIT(NAME) \
|
||||
public: \
|
||||
\
|
||||
|
@ -22,11 +22,36 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/**[info]
|
||||
* This file contains "defines" for DTO code generating macro. <br>
|
||||
* Usage:<br>
|
||||
*
|
||||
* ```cpp
|
||||
* #include OATPP_CODEGEN_BEGIN(DTO)
|
||||
* ...
|
||||
* // Generated Endpoints.
|
||||
* ...
|
||||
* #include OATPP_CODEGEN_END(DTO)
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* *For details see:*
|
||||
* <ul>
|
||||
* <li>[Data Transfer Object(DTO) component](https://oatpp.io/docs/components/dto/)</li>
|
||||
* <li>&id:oatpp::data::mapping::type::Object;</li>
|
||||
* </ul>
|
||||
*/
|
||||
|
||||
#include "oatpp/core/macro/basic.hpp"
|
||||
#include "oatpp/core/macro/codegen.hpp"
|
||||
|
||||
// Defaults
|
||||
|
||||
/**
|
||||
* Codegen macoro to be used in classes extending &id:oatpp::data::mapping::type::Object; to generate required fields/methods/constructors for DTO object.
|
||||
* @param TYPE_NAME - name of the DTO class.
|
||||
* @param TYPE_EXTEND - name of the parent DTO class. If DTO extends &id:oatpp::data::mapping::type::Object; TYPE_EXETENDS should be `Object`.
|
||||
*/
|
||||
#define DTO_INIT(TYPE_NAME, TYPE_EXTEND) \
|
||||
public: \
|
||||
typedef TYPE_NAME Z__CLASS; \
|
||||
@ -113,6 +138,12 @@ TYPE NAME
|
||||
#define OATPP_MACRO_DTO_FIELD__(X, TYPE, NAME, LIST) OATPP_MACRO_DTO_FIELD_(X, TYPE, NAME, LIST)
|
||||
#define OATPP_MACRO_DTO_FIELD___(TYPE, NAME, LIST) OATPP_MACRO_DTO_FIELD__(OATPP_MACRO_HAS_ARGS LIST, TYPE, NAME, LIST)
|
||||
|
||||
/**
|
||||
* Codegen macro to generate fields of DTO object.
|
||||
* @param TYPE - type of the field.
|
||||
* @param NAME - name of the field.
|
||||
* @param QUALIFIER_NAME - additional (optional) field to specify serialized name of the field. If not specified it will be same as NAME.
|
||||
*/
|
||||
#define DTO_FIELD(TYPE, NAME, ...) \
|
||||
OATPP_MACRO_DTO_FIELD___(TYPE, NAME, (__VA_ARGS__))
|
||||
|
||||
|
@ -22,6 +22,26 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/**[info]
|
||||
* This file contains "undefs" for ApiClient code generating macro. <br>
|
||||
* Usage:<br>
|
||||
*
|
||||
* ```cpp
|
||||
* #include OATPP_CODEGEN_BEGIN(ApiClient)
|
||||
* ...
|
||||
* // Generated API-Calls.
|
||||
* ...
|
||||
* #include OATPP_CODEGEN_END(ApiClient)
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* *For details see:*
|
||||
* <ul>
|
||||
* <li>[ApiClient component](https://oatpp.io/docs/components/api-client/)</li>
|
||||
* <li>&id:oatpp::web::client::ApiClient;</li>
|
||||
* </ul>
|
||||
*/
|
||||
|
||||
#undef OATPP_MACRO_API_CLIENT_PARAM_MACRO
|
||||
#undef OATPP_MACRO_API_CLIENT_PARAM_TYPE
|
||||
#undef OATPP_MACRO_API_CLIENT_PARAM_NAME
|
||||
|
@ -22,6 +22,26 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/**[info]
|
||||
* This file contains "undefs" for ApiController code generating macro. <br>
|
||||
* Usage:<br>
|
||||
*
|
||||
* ```cpp
|
||||
* #include OATPP_CODEGEN_BEGIN(ApiController)
|
||||
* ...
|
||||
* // Generated Endpoints.
|
||||
* ...
|
||||
* #include OATPP_CODEGEN_END(ApiController)
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* *For details see:*
|
||||
* <ul>
|
||||
* <li>[ApiController component](https://oatpp.io/docs/components/api-controller/)</li>
|
||||
* <li>&id:oatpp::web::server::api::ApiController;</li>
|
||||
* </ul>
|
||||
*/
|
||||
|
||||
#undef OATPP_MACRO_API_CONTROLLER_PARAM_MACRO
|
||||
#undef OATPP_MACRO_API_CONTROLLER_PARAM_INFO
|
||||
#undef OATPP_MACRO_API_CONTROLLER_PARAM_TYPE
|
||||
|
@ -22,6 +22,26 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/**[info]
|
||||
* This file contains "undefs" for DTO code generating macro. <br>
|
||||
* Usage:<br>
|
||||
*
|
||||
* ```cpp
|
||||
* #include OATPP_CODEGEN_BEGIN(DTO)
|
||||
* ...
|
||||
* // Generated Endpoints.
|
||||
* ...
|
||||
* #include OATPP_CODEGEN_END(DTO)
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* *For details see:*
|
||||
* <ul>
|
||||
* <li>[Data Transfer Object(DTO) component](https://oatpp.io/docs/components/dto/)</li>
|
||||
* <li>&id:oatpp::data::mapping::type::Object;</li>
|
||||
* </ul>
|
||||
*/
|
||||
|
||||
#undef DTO_INIT
|
||||
|
||||
// Fields
|
||||
|
@ -29,14 +29,46 @@
|
||||
#include "oatpp/core/data/mapping/type/Primitive.hpp"
|
||||
|
||||
namespace oatpp {
|
||||
|
||||
|
||||
/**
|
||||
* Mapping-Enabled String type. &id:oatpp::data::mapping::type::String; <br>
|
||||
* For `oatpp::String` methods see &id:oatpp::base::StrBuffer;
|
||||
*/
|
||||
typedef oatpp::data::mapping::type::String String;
|
||||
|
||||
/**
|
||||
* Mapping-Enabled 8-bits int. Can hold nullptr value. &id:oatpp::data::mapping::type::Int8;
|
||||
*/
|
||||
typedef oatpp::data::mapping::type::Int8 Int8;
|
||||
|
||||
/**
|
||||
* Mapping-Enabled 16-bits int. Can hold nullptr value. &id:oatpp::data::mapping::type::Int16;
|
||||
*/
|
||||
typedef oatpp::data::mapping::type::Int16 Int16;
|
||||
|
||||
/**
|
||||
* Mapping-Enabled 32-bits int. Can hold nullptr value. &id:oatpp::data::mapping::type::Int32;
|
||||
*/
|
||||
typedef oatpp::data::mapping::type::Int32 Int32;
|
||||
|
||||
/**
|
||||
* Mapping-Enabled 64-bits int. Can hold nullptr value. &id:oatpp::data::mapping::type::Int64;
|
||||
*/
|
||||
typedef oatpp::data::mapping::type::Int64 Int64;
|
||||
|
||||
/**
|
||||
* Mapping-Enabled 32-bits float. Can hold nullptr value. &id:oatpp::data::mapping::type::Float32;
|
||||
*/
|
||||
typedef oatpp::data::mapping::type::Float32 Float32;
|
||||
|
||||
/**
|
||||
* Mapping-Enabled 64-bits float (double). Can hold nullptr value. &id:oatpp::data::mapping::type::Float64;
|
||||
*/
|
||||
typedef oatpp::data::mapping::type::Float64 Float64;
|
||||
|
||||
/**
|
||||
* Mapping-Enabled Boolean. Can hold nullptr value. &id:oatpp::data::mapping::type::Boolean;
|
||||
*/
|
||||
typedef oatpp::data::mapping::type::Boolean Boolean;
|
||||
|
||||
}
|
||||
|
@ -25,12 +25,17 @@
|
||||
#include "Coroutine.hpp"
|
||||
|
||||
namespace oatpp { namespace async {
|
||||
|
||||
|
||||
const Action Action::_WAIT_RETRY(TYPE_WAIT_RETRY, nullptr, nullptr);
|
||||
const Action Action::_REPEAT(TYPE_REPEAT, nullptr, nullptr);
|
||||
const Action Action::_FINISH(TYPE_FINISH, nullptr, nullptr);
|
||||
const Action Action::_ABORT(TYPE_ABORT, nullptr, nullptr);
|
||||
|
||||
|
||||
Error::Error(const char* pMessage, bool pIsExceptionThrown)
|
||||
: message(pMessage)
|
||||
, isExceptionThrown(pIsExceptionThrown)
|
||||
{}
|
||||
|
||||
Action::Action(v_int32 type,
|
||||
AbstractCoroutine* coroutine,
|
||||
FunctionPtr functionPtr)
|
||||
|
@ -33,37 +33,95 @@ namespace oatpp { namespace async {
|
||||
|
||||
class AbstractCoroutine; // FWD
|
||||
class Processor; // FWD
|
||||
|
||||
|
||||
/**
|
||||
* Class to hold and communicate errors between Coroutines
|
||||
*/
|
||||
class Error {
|
||||
public:
|
||||
|
||||
Error(const char* pMessage, bool pIsExceptionThrown = false)
|
||||
: message(pMessage)
|
||||
, isExceptionThrown(pIsExceptionThrown)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param pMessage - Error message.
|
||||
* @param pIsExceptionThrown - Indicate that this error is a result of thrown exception.
|
||||
*/
|
||||
Error(const char* pMessage, bool pIsExceptionThrown = false);
|
||||
|
||||
/**
|
||||
* Error message
|
||||
*/
|
||||
const char* message;
|
||||
|
||||
/**
|
||||
* Indicates that this error is a result of thrown exception. Re-throw if true to catch original exception.
|
||||
*/
|
||||
bool isExceptionThrown;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class Action represents an asynchronous action.
|
||||
*/
|
||||
class Action {
|
||||
friend Processor;
|
||||
friend AbstractCoroutine;
|
||||
public:
|
||||
typedef Action (AbstractCoroutine::*FunctionPtr)();
|
||||
public:
|
||||
/**
|
||||
* Indicate that Action is to start coroutine. Value = 0.
|
||||
*/
|
||||
static constexpr const v_int32 TYPE_COROUTINE = 0;
|
||||
|
||||
/**
|
||||
* Indicate that Action is to YIELD control to other method of Coroutine. Value = 1.
|
||||
*/
|
||||
static constexpr const v_int32 TYPE_YIELD_TO = 1;
|
||||
|
||||
/**
|
||||
* Indicate that Action is to WAIT and then RETRY call to current method of Coroutine. Value = 2.
|
||||
*/
|
||||
static constexpr const v_int32 TYPE_WAIT_RETRY = 2;
|
||||
|
||||
/**
|
||||
* Indicate that Action is to REPEAT call to current method of Coroutine. Value = 3.
|
||||
*/
|
||||
static constexpr const v_int32 TYPE_REPEAT = 3;
|
||||
|
||||
/**
|
||||
* Indicate that Action is to FINISH current Coroutine and return control to a caller-Coroutine. Value = 4.
|
||||
*/
|
||||
static constexpr const v_int32 TYPE_FINISH = 4;
|
||||
|
||||
/**
|
||||
* Deprecated
|
||||
*/
|
||||
static constexpr const v_int32 TYPE_ABORT = 5;
|
||||
|
||||
/**
|
||||
* Indicate that Error occurred
|
||||
*/
|
||||
static constexpr const v_int32 TYPE_ERROR = 6;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Predefined WAIT_RETRY action
|
||||
*/
|
||||
static const Action _WAIT_RETRY;
|
||||
|
||||
/**
|
||||
* Predefined REPEAT action
|
||||
*/
|
||||
static const Action _REPEAT;
|
||||
|
||||
/**
|
||||
* Predefined FINISH action
|
||||
*/
|
||||
static const Action _FINISH;
|
||||
|
||||
/**
|
||||
* Deprecated
|
||||
*/
|
||||
static const Action _ABORT;
|
||||
private:
|
||||
v_int32 m_type;
|
||||
@ -73,20 +131,39 @@ private:
|
||||
protected:
|
||||
void free();
|
||||
public:
|
||||
|
||||
Action(v_int32 type,
|
||||
AbstractCoroutine* coroutine,
|
||||
FunctionPtr functionPtr);
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param type - type of the Action.
|
||||
* @param coroutine - pointer to a Coroutine to start if type == TYPE_COROUTINE. nullptr otherwise.
|
||||
* @param functionPtr - pointer to a function to YIELD control to if type == TYPE_YIELD_TO. nullptr otherwise.
|
||||
*/
|
||||
Action(v_int32 type, AbstractCoroutine* coroutine, FunctionPtr functionPtr);
|
||||
|
||||
/**
|
||||
* Constructor. Construct error reporting action.
|
||||
* @param error - Error message.
|
||||
*/
|
||||
Action(const Error& error);
|
||||
|
||||
/**
|
||||
* Check if action is an error reporting action.
|
||||
* @return `true` if action is an error reporting action.
|
||||
*/
|
||||
bool isError();
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Abstract Coroutine. Base class for Coroutines. It provides state management, coroutines stack management and error reporting functionality.
|
||||
*/
|
||||
class AbstractCoroutine {
|
||||
friend oatpp::collection::FastQueue<AbstractCoroutine>;
|
||||
friend Processor;
|
||||
public:
|
||||
/**
|
||||
* Convenience typedef for Action
|
||||
*/
|
||||
typedef oatpp::async::Action Action;
|
||||
typedef Action (AbstractCoroutine::*FunctionPtr)();
|
||||
public:
|
||||
@ -183,7 +260,11 @@ private:
|
||||
protected:
|
||||
Action m_parentReturnAction = Action::_FINISH;
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Make one Coroutine iteration.
|
||||
* @return - control Action.
|
||||
*/
|
||||
Action iterate() {
|
||||
try {
|
||||
return takeAction(_CP->call(_FP));
|
||||
@ -202,22 +283,46 @@ public:
|
||||
}
|
||||
return action;
|
||||
};*/
|
||||
|
||||
|
||||
/**
|
||||
* Virtual Destructor
|
||||
*/
|
||||
virtual ~AbstractCoroutine(){
|
||||
m_parentReturnAction.free();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Entrypoint of Coroutine.
|
||||
* @return - Action
|
||||
*/
|
||||
virtual Action act() = 0;
|
||||
|
||||
/**
|
||||
* Call function of Coroutine specified by ptr.<br>
|
||||
* This method is called from iterate().<br>
|
||||
* Coroutine keeps track of function ptr and calls corresponding function on each iteration.
|
||||
* When Coroutine starts, function ptr points to act().
|
||||
* @param ptr - pointer of the function to call.
|
||||
* @return - Action.
|
||||
*/
|
||||
virtual Action call(FunctionPtr ptr) = 0;
|
||||
|
||||
/**
|
||||
* Internal function. Should free Coroutine on MemoryPool/Bench
|
||||
* free() also calls virtual destructor:
|
||||
* Coroutine::free() --> Bench::free(Coroutine* coroutine) { ... coroutine->~Coroutine(); ... }
|
||||
* Internal function. Should free Coroutine on MemoryPool/Bench.<br>
|
||||
* Method free() also calls virtual destructor:<br>
|
||||
* `Coroutine::free() --> Bench::free(Coroutine* coroutine) { ... coroutine->~Coroutine(); ... }`
|
||||
*/
|
||||
virtual void free() = 0;
|
||||
|
||||
virtual MemberCaller getMemberCaller() const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Default implementation of handleError(error) function.
|
||||
* User may override this function in order to handle errors.
|
||||
* @param error - error.
|
||||
* @return - Action. If handleError function returns Error,
|
||||
* current coroutine will finish, return control to caller coroutine and handleError is called for caller coroutine.
|
||||
*/
|
||||
virtual Action handleError(const Error& error) {
|
||||
return error;
|
||||
}
|
||||
@ -226,48 +331,103 @@ public:
|
||||
Action callWithParams(FunctionPtr ptr, Args... args) {
|
||||
return getMemberCaller().call<Action>(ptr, args...);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start new Coroutine as a "nested" Coroutine, keeping track of a coroutine call stack.
|
||||
* @tparam C - Coroutine to start.
|
||||
* @tparam Args - arguments to be passed to a starting coroutine.
|
||||
* @param actionOnReturn - Action to be called once new coroutine finished.
|
||||
* @param args - actual parameters passed to startCoroutine call.
|
||||
* @return - start Coroutine Action.
|
||||
*/
|
||||
template<typename C, typename ... Args>
|
||||
Action startCoroutine(const Action& actionOnReturn, Args... args) {
|
||||
C* coroutine = C::getBench().obtain(args...);
|
||||
coroutine->m_parentReturnAction = actionOnReturn;
|
||||
return Action(Action::TYPE_COROUTINE, coroutine, nullptr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start new Coroutine for result as a "nested" Coroutine, keeping track of a coroutine call stack.
|
||||
* After Coroutine finished result value should be passed to callback function. <br>
|
||||
* Example call:<br>
|
||||
* `startCoroutineForResult<CoroutineWithResult>(&MyCoroutine::onResult);`
|
||||
* @tparam CoroutineType - Coroutine to start.
|
||||
* @tparam ParentCoroutineType - calling Coroutine type.
|
||||
* @tparam CallbackArgs - callback arguments.
|
||||
* @tparam Args - arguments to be passed to a starting coroutine.
|
||||
* @param function - Callback to receive result.
|
||||
* @param args - actual parameters passed to startCoroutine call.
|
||||
* @return - start Coroutine Action.
|
||||
*/
|
||||
template<typename CoroutineType, typename ParentCoroutineType, typename ... CallbackArgs, typename ...Args>
|
||||
Action startCoroutineForResult(Action (ParentCoroutineType::*function)(CallbackArgs...), Args... args) {
|
||||
CoroutineType* coroutine = CoroutineType::getBench().obtain(args...);
|
||||
coroutine->m_callback = reinterpret_cast<FunctionPtr>(function);
|
||||
return Action(Action::TYPE_COROUTINE, coroutine, nullptr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if coroutine is finished
|
||||
* @return - true if finished
|
||||
*/
|
||||
bool finished() const {
|
||||
return _CP == nullptr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get parent coroutine
|
||||
* @return - pointer to a parent coroutine
|
||||
*/
|
||||
AbstractCoroutine* getParent() const {
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Coroutine template. <br>
|
||||
* Example usage:<br>
|
||||
* `class MyCoroutine : public oatpp::async::Coroutine<MyCoroutine>`
|
||||
* @tparam T - child class type
|
||||
*/
|
||||
template<class T>
|
||||
class Coroutine : public AbstractCoroutine {
|
||||
public:
|
||||
typedef Action (T::*Function)();
|
||||
|
||||
/**
|
||||
* Convenience typedef for Bench
|
||||
*/
|
||||
typedef oatpp::base::memory::Bench<T> Bench;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Get Bench for this Coroutine type.<br>
|
||||
* Used for system needs. End user should not use it.
|
||||
* @return
|
||||
*/
|
||||
static Bench& getBench(){
|
||||
static thread_local Bench bench(512);
|
||||
return bench;
|
||||
}
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Call function of Coroutine specified by ptr. <br>
|
||||
* Overridden `AbstractCoroutine::call()` method.
|
||||
* @param ptr - pointer of the function to call.
|
||||
* @return - Action.
|
||||
*/
|
||||
Action call(FunctionPtr ptr) override {
|
||||
Function f = static_cast<Function>(ptr);
|
||||
return (static_cast<T*>(this)->*f)();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free Coroutine instance.
|
||||
* See &l:AbstractCoroutine::free ();.
|
||||
*/
|
||||
void free() override {
|
||||
Coroutine<T>::getBench().free(static_cast<T*>(this));
|
||||
}
|
||||
@ -275,33 +435,66 @@ public:
|
||||
MemberCaller getMemberCaller() const override {
|
||||
return MemberCaller((void*) this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method to generate Action of `type == Action::TYPE_YIELD_TO`.
|
||||
* @param function - pointer to function.
|
||||
* @return - yield Action.
|
||||
*/
|
||||
Action yieldTo(Function function) const {
|
||||
return Action(Action::TYPE_YIELD_TO, nullptr, static_cast<FunctionPtr>(function));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method to generate Action of `type == Action::TYPE_WAIT_RETRY`.
|
||||
* @return - WAIT_RETRY Action.
|
||||
*/
|
||||
const Action& waitRetry() const {
|
||||
return Action::_WAIT_RETRY;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method to generate Action of `type == Action::TYPE_REPEAT`.
|
||||
* @return - repeat Action.
|
||||
*/
|
||||
const Action& repeat() const {
|
||||
return Action::_REPEAT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method to generate Action of `type == Action::TYPE_FINISH`.
|
||||
* @return - finish Action.
|
||||
*/
|
||||
const Action& finish() const {
|
||||
return Action::_FINISH;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deprecated.
|
||||
* @return - abort Action.
|
||||
*/
|
||||
const Action& abort() const {
|
||||
return Action::_ABORT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method to generate error reporting Action.
|
||||
* @param message - error message.
|
||||
* @return - error reporting Action.
|
||||
*/
|
||||
Action error(const char* message) {
|
||||
return Action(Error(message));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Coroutine with result template. <br>
|
||||
* Example usage:<br>
|
||||
* `class CoroutineWithResult : public oatpp::async::CoroutineWithResult<CoroutineWithResult, const char*>`
|
||||
* @tparam T - child class type.
|
||||
* @tparam Args - return argumet type.
|
||||
*/
|
||||
template<class T, typename ...Args>
|
||||
class CoroutineWithResult : public AbstractCoroutine {
|
||||
friend AbstractCoroutine;
|
||||
@ -316,12 +509,22 @@ public:
|
||||
private:
|
||||
FunctionPtr m_callback;
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Call function of Coroutine specified by ptr. <br>
|
||||
* Overridden AbstractCoroutine::call() method.
|
||||
* @param ptr - pointer of the function to call.
|
||||
* @return - Action.
|
||||
*/
|
||||
virtual Action call(FunctionPtr ptr) override {
|
||||
Function f = static_cast<Function>(ptr);
|
||||
return (static_cast<T*>(this)->*f)();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free Coroutine instance.
|
||||
* See &l:AbstractCoroutine::free ();.
|
||||
*/
|
||||
virtual void free() override {
|
||||
CoroutineWithResult<T, Args...>::getBench().free(static_cast<T*>(this));
|
||||
}
|
||||
@ -329,28 +532,56 @@ public:
|
||||
MemberCaller getMemberCaller() const override {
|
||||
return MemberCaller((void*) this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method to generate Action of `type == Action::TYPE_YIELD_TO`.
|
||||
* @param function - pointer to function.
|
||||
* @return - yield Action.
|
||||
*/
|
||||
Action yieldTo(Function function) const {
|
||||
return Action(Action::TYPE_YIELD_TO, nullptr, static_cast<FunctionPtr>(function));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method to generate Action of `type == Action::TYPE_WAIT_RETRY`.
|
||||
* @return - WAIT_RETRY Action.
|
||||
*/
|
||||
const Action& waitRetry() const {
|
||||
return Action::_WAIT_RETRY;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method to generate Action of `type == Action::TYPE_REPEAT`.
|
||||
* @return - repeat Action.
|
||||
*/
|
||||
const Action& repeat() const {
|
||||
return Action::_REPEAT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deprecated. <br>
|
||||
* Call caller's Callback passing returned value, and generate Action of `type == Action::TYPE_FINISH`.
|
||||
* @param args - argumets to be passed to callback.
|
||||
* @return - finish Action.
|
||||
*/
|
||||
const Action& _return(Args... args) {
|
||||
m_parentReturnAction = getParent()->callWithParams(m_callback, args...);
|
||||
return Action::_FINISH;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deprecated.
|
||||
* @return - abort Action.
|
||||
*/
|
||||
const Action& abort() const {
|
||||
return Action::_ABORT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method to generate error reporting Action.
|
||||
* @param message - error message.
|
||||
* @return - error reporting Action.
|
||||
*/
|
||||
Action error(const char* message) {
|
||||
return Action(Error(message));
|
||||
}
|
||||
|
@ -83,13 +83,11 @@ void Executor::SubmissionProcessor::addTaskSubmission(const std::shared_ptr<Task
|
||||
|
||||
Executor::Executor(v_int32 threadsCount)
|
||||
: m_threadsCount(threadsCount)
|
||||
, m_threads(new std::shared_ptr<oatpp::concurrency::Thread>[m_threadsCount])
|
||||
, m_processors(new std::shared_ptr<SubmissionProcessor>[m_threadsCount])
|
||||
, m_threads(new std::thread[m_threadsCount])
|
||||
, m_processors(new SubmissionProcessor[m_threadsCount])
|
||||
{
|
||||
for(v_int32 i = 0; i < m_threadsCount; i ++) {
|
||||
auto processor = std::make_shared<SubmissionProcessor>();
|
||||
m_processors[i] = processor;
|
||||
m_threads[i] = oatpp::concurrency::Thread::createShared(processor);
|
||||
m_threads[i] = std::thread(&SubmissionProcessor::run, &m_processors[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,19 +98,19 @@ Executor::~Executor() {
|
||||
|
||||
void Executor::join() {
|
||||
for(v_int32 i = 0; i < m_threadsCount; i ++) {
|
||||
m_threads[i]->join();
|
||||
m_threads[i].join();
|
||||
}
|
||||
}
|
||||
|
||||
void Executor::detach() {
|
||||
for(v_int32 i = 0; i < m_threadsCount; i ++) {
|
||||
m_threads[i]->detach();
|
||||
m_threads[i].detach();
|
||||
}
|
||||
}
|
||||
|
||||
void Executor::stop() {
|
||||
for(v_int32 i = 0; i < m_threadsCount; i ++) {
|
||||
m_processors[i]->stop();
|
||||
m_processors[i].stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,12 @@
|
||||
#include <condition_variable>
|
||||
|
||||
namespace oatpp { namespace async {
|
||||
|
||||
|
||||
/**
|
||||
* Asynchronous Executor.<br>
|
||||
* Executes coroutines in multiple &id:oatpp::async::Processor;
|
||||
* allocating one thread per processor.
|
||||
*/
|
||||
class Executor {
|
||||
private:
|
||||
|
||||
@ -47,7 +52,7 @@ private:
|
||||
virtual AbstractCoroutine* createCoroutine() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* Sequence generating templates
|
||||
* used to convert tuple to parameters pack
|
||||
* Example: expand SequenceGenerator<3>:
|
||||
@ -82,7 +87,7 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class SubmissionProcessor : public oatpp::concurrency::Runnable {
|
||||
class SubmissionProcessor {
|
||||
private:
|
||||
typedef oatpp::collection::LinkedList<std::shared_ptr<TaskSubmission>> Tasks;
|
||||
private:
|
||||
@ -99,37 +104,64 @@ private:
|
||||
SubmissionProcessor();
|
||||
public:
|
||||
|
||||
void run() override;
|
||||
void run();
|
||||
void stop();
|
||||
void addTaskSubmission(const std::shared_ptr<TaskSubmission>& task);
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default number of threads to run coroutines.
|
||||
*/
|
||||
static const v_int32 THREAD_NUM_DEFAULT;
|
||||
private:
|
||||
v_int32 m_threadsCount;
|
||||
std::shared_ptr<oatpp::concurrency::Thread>* m_threads;
|
||||
std::shared_ptr<SubmissionProcessor>* m_processors;
|
||||
//std::shared_ptr<oatpp::concurrency::Thread>* m_threads;
|
||||
std::thread* m_threads;
|
||||
SubmissionProcessor* m_processors;
|
||||
std::atomic<v_word32> m_balancer;
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param threadsCount - Number of threads to run coroutines.
|
||||
*/
|
||||
Executor(v_int32 threadsCount = THREAD_NUM_DEFAULT);
|
||||
|
||||
|
||||
/**
|
||||
* Non-virtual Destructor.
|
||||
*/
|
||||
~Executor();
|
||||
|
||||
|
||||
/**
|
||||
* Join all worker-threads.
|
||||
*/
|
||||
void join();
|
||||
|
||||
|
||||
/**
|
||||
* Detach all worker-threads.
|
||||
*/
|
||||
void detach();
|
||||
|
||||
|
||||
/**
|
||||
* Stop Executor. <br>
|
||||
* After all worker-threads are stopped. Join should unblock.
|
||||
*/
|
||||
void stop();
|
||||
|
||||
|
||||
/**
|
||||
* Execute Coroutine.
|
||||
* @tparam CoroutineType - type of coroutine to execute.
|
||||
* @tparam Args - types of arguments to be passed to Coroutine constructor.
|
||||
* @param params - actual arguments to be passed to Coroutine constructor.
|
||||
*/
|
||||
template<typename CoroutineType, typename ... Args>
|
||||
void execute(Args... params) {
|
||||
auto processor = m_processors[m_balancer % m_threadsCount];
|
||||
auto& processor = m_processors[m_balancer % m_threadsCount];
|
||||
|
||||
auto submission = std::make_shared<SubmissionTemplate<CoroutineType, Args...>>(params...);
|
||||
processor->addTaskSubmission(submission);
|
||||
processor.addTaskSubmission(submission);
|
||||
|
||||
m_balancer ++;
|
||||
}
|
||||
|
@ -29,7 +29,11 @@
|
||||
#include "oatpp/core/collection/FastQueue.hpp"
|
||||
|
||||
namespace oatpp { namespace async {
|
||||
|
||||
|
||||
/**
|
||||
* Asynchronous Processor.<br>
|
||||
* Responsible for processing and managing multiple Coroutines.
|
||||
*/
|
||||
class Processor {
|
||||
private:
|
||||
|
||||
@ -43,9 +47,29 @@ private:
|
||||
v_int64 m_inactivityTick = 0;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Add Coroutine to processor.
|
||||
* @param coroutine - pointer to Coroutine.
|
||||
*/
|
||||
void addCoroutine(AbstractCoroutine* coroutine);
|
||||
|
||||
/**
|
||||
* Add Coroutine to processor in "waiting queue"
|
||||
* @param coroutine
|
||||
*/
|
||||
void addWaitingCoroutine(AbstractCoroutine* coroutine);
|
||||
|
||||
/**
|
||||
* Iterate Coroutines.
|
||||
* @param numIterations - number of iterations.
|
||||
* @return - `true` if there are active Coroutines.
|
||||
*/
|
||||
bool iterate(v_int32 numIterations);
|
||||
|
||||
/**
|
||||
* Check if there is no more Coroutines in processor.
|
||||
* @return - `true` if all coroutines in all queues are finished.
|
||||
*/
|
||||
bool isEmpty() {
|
||||
return m_activeQueue.first == nullptr && m_waitingQueue.first == nullptr;
|
||||
}
|
||||
|
@ -27,6 +27,16 @@
|
||||
#include <cstring>
|
||||
|
||||
namespace oatpp { namespace base {
|
||||
|
||||
CommandLineArguments::CommandLineArguments()
|
||||
: m_argc(0)
|
||||
, m_argv(nullptr)
|
||||
{}
|
||||
|
||||
CommandLineArguments::CommandLineArguments(int argc, const char * argv[])
|
||||
: m_argc(argc)
|
||||
, m_argv(argv)
|
||||
{}
|
||||
|
||||
bool CommandLineArguments::Parser::hasArgument(int argc, const char * argv[], const char* argName) {
|
||||
return getArgumentIndex(argc, argv, argName) >= 0;
|
||||
|
@ -29,37 +29,63 @@
|
||||
|
||||
namespace oatpp { namespace base {
|
||||
|
||||
/**
|
||||
* Class for storing and managing Command Line arguments.
|
||||
*/
|
||||
class CommandLineArguments {
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Command Line arguments parser.
|
||||
*/
|
||||
class Parser {
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* returns true if getArgumentIndex(argName) >= 0
|
||||
* Check the specified argument is present among command line arguments.
|
||||
* @param argc - count of arguments in argv array.
|
||||
* @param argv - array of arguments.
|
||||
* @param argName - name of the target argument.
|
||||
* @return - `true` if `getArgumentIndex(argName) >= 0`
|
||||
*/
|
||||
static bool hasArgument(int argc, const char * argv[], const char* argName);
|
||||
|
||||
/**
|
||||
* get index of the argument with the name == argName
|
||||
*/
|
||||
static v_int32 getArgumentIndex(int argc, const char * argv[], const char* argName);
|
||||
|
||||
|
||||
/**
|
||||
* return argument wich starts with the prefix
|
||||
* ex:
|
||||
* for cmd = "-k -c 1000 -n 100 'http://127.0.0.1:8000/'"
|
||||
* getArgumentWhichStartsWith("http") == http://127.0.0.1:8000/
|
||||
* if no argument found defaultValue returned
|
||||
* Get index of the argument specified by name in the argv[] array.
|
||||
* @param argc - count of arguments in argv array.
|
||||
* @param argv - array of arguments.
|
||||
* @param argName - name of the target argument.
|
||||
* @return - index of the argument in argv[] array. -1 if there is no such argument.
|
||||
*/
|
||||
static v_int32 getArgumentIndex(int argc, const char * argv[], const char* argName);
|
||||
|
||||
/**
|
||||
* Get argument which starts with the prefix. <br>
|
||||
* Example: <br>
|
||||
* For command line: `-k -c 1000 -n 100 http://127.0.0.1:8000/` <br>
|
||||
* `getArgumentWhichStartsWith("http") == http://127.0.0.1:8000/`
|
||||
* @param argc - count of arguments in argv array.
|
||||
* @param argv - array of arguments.
|
||||
* @param argNamePrefix - prefix to search.
|
||||
* @param defaultValue - default value to return in case not found.
|
||||
* @return - argument which starts with the specified prefix.
|
||||
*/
|
||||
static const char* getArgumentStartingWith(int argc, const char * argv[], const char* argNamePrefix, const char* defaultValue = nullptr);
|
||||
|
||||
|
||||
/**
|
||||
* return value preceded by the argument
|
||||
* ex:
|
||||
* for cmd = "-k -c 1000 -n 100"
|
||||
* getNamedArgumentValue("-c") == "1000"
|
||||
* getNamedArgumentValue("-n") == "100"
|
||||
* Get value preceded by the argument. <br>
|
||||
* Example: <br>
|
||||
* For command line: `-k -c 1000 -n 100` <br>
|
||||
* `getNamedArgumentValue("-c") == "1000"`, `getNamedArgumentValue("-n") == "100"`
|
||||
* @param argc - count of arguments in argv array.
|
||||
* @param argv - array of arguments.
|
||||
* @param argName - name of the preceded argument.
|
||||
* @param defaultValue - default value to return in case not found.
|
||||
* @return - value preceded by the argument.
|
||||
*/
|
||||
static const char* getNamedArgumentValue(int argc, const char * argv[], const char* argName, const char* defaultValue = nullptr);
|
||||
|
||||
@ -69,29 +95,59 @@ private:
|
||||
int m_argc;
|
||||
const char ** m_argv;
|
||||
public:
|
||||
|
||||
CommandLineArguments()
|
||||
: m_argc(0)
|
||||
, m_argv(nullptr)
|
||||
{}
|
||||
|
||||
CommandLineArguments(int argc, const char * argv[])
|
||||
: m_argc(argc)
|
||||
, m_argv(argv)
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
CommandLineArguments();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param argc - count of arguments in argv[] array.
|
||||
* @param argv - array of arguments.
|
||||
*/
|
||||
CommandLineArguments(int argc, const char * argv[]);
|
||||
|
||||
/**
|
||||
* Check the specified argument is present.
|
||||
* @param argName - name of the target argument.
|
||||
* @return - `true` if present.
|
||||
*/
|
||||
bool hasArgument(const char* argName) {
|
||||
return Parser::hasArgument(m_argc, m_argv, argName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get index of the argument specified by name.
|
||||
* @param argName - name of the target argument.
|
||||
* @return - index of the argument in argv[] array. -1 if there is no such argument.
|
||||
*/
|
||||
v_int32 getArgumentIndex(const char* argName) {
|
||||
return Parser::getArgumentIndex(m_argc, m_argv, argName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get argument which starts with the prefix. <br>
|
||||
* Example: <br>
|
||||
* For command line: `-k -c 1000 -n 100 'http://127.0.0.1:8000/'` <br>
|
||||
* `getArgumentWhichStartsWith("http") == http://127.0.0.1:8000/`
|
||||
* @param argNamePrefix - prefix to search.
|
||||
* @param defaultValue - default value to return in case not found.
|
||||
* @return - argument which starts with the specified prefix. defaultValue if not found.
|
||||
*/
|
||||
const char* getArgumentStartingWith(const char* argNamePrefix, const char* defaultValue = nullptr) {
|
||||
return Parser::getArgumentStartingWith(m_argc, m_argv, argNamePrefix, defaultValue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get value preceded by the argument. <br>
|
||||
* Example: <br>
|
||||
* For command line: `-k -c 1000 -n 100` <br>
|
||||
* `getNamedArgumentValue("-c") == "1000"`, `getNamedArgumentValue("-n") == "100"`
|
||||
* @param argName - name of the preceded argument.
|
||||
* @param defaultValue - default value to return in case not found.
|
||||
* @return - value preceded by the argument. defaultValue if not found.
|
||||
*/
|
||||
const char* getNamedArgumentValue(const char* argName, const char* defaultValue = nullptr) {
|
||||
return Parser::getNamedArgumentValue(m_argc, m_argv, argName, defaultValue);
|
||||
}
|
||||
|
@ -32,6 +32,12 @@ Countable::Countable() {
|
||||
#endif
|
||||
}
|
||||
|
||||
Countable::Countable(const Countable& other) {
|
||||
#ifndef OATPP_DISABLE_ENV_OBJECT_COUNTERS
|
||||
Environment::incObjects();
|
||||
#endif
|
||||
}
|
||||
|
||||
Countable::~Countable(){
|
||||
#ifndef OATPP_DISABLE_ENV_OBJECT_COUNTERS
|
||||
Environment::decObjects();
|
||||
|
@ -29,10 +29,26 @@
|
||||
#include "./Environment.hpp"
|
||||
|
||||
namespace oatpp { namespace base{
|
||||
|
||||
|
||||
/**
|
||||
* Class instantiations of which can be counted.
|
||||
*/
|
||||
class Countable {
|
||||
public:
|
||||
/**
|
||||
* Constructor. Increment counter calling &id:oatpp::base::Environment::incObjects;.
|
||||
*/
|
||||
Countable();
|
||||
|
||||
/**
|
||||
* Copy constructor. Increment counter calling &id:oatpp::base::Environment::incObjects;.
|
||||
* @param other
|
||||
*/
|
||||
Countable(const Countable& other);
|
||||
|
||||
/**
|
||||
* Virtual destructor. Decrement counter calling &id:oatpp::base::Environment::decObjects;.
|
||||
*/
|
||||
virtual ~Countable();
|
||||
};
|
||||
|
||||
|
@ -71,13 +71,31 @@ typedef std::atomic_int_fast64_t v_atomicCounter;
|
||||
typedef v_int64 v_counter;
|
||||
|
||||
namespace oatpp { namespace base{
|
||||
|
||||
|
||||
/**
|
||||
* Interface for system-wide Logger.<br>
|
||||
* All calls to `OATPP_DISABLE_LOGV`, `OATPP_DISABLE_LOGE`, `OATPP_DISABLE_LOGD` should come here.
|
||||
*/
|
||||
class Logger {
|
||||
public:
|
||||
/**
|
||||
* Virtual Destructor.
|
||||
*/
|
||||
virtual ~Logger() = default;
|
||||
|
||||
/**
|
||||
* Log message with priority, tag, message.
|
||||
* @param priority - priority channel of the message.
|
||||
* @param tag - tag of the log message.
|
||||
* @param message - message.
|
||||
*/
|
||||
virtual void log(v_int32 priority, const std::string& tag, const std::string& message) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class to manage application environment.<br>
|
||||
* Manage object counters, manage components, and do system health-checks.
|
||||
*/
|
||||
class Environment{
|
||||
private:
|
||||
static v_atomicCounter m_objectsCount;
|
||||
@ -90,7 +108,11 @@ private:
|
||||
private:
|
||||
static std::unordered_map<std::string, std::unordered_map<std::string, void*>> m_components;
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Class representing system component.
|
||||
* @tparam T - component type.
|
||||
*/
|
||||
template <typename T>
|
||||
class Component {
|
||||
private:
|
||||
@ -98,7 +120,12 @@ public:
|
||||
std::string m_name;
|
||||
T m_object;
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param name - component name.
|
||||
* @param object - component object.
|
||||
*/
|
||||
Component(const std::string& name, const T& object)
|
||||
: m_type(typeid(T).name())
|
||||
, m_name(name)
|
||||
@ -106,15 +133,26 @@ public:
|
||||
{
|
||||
Environment::registerComponent(m_type, m_name, &m_object);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param object - component object.
|
||||
*/
|
||||
Component(const T& object)
|
||||
: Component("NoName", object)
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* Non-virtual Destructor.
|
||||
*/
|
||||
~Component() {
|
||||
Environment::unregisterComponent(m_type, m_name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get object stored in the component.
|
||||
* @return - object.
|
||||
*/
|
||||
T getObject() {
|
||||
return m_object;
|
||||
}
|
||||
@ -125,29 +163,106 @@ private:
|
||||
static void registerComponent(const std::string& typeName, const std::string& componentName, void* component);
|
||||
static void unregisterComponent(const std::string& typeName, const std::string& componentName);
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Initialize environment and do basic health-checks.
|
||||
*/
|
||||
static void init();
|
||||
|
||||
/**
|
||||
* De-initialize environment and do basic health-checks.
|
||||
* Check for memory leaks.
|
||||
*/
|
||||
static void destroy();
|
||||
|
||||
|
||||
/**
|
||||
* increment counter of objects.
|
||||
*/
|
||||
static void incObjects();
|
||||
|
||||
/**
|
||||
* decrement counter of objects.
|
||||
*/
|
||||
static void decObjects();
|
||||
|
||||
|
||||
/**
|
||||
* Get count of objects currently allocated and stored in the memory.
|
||||
* @return
|
||||
*/
|
||||
static v_counter getObjectsCount();
|
||||
|
||||
/**
|
||||
* Get count of objects created for a whole system lifetime.
|
||||
* @return - count of objects.
|
||||
*/
|
||||
static v_counter getObjectsCreated();
|
||||
|
||||
|
||||
/**
|
||||
* Same as `getObjectsCount()` but `thread_local`
|
||||
* @return - count of objects.
|
||||
*/
|
||||
static v_counter getThreadLocalObjectsCount();
|
||||
|
||||
/**
|
||||
* Same as `getObjectsCreated()` but `thread_local`
|
||||
* @return - count of objects.
|
||||
*/
|
||||
static v_counter getThreadLocalObjectsCreated();
|
||||
|
||||
|
||||
/**
|
||||
* Set environment logger.
|
||||
* @param logger - pointer to logger.
|
||||
*/
|
||||
static void setLogger(Logger* logger);
|
||||
|
||||
/**
|
||||
* Print debug information of compilation config.<br>
|
||||
* Print values for: <br>
|
||||
* - `OATPP_DISABLE_ENV_OBJECT_COUNTERS`<br>
|
||||
* - `OATPP_DISABLE_POOL_ALLOCATIONS`<br>
|
||||
* - `OATPP_THREAD_HARDWARE_CONCURRENCY`<br>
|
||||
* - `OATPP_THREAD_DISTRIBUTED_MEM_POOL_SHARDS_COUNT`<br>
|
||||
* - `OATPP_ASYNC_EXECUTOR_THREAD_NUM_DEFAULT`
|
||||
*/
|
||||
static void printCompilationConfig();
|
||||
|
||||
|
||||
/**
|
||||
* Call `Logger::log()`
|
||||
* @param priority - priority channel of the message.
|
||||
* @param tag - tag of the log message.
|
||||
* @param message - message.
|
||||
*/
|
||||
static void log(v_int32 priority, const std::string& tag, const std::string& message);
|
||||
|
||||
/**
|
||||
* Format message and call `Logger::log()`<br>
|
||||
* Message is formatted using `vsnprintf` method.
|
||||
* @param priority - priority channel of the message.
|
||||
* @param tag - tag of the log message.
|
||||
* @param message - message.
|
||||
* @param ... - format arguments.
|
||||
*/
|
||||
static void logFormatted(v_int32 priority, const std::string& tag, const char* message, ...);
|
||||
|
||||
|
||||
/**
|
||||
* Get component object by typeName.
|
||||
* @param typeName - type name of the component.
|
||||
* @return - pointer to a component object.
|
||||
*/
|
||||
static void* getComponent(const std::string& typeName);
|
||||
|
||||
/**
|
||||
* Get component object by typeName and componentName.
|
||||
* @param typeName - type name of the component.
|
||||
* @param componentName - component qualifier name.
|
||||
* @return - pointer to a component object.
|
||||
*/
|
||||
static void* getComponent(const std::string& typeName, const std::string& componentName);
|
||||
|
||||
|
||||
/**
|
||||
* Get ticks count in microseconds.
|
||||
* @return - ticks count in microseconds.
|
||||
*/
|
||||
static v_int64 getMicroTickCount();
|
||||
|
||||
};
|
||||
|
@ -70,7 +70,19 @@ p_char8 StrBuffer::allocStrBuffer(const void* originData, v_int32 size, bool cop
|
||||
}
|
||||
return (p_char8) originData;
|
||||
}
|
||||
|
||||
|
||||
StrBuffer::StrBuffer()
|
||||
: m_data((p_char8)"[<nullptr>]")
|
||||
, m_size(11)
|
||||
, m_hasOwnData(false)
|
||||
{}
|
||||
|
||||
StrBuffer::StrBuffer(const void* data, v_int32 size, bool copyAsOwnData)
|
||||
: m_data(allocStrBuffer(data, size, copyAsOwnData))
|
||||
, m_size(size)
|
||||
, m_hasOwnData(copyAsOwnData)
|
||||
{}
|
||||
|
||||
StrBuffer::~StrBuffer() {
|
||||
if(m_hasOwnData) {
|
||||
delete [] m_data;
|
||||
|
@ -32,6 +32,9 @@
|
||||
|
||||
namespace oatpp { namespace base {
|
||||
|
||||
/**
|
||||
* String buffer class.
|
||||
*/
|
||||
class StrBuffer : public oatpp::base::Countable {
|
||||
private:
|
||||
|
||||
@ -63,105 +66,305 @@ private:
|
||||
void setAndCopy(const void* data, const void* originData, v_int32 size);
|
||||
static std::shared_ptr<StrBuffer> allocShared(const void* data, v_int32 size, bool copyAsOwnData);
|
||||
|
||||
/**
|
||||
* Allocate memory for string or use originData
|
||||
* if copyAsOwnData == false return originData
|
||||
/*
|
||||
* Allocate memory for string or use originData<br>
|
||||
* if copyAsOwnData == false return originData
|
||||
*/
|
||||
static p_char8 allocStrBuffer(const void* originData, v_int32 size, bool copyAsOwnData);
|
||||
|
||||
public:
|
||||
StrBuffer()
|
||||
: m_data((p_char8)"[<nullptr>]")
|
||||
, m_size(11)
|
||||
, m_hasOwnData(false)
|
||||
{}
|
||||
|
||||
StrBuffer(const void* data, v_int32 size, bool copyAsOwnData)
|
||||
: m_data(allocStrBuffer(data, size, copyAsOwnData))
|
||||
, m_size(size)
|
||||
, m_hasOwnData(copyAsOwnData)
|
||||
{}
|
||||
/**
|
||||
* Constructor. Default.
|
||||
*/
|
||||
StrBuffer();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param data - pointer to data.
|
||||
* @param size - size of the data.
|
||||
* @param copyAsOwnData - if true then allocate own buffer and copy data to that buffer.
|
||||
*/
|
||||
StrBuffer(const void* data, v_int32 size, bool copyAsOwnData);
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* virtual Destructor.
|
||||
*/
|
||||
virtual ~StrBuffer();
|
||||
|
||||
|
||||
/**
|
||||
* Create shared StrBuffer of specified size.
|
||||
* @param size - size of the buffer.
|
||||
* @return - shared_ptr to StrBuffer.
|
||||
*/
|
||||
static std::shared_ptr<StrBuffer> createShared(v_int32 size);
|
||||
|
||||
/**
|
||||
* Create shared StrBuffer with data, size, and copyAsOwnData parameters.
|
||||
* @param data - buffer data.
|
||||
* @param size - size of the data.
|
||||
* @param copyAsOwnData - if true then allocate own buffer and copy data to that buffer.
|
||||
* @return - shared_ptr to StrBuffer.
|
||||
*/
|
||||
static std::shared_ptr<StrBuffer> createShared(const void* data, v_int32 size, bool copyAsOwnData = true);
|
||||
|
||||
/**
|
||||
* Create shared StrBuffer with data, and copyAsOwnData parameters.
|
||||
* @param data - buffer data.
|
||||
* @param copyAsOwnData - if true then allocate own buffer and copy data to that buffer.
|
||||
* @return - shared_ptr to StrBuffer.
|
||||
*/
|
||||
static std::shared_ptr<StrBuffer> createShared(const char* data, bool copyAsOwnData = true);
|
||||
|
||||
/**
|
||||
* Create shared StrBuffer from other StrBuffer.
|
||||
* @param other - other StrBuffer.
|
||||
* @param copyAsOwnData - if true then allocate own buffer and copy data to that buffer.
|
||||
* @return - shared_ptr to StrBuffer.
|
||||
*/
|
||||
static std::shared_ptr<StrBuffer> createShared(StrBuffer* other, bool copyAsOwnData = true);
|
||||
|
||||
|
||||
/**
|
||||
* Create shared StrBuffer of size=size1 + size2 and data=data1 + data2.
|
||||
* @param data1 - pointer to data1.
|
||||
* @param size1 - size of the data1.
|
||||
* @param data2 - pointer to data2.
|
||||
* @param size2 - size of the data2.
|
||||
* @return - shared_ptr to StrBuffer.
|
||||
*/
|
||||
static std::shared_ptr<StrBuffer> createSharedConcatenated(const void* data1, v_int32 size1, const void* data2, v_int32 size2);
|
||||
|
||||
|
||||
/**
|
||||
* Create shared StrBuffer from c-string.
|
||||
* @param data - data.
|
||||
* @param copyAsOwnData - if true then allocate own buffer and copy data to that buffer.
|
||||
* @return - shared_ptr to StrBuffer.
|
||||
*/
|
||||
static std::shared_ptr<StrBuffer> createFromCString(const char* data, bool copyAsOwnData = true) {
|
||||
if(data != nullptr) {
|
||||
return allocShared(data, (v_int32) std::strlen(data), copyAsOwnData);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load data from file and store in StrBuffer.
|
||||
* If file not found return nullptr
|
||||
* @param filename - name of the file.
|
||||
* @return - shared_ptr to StrBuffer.
|
||||
*/
|
||||
static std::shared_ptr<StrBuffer> loadFromFile(const char* filename);
|
||||
|
||||
void saveToFile(const char* filename);
|
||||
|
||||
p_char8 getData() const;
|
||||
v_int32 getSize() const;
|
||||
|
||||
const char* c_str() const;
|
||||
std::string std_str() const;
|
||||
|
||||
bool hasOwnData() const;
|
||||
|
||||
|
||||
/**
|
||||
* (correct for ACII only)
|
||||
* Save content of the buffer to file.
|
||||
* @param filename - name of the file.
|
||||
*/
|
||||
void saveToFile(const char* filename);
|
||||
|
||||
/**
|
||||
* Get pointer to data of the buffer.
|
||||
* @return - pointer to data of the buffer.
|
||||
*/
|
||||
p_char8 getData() const;
|
||||
|
||||
/**
|
||||
* Get buffer size.
|
||||
* @return - buffer size.
|
||||
*/
|
||||
v_int32 getSize() const;
|
||||
|
||||
/**
|
||||
* Get pointer to data of the buffer as `const* char`.
|
||||
* @return - pointer to data of the buffer.
|
||||
*/
|
||||
const char* c_str() const;
|
||||
|
||||
/**
|
||||
* Get copy of the buffer data as `std::string`.
|
||||
* @return - copy of the buffer data as `std::string`.
|
||||
*/
|
||||
std::string std_str() const;
|
||||
|
||||
/**
|
||||
* Is this object is responsible for freeing buffer data.
|
||||
* @return - true if this object is responsible for freeing buffer data.
|
||||
*/
|
||||
bool hasOwnData() const;
|
||||
|
||||
/**
|
||||
* Create lowercase copy of the buffer.<br>
|
||||
* (correct for ASCII only)
|
||||
* @return - copy of the buffer containing lowercase variants of ascii symbols.
|
||||
*/
|
||||
std::shared_ptr<StrBuffer> toLowerCase() const;
|
||||
|
||||
|
||||
/**
|
||||
* (correct for ACII only)
|
||||
* Create uppercase copy of the buffer.<br>
|
||||
* (correct for ASCII only)
|
||||
* @return - copy of the buffer containing uppercase variants of ascii symbols.
|
||||
*/
|
||||
std::shared_ptr<StrBuffer> toUpperCase() const;
|
||||
|
||||
|
||||
/**
|
||||
* Check string equality of the buffer to data of specified size.
|
||||
* @param data - pointer to data to be compared with the buffer data.
|
||||
* @param size - size of the data.
|
||||
* @return - true if all chars of buffer are same as in data, and size == this.getSize().
|
||||
*/
|
||||
bool equals(const void* data, v_int32 size) const;
|
||||
|
||||
/**
|
||||
* Check string equality of the buffer to data of specified size.
|
||||
* @param data - pointer to data to be compared with the buffer data.
|
||||
* @return - true if all chars of buffer are same as in data, and std::strlen(data) == this.getSize().
|
||||
*/
|
||||
bool equals(const char* data) const;
|
||||
|
||||
/**
|
||||
* Check string equality to other buffer.
|
||||
* @param other - pointer to other StrBuffer to be compared with the buffer data.
|
||||
* @return - true if all chars of one buffer are same as in other, and other.getSize() == this.getSize().
|
||||
*/
|
||||
bool equals(StrBuffer* other) const;
|
||||
|
||||
|
||||
/**
|
||||
* Check if buffer starts with specified data, size.
|
||||
* @param data - data as `const void*`.
|
||||
* @param size - size of the data.
|
||||
* @return - true if buffer starts with specified data.
|
||||
*/
|
||||
bool startsWith(const void* data, v_int32 size) const;
|
||||
|
||||
/**
|
||||
* Check if buffer starts with specified data.
|
||||
* @param data - data as `const char*`.
|
||||
* @return - true if buffer starts with specified data.
|
||||
*/
|
||||
bool startsWith(const char* data) const;
|
||||
|
||||
/**
|
||||
* Check if buffer starts with specified data.
|
||||
* @param data - data as `StrBuffer`.
|
||||
* @return - true if buffer starts with specified data.
|
||||
*/
|
||||
bool startsWith(StrBuffer* data) const;
|
||||
|
||||
public:
|
||||
|
||||
static v_int32 compare(const void* data1, const void* data2, v_int32 size);
|
||||
static v_int32 compare(StrBuffer* str1, StrBuffer* str2);
|
||||
|
||||
static bool equals(const void* data1, const void* data2, v_int32 size);
|
||||
static bool equals(const char* data1, const char* data2);
|
||||
static bool equals(StrBuffer* str1, StrBuffer* str2);
|
||||
|
||||
// Case Insensitive (correct for ASCII only)
|
||||
|
||||
static bool equalsCI(const void* data1, const void* data2, v_int32 size);
|
||||
static bool equalsCI(const char* data1, const char* data2);
|
||||
static bool equalsCI(StrBuffer* str1, StrBuffer* str2);
|
||||
|
||||
// Case Insensitive Fast (ASCII only, correct compare if one of strings contains letters only)
|
||||
|
||||
static bool equalsCI_FAST(const void* data1, const void* data2, v_int32 size);
|
||||
static bool equalsCI_FAST(const char* data1, const char* data2);
|
||||
static bool equalsCI_FAST(StrBuffer* str1, StrBuffer* str2);
|
||||
static bool equalsCI_FAST(StrBuffer* str1, const char* str2);
|
||||
|
||||
|
||||
/**
|
||||
* lower case chars in the buffer @data (correct for ACII only)
|
||||
* Compare data1, data2 using `std::memcmp`.
|
||||
* @param data1 - pointer to data1.
|
||||
* @param data2 - pointer to data2.
|
||||
* @param size - number of characters to compare.
|
||||
* @return - Negative value if the first differing byte (reinterpreted as unsigned char) in data1 is less than the corresponding byte in data2.<br>
|
||||
* 0 if all count bytes of data1 and data2 are equal.<br>
|
||||
* Positive value if the first differing byte in data1 is greater than the corresponding byte in data2.
|
||||
*/
|
||||
static v_int32 compare(const void* data1, const void* data2, v_int32 size);
|
||||
|
||||
/**
|
||||
* Compare data1, data2 using `std::memcmp`.
|
||||
* @param data1 - data1 as `StrBuffer`.
|
||||
* @param data2 - data2 as `StrBuffer`.
|
||||
* @return - Negative value if the first differing byte (reinterpreted as unsigned char) in data1 is less than the corresponding byte in data2.<br>
|
||||
* 0 if all count bytes of data1 and data2 are equal.<br>
|
||||
* Positive value if the first differing byte in data1 is greater than the corresponding byte in data2.
|
||||
*/
|
||||
static v_int32 compare(StrBuffer* data1, StrBuffer* data2);
|
||||
|
||||
/**
|
||||
* Check string equality of data1 to data2.
|
||||
* @param data1 - pointer to data1.
|
||||
* @param data2 - pointer to data2.
|
||||
* @param size - number of characters to compare.
|
||||
* @return - `true` if equals.
|
||||
*/
|
||||
static bool equals(const void* data1, const void* data2, v_int32 size);
|
||||
|
||||
/**
|
||||
* Check string equality of data1 to data2.
|
||||
* @param data1 - pointer to data1.
|
||||
* @param data2 - pointer to data2.
|
||||
* @return - `true` if equals.
|
||||
*/
|
||||
static bool equals(const char* data1, const char* data2);
|
||||
|
||||
/**
|
||||
* Check string equality of str1 to str2.
|
||||
* @param str1 - pointer to str1.
|
||||
* @param str2 - pointer to str2.
|
||||
* @return - `true` if equals.
|
||||
*/
|
||||
static bool equals(StrBuffer* str1, StrBuffer* str2);
|
||||
|
||||
/**
|
||||
* Check Case Insensitive string equality of data1 to data2.
|
||||
* @param data1 - pointer to data1.
|
||||
* @param data2 - pointer to data2.
|
||||
* @param size - number of characters to compare.
|
||||
* @return - `true` if equals.
|
||||
*/
|
||||
static bool equalsCI(const void* data1, const void* data2, v_int32 size);
|
||||
|
||||
/**
|
||||
* Check Case Insensitive string equality of data1 to data2.
|
||||
* @param data1 - pointer to data1.
|
||||
* @param data2 - pointer to data2.
|
||||
* @return - `true` if equals.
|
||||
*/
|
||||
static bool equalsCI(const char* data1, const char* data2);
|
||||
|
||||
/**
|
||||
* Check Case Insensitive string equality of str1 to str2.
|
||||
* @param str1 - pointer to str1.
|
||||
* @param str2 - pointer to str2.
|
||||
* @return - `true` if equals.
|
||||
*/
|
||||
static bool equalsCI(StrBuffer* str1, StrBuffer* str2);
|
||||
|
||||
/**
|
||||
* Check Case Insensitive string equality of data1 to data2. (ASCII only, correct compare if one of strings contains letters only)
|
||||
* @param data1 - pointer to data1.
|
||||
* @param data2 - pointer to data2.
|
||||
* @param size - number of characters to compare.
|
||||
* @return - `true` if equals.
|
||||
*/
|
||||
static bool equalsCI_FAST(const void* data1, const void* data2, v_int32 size);
|
||||
|
||||
/**
|
||||
* Check Case Insensitive string equality of data1 to data2. (ASCII only, correct compare if one of strings contains letters only)
|
||||
* @param data1 - pointer to data1.
|
||||
* @param data2 - pointer to data2.
|
||||
* @return - `true` if equals.
|
||||
*/
|
||||
static bool equalsCI_FAST(const char* data1, const char* data2);
|
||||
|
||||
/**
|
||||
* Check Case Insensitive string equality of str1 to str2. (ASCII only, correct compare if one of strings contains letters only)
|
||||
* @param str1 - pointer to str1.
|
||||
* @param str2 - pointer to str2.
|
||||
* @return - `true` if equals.
|
||||
*/
|
||||
static bool equalsCI_FAST(StrBuffer* str1, StrBuffer* str2);
|
||||
|
||||
/**
|
||||
* Check Case Insensitive string equality of str1 to str2. (ASCII only, correct compare if one of strings contains letters only)
|
||||
* @param str1 - pointer to str1 as `StrBuffer`.
|
||||
* @param str2 - pointer to str2 as `const char*`
|
||||
* @return - `true` if equals.
|
||||
*/
|
||||
static bool equalsCI_FAST(StrBuffer* str1, const char* str2);
|
||||
|
||||
/**
|
||||
* Change characters in data to lowercase.
|
||||
* @param data - pointer to data.
|
||||
* @param size - size of the data.
|
||||
*/
|
||||
static void lowerCase(const void* data, v_int32 size);
|
||||
|
||||
|
||||
/**
|
||||
* upper case chars in the buffer @data (correct for ACII only)
|
||||
* Change characters in data to uppercase.
|
||||
* @param data - pointer to data.
|
||||
* @param size - size of the data.
|
||||
*/
|
||||
static void upperCase(const void* data, v_int32 size);
|
||||
|
||||
|
@ -23,3 +23,12 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "Allocator.hpp"
|
||||
|
||||
namespace oatpp { namespace base { namespace memory {
|
||||
|
||||
AllocatorPoolInfo::AllocatorPoolInfo(const char* pPoolName, v_int32 pPoolChunkSize)
|
||||
: poolName(pPoolName)
|
||||
, poolChunkSize(pPoolChunkSize)
|
||||
{}
|
||||
|
||||
}}}
|
@ -29,16 +29,35 @@
|
||||
|
||||
namespace oatpp { namespace base { namespace memory {
|
||||
|
||||
/**
|
||||
* Pool Information for Pool Allocators.
|
||||
*/
|
||||
class AllocatorPoolInfo {
|
||||
public:
|
||||
AllocatorPoolInfo(const char* pPoolName, v_int32 pPoolChunkSize)
|
||||
: poolName(pPoolName)
|
||||
, poolChunkSize(pPoolChunkSize)
|
||||
{}
|
||||
/**
|
||||
* Constructor.
|
||||
* @param pPoolName - memory pool name.
|
||||
* @param pPoolChunkSize - memory pool chunk size. For more about chunk size see &id:oatpp::base::memory::MemoryPool::MemoryPool;.
|
||||
*/
|
||||
AllocatorPoolInfo(const char* pPoolName, v_int32 pPoolChunkSize);
|
||||
|
||||
/**
|
||||
* Memory pool name.
|
||||
*/
|
||||
const char* const poolName;
|
||||
|
||||
/**
|
||||
* Memory pool chunk size.
|
||||
* For more about chunk size see &id:oatpp::base::memory::MemoryPool::MemoryPool;.
|
||||
*/
|
||||
const v_int32 poolChunkSize;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Allocator to allocate shared object on &id:oatpp::base::memory::MemoryPool;
|
||||
* Used to allocate shared_ptr control block and an object in the same memory entry of the pool.
|
||||
* @tparam T - type of the object to allocate.
|
||||
*/
|
||||
template<class T>
|
||||
class PoolSharedObjectAllocator {
|
||||
public:
|
||||
@ -79,7 +98,11 @@ template <typename T, typename U>
|
||||
inline bool operator != (const PoolSharedObjectAllocator<T>& a, const PoolSharedObjectAllocator<U>& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Same as &l:PoolSharedObjectAllocator; but uses `thread_local` &id:oatpp::base::memory::MemoryPool;.
|
||||
* @tparam T - type of the object to allocate.
|
||||
*/
|
||||
template<class T>
|
||||
class ThreadLocalPoolSharedObjectAllocator {
|
||||
public:
|
||||
@ -120,17 +143,26 @@ template <typename T, typename U>
|
||||
inline bool operator != (const ThreadLocalPoolSharedObjectAllocator<T>& a, const ThreadLocalPoolSharedObjectAllocator<U>& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extra information for, and about allocation.
|
||||
* Used for variable-size objects allocations. (ex.: for strings).
|
||||
*/
|
||||
class AllocationExtras {
|
||||
public:
|
||||
AllocationExtras(v_int32 pExtraWanted)
|
||||
: extraWanted(pExtraWanted)
|
||||
: extraWanted(pExtraWanted)
|
||||
{}
|
||||
const v_int32 extraWanted;
|
||||
void* extraPtr;
|
||||
v_int32 baseSize;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Allocator for shared objects.
|
||||
* Used to allocate object and shared_ptr's control block in the same memory entry.
|
||||
* @tparam T - type of the object to allocate.
|
||||
*/
|
||||
template<class T>
|
||||
class SharedObjectAllocator {
|
||||
public:
|
||||
@ -160,7 +192,12 @@ public:
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Allocator for shared objects. Allocates objects on the pool provided.
|
||||
* @tparam T - type of object to allocate.
|
||||
* @tparam P - type of memory pool to allocate object on.
|
||||
*/
|
||||
template<class T, class P>
|
||||
class CustomPoolSharedObjectAllocator {
|
||||
public:
|
||||
@ -203,7 +240,7 @@ template <typename T, typename U>
|
||||
inline bool operator != (const SharedObjectAllocator<T>& a, const SharedObjectAllocator<U>& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
|
||||
template<typename T, typename ... Args>
|
||||
static std::shared_ptr<T> allocateSharedWithExtras(AllocationExtras& extras, Args... args){
|
||||
typedef SharedObjectAllocator<T> _Allocator;
|
||||
|
@ -28,6 +28,31 @@
|
||||
|
||||
namespace oatpp { namespace base { namespace memory {
|
||||
|
||||
MemoryPool::MemoryPool(const std::string& name, v_int32 entrySize, v_int32 chunkSize)
|
||||
: m_name(name)
|
||||
, m_entrySize(entrySize)
|
||||
, m_chunkSize(chunkSize)
|
||||
, m_id(++poolIdCounter)
|
||||
, m_rootEntry(nullptr)
|
||||
, m_atom(false)
|
||||
, m_objectsCount(0)
|
||||
{
|
||||
allocChunk();
|
||||
oatpp::concurrency::SpinLock lock(POOLS_ATOM);
|
||||
POOLS[m_id] = this;
|
||||
}
|
||||
|
||||
MemoryPool::~MemoryPool() {
|
||||
auto it = m_chunks.begin();
|
||||
while (it != m_chunks.end()) {
|
||||
p_char8 chunk = *it;
|
||||
delete [] chunk;
|
||||
it++;
|
||||
}
|
||||
oatpp::concurrency::SpinLock lock(POOLS_ATOM);
|
||||
POOLS.erase(m_id);
|
||||
}
|
||||
|
||||
void MemoryPool::allocChunk() {
|
||||
#ifdef OATPP_DISABLE_POOL_ALLOCATIONS
|
||||
// DO NOTHING
|
||||
|
@ -34,7 +34,11 @@
|
||||
#include <cstring>
|
||||
|
||||
namespace oatpp { namespace base { namespace memory {
|
||||
|
||||
|
||||
/**
|
||||
* Memory Pool allocates memory chunks. Each chunk consists of specified number of fixed-size entries.
|
||||
* Entries can be obtained and freed by user. When memory pool runs out of free entries, new chunk is allocated.
|
||||
*/
|
||||
class MemoryPool {
|
||||
public:
|
||||
static oatpp::concurrency::SpinLock::Atom POOLS_ATOM;
|
||||
@ -70,58 +74,114 @@ private:
|
||||
oatpp::concurrency::SpinLock::Atom m_atom;
|
||||
v_int32 m_objectsCount;
|
||||
public:
|
||||
|
||||
MemoryPool(const std::string& name, v_int32 entrySize, v_int32 chunkSize)
|
||||
: m_name(name)
|
||||
, m_entrySize(entrySize)
|
||||
, m_chunkSize(chunkSize)
|
||||
, m_id(++poolIdCounter)
|
||||
, m_rootEntry(nullptr)
|
||||
, m_atom(false)
|
||||
, m_objectsCount(0)
|
||||
{
|
||||
allocChunk();
|
||||
oatpp::concurrency::SpinLock lock(POOLS_ATOM);
|
||||
POOLS[m_id] = this;
|
||||
}
|
||||
|
||||
virtual ~MemoryPool() {
|
||||
auto it = m_chunks.begin();
|
||||
while (it != m_chunks.end()) {
|
||||
p_char8 chunk = *it;
|
||||
delete [] chunk;
|
||||
it++;
|
||||
}
|
||||
oatpp::concurrency::SpinLock lock(POOLS_ATOM);
|
||||
POOLS.erase(m_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param name - name of the pool.
|
||||
* @param entrySize - size of the entry in bytes returned in call to &l:MemoryPool::obtain ();.
|
||||
* @param chunkSize - number of entries in one chunk.
|
||||
*/
|
||||
MemoryPool(const std::string& name, v_int32 entrySize, v_int32 chunkSize);
|
||||
|
||||
/**
|
||||
* Virtual destructor.
|
||||
*/
|
||||
virtual ~MemoryPool();
|
||||
|
||||
/**
|
||||
* Obtain pointer to memory entry.
|
||||
* When entry is no more needed, user must call &id:oatpp::base::memory::MemoryPool::free; and pass obtained entry pointer as a parameter.
|
||||
* @return - pointer to memory entry.
|
||||
*/
|
||||
void* obtain();
|
||||
|
||||
/*
|
||||
* Do not use it.
|
||||
* Same as &l:MemoryPool::obtain (); but lock free. <br>
|
||||
* TODO - check if this method is ever used.
|
||||
* @return - pointer to memory entry.
|
||||
*/
|
||||
void* obtainLockFree();
|
||||
|
||||
|
||||
/*
|
||||
* For internal use only.
|
||||
* TODO - make it private.
|
||||
* @param entry
|
||||
*/
|
||||
void freeByEntryHeader(EntryHeader* entry);
|
||||
|
||||
/**
|
||||
* Free obtained earlier memory entry.
|
||||
* This method is static, because entry "knows" to what pool it belongs.
|
||||
* @param entry - entry obtained by call to &l:MemoryPool::obtain ();
|
||||
*/
|
||||
static void free(void* entry);
|
||||
|
||||
|
||||
/**
|
||||
* Get name of the memory pool.
|
||||
* @return - memory pool name as `std::string`.
|
||||
*/
|
||||
std::string getName();
|
||||
|
||||
/**
|
||||
* Get size of the memory entry in bytes which can be obtained by call to &l:MemoryPool::obtain ();.
|
||||
* @return - size of the enrty in bytes.
|
||||
*/
|
||||
v_int32 getEntrySize();
|
||||
|
||||
/**
|
||||
* Get size of the memory allocated by memory pool.
|
||||
* @return - size of the memory allocated by memory pool.
|
||||
*/
|
||||
v_int64 getSize();
|
||||
|
||||
/**
|
||||
* Get number of entries currently in use.
|
||||
* @return - number of entries currently in use.
|
||||
*/
|
||||
v_int32 getObjectsCount();
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates multiple MemoryPools (&l:MemoryPool;) to reduce concurrency blocking in call to &l:ThreadDistributedMemoryPool::obtain ();
|
||||
*/
|
||||
class ThreadDistributedMemoryPool {
|
||||
private:
|
||||
v_int32 m_shardsCount;
|
||||
MemoryPool** m_shards;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default number of MemoryPools (&l:MemoryPool;) "shards" to create.
|
||||
*/
|
||||
static const v_int32 SHARDS_COUNT_DEFAULT;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param name - name of the memory pool.
|
||||
* @param entrySize - size of memory pool entry.
|
||||
* @param chunkSize - number of entries in chunk.
|
||||
* @param shardsCount - number of MemoryPools (&l:MemoryPool;) "shards" to create.
|
||||
*/
|
||||
ThreadDistributedMemoryPool(const std::string& name, v_int32 entrySize, v_int32 chunkSize,
|
||||
v_int32 shardsCount = SHARDS_COUNT_DEFAULT);
|
||||
virtual ~ThreadDistributedMemoryPool();
|
||||
|
||||
/**
|
||||
* Obtain pointer to memory entry.
|
||||
* When entry is no more needed, user must call &id:oatpp::base::memory::MemoryPool::free; and pass obtained entry pointer as a parameter.
|
||||
* @return - pointer to memory entry.
|
||||
*/
|
||||
void* obtain();
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Not thread-safe pool of objects of specified type.
|
||||
* @tparam T - object type.
|
||||
*/
|
||||
template<typename T>
|
||||
class Bench {
|
||||
private:
|
||||
@ -163,7 +223,11 @@ private:
|
||||
Block* m_blocks;
|
||||
T** m_index;
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param growSize - number of objects to allocate when no free objects left.
|
||||
*/
|
||||
Bench(v_int32 growSize)
|
||||
: m_growSize(growSize)
|
||||
, m_size(0)
|
||||
@ -173,7 +237,10 @@ public:
|
||||
{
|
||||
grow();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Non virtual destructor.
|
||||
*/
|
||||
~Bench(){
|
||||
auto curr = m_blocks;
|
||||
while (curr != nullptr) {
|
||||
@ -183,7 +250,13 @@ public:
|
||||
}
|
||||
delete [] m_index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct object and get pointer to constructed object.
|
||||
* @tparam Args - arguments to be passed to object constructor.
|
||||
* @param args - actual arguments to pass to object constructor.
|
||||
* @return - pointer to constructed object.
|
||||
*/
|
||||
template<typename ... Args>
|
||||
T* obtain(Args... args) {
|
||||
if(m_indexPosition == m_size) {
|
||||
@ -191,7 +264,11 @@ public:
|
||||
}
|
||||
return new (m_index[m_indexPosition ++]) T(args...);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call object destructor and put it on "bench".
|
||||
* @param entry - object to be freed.
|
||||
*/
|
||||
void free(T* entry) {
|
||||
entry->~T();
|
||||
m_index[--m_indexPosition] = entry;
|
||||
|
@ -30,6 +30,12 @@
|
||||
|
||||
namespace oatpp { namespace base { namespace memory {
|
||||
|
||||
/**
|
||||
* Macro to declare object pool class which uses &id:oatpp::base::memory::PoolSharedObjectAllocator; to allocate objects.
|
||||
* @param NAME - name of the memory pool.
|
||||
* @param TYPE - type of the object.
|
||||
* @param CHUNK_SIZE - chunk size for &id:oatpp::base::memory::MemoryPool;.
|
||||
*/
|
||||
#define SHARED_OBJECT_POOL(NAME, TYPE, CHUNK_SIZE) \
|
||||
class NAME { \
|
||||
public: \
|
||||
@ -54,7 +60,12 @@ public: \
|
||||
\
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Macro to declare object pool class which uses &id:oatpp::base::memory::ThreadLocalPoolSharedObjectAllocator; to allocate objects.
|
||||
* @param NAME - name of the memory pool.
|
||||
* @param TYPE - type of the object.
|
||||
* @param CHUNK_SIZE - chunk size for &id:oatpp::base::memory::MemoryPool;.
|
||||
*/
|
||||
#define SHARED_OBJECT_POOL_THREAD_LOCAL(NAME, TYPE, CHUNK_SIZE) \
|
||||
class NAME { \
|
||||
public: \
|
||||
@ -78,7 +89,15 @@ public: \
|
||||
} \
|
||||
\
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Macro to declare: &id:oatpp::base::memory::MemoryPool; for object, plus class-specific operators
|
||||
* `static void* operator new(std::size_t sz)`, `static void operator delete(void* ptr, std::size_t sz)`,
|
||||
* `static void* operator new(std::size_t sz, void* entry)`, `static void operator delete(void* ptr, void* entry)`.
|
||||
* @param NAME - name of the memory pool.
|
||||
* @param TYPE - type of the object.
|
||||
* @param CHUNK_SIZE - chunk size for &id:oatpp::base::memory::MemoryPool;.
|
||||
*/
|
||||
#define OBJECT_POOL(POOL_NAME, TYPE, CHUNK_SIZE) \
|
||||
class POOL_NAME { \
|
||||
public: \
|
||||
@ -115,6 +134,14 @@ static void* operator new(std::size_t sz, void* entry) { \
|
||||
static void operator delete(void* ptr, void* entry) { \
|
||||
}
|
||||
|
||||
/**
|
||||
* Macro to declare: `thread_local` &id:oatpp::base::memory::MemoryPool; for object, plus class-specific operators
|
||||
* `static void* operator new(std::size_t sz)`, `static void operator delete(void* ptr, std::size_t sz)`,
|
||||
* `static void* operator new(std::size_t sz, void* entry)`, `static void operator delete(void* ptr, void* entry)`.
|
||||
* @param NAME - name of the memory pool.
|
||||
* @param TYPE - type of the object.
|
||||
* @param CHUNK_SIZE - chunk size for &id:oatpp::base::memory::MemoryPool;.
|
||||
*/
|
||||
#define OBJECT_POOL_THREAD_LOCAL(POOL_NAME, TYPE, CHUNK_SIZE) \
|
||||
class POOL_NAME { \
|
||||
public: \
|
||||
|
@ -1,25 +0,0 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "Runnable.hpp"
|
@ -1,41 +0,0 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* Project _____ __ ____ _ _
|
||||
* ( _ ) /__\ (_ _)_| |_ _| |_
|
||||
* )(_)( /(__)\ )( (_ _)(_ _)
|
||||
* (_____)(__)(__)(__) |_| |_|
|
||||
*
|
||||
*
|
||||
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef concurrency_Runnable_hpp
|
||||
#define concurrency_Runnable_hpp
|
||||
|
||||
|
||||
|
||||
namespace oatpp { namespace concurrency {
|
||||
|
||||
class Runnable {
|
||||
public:
|
||||
|
||||
virtual void run() = 0;
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* concurrency_Runnable_hpp */
|
@ -30,17 +30,40 @@
|
||||
|
||||
namespace oatpp { namespace concurrency {
|
||||
|
||||
/**
|
||||
* SpinLock implementation based on atomic.
|
||||
*/
|
||||
class SpinLock {
|
||||
public:
|
||||
/**
|
||||
* Convenience typedef for atomic bool.
|
||||
*/
|
||||
typedef std::atomic<bool> Atom;
|
||||
private:
|
||||
Atom* m_atom;
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor. Lock on construction.
|
||||
* @param atom - atomic boolean.
|
||||
*/
|
||||
SpinLock(Atom& atom);
|
||||
|
||||
/**
|
||||
* Non virtual destructor. Unlock on destruction.
|
||||
*/
|
||||
~SpinLock();
|
||||
|
||||
|
||||
/**
|
||||
* Spin-Lock using atomic boolean.
|
||||
* @param atom - atomic boolean.
|
||||
*/
|
||||
static void lock(Atom& atom);
|
||||
|
||||
/**
|
||||
* Spin-Unlock using atomic boolean.
|
||||
* @param atom - atomic boolean.
|
||||
*/
|
||||
static void unlock(Atom& atom);
|
||||
|
||||
};
|
||||
|
@ -30,17 +30,17 @@
|
||||
|
||||
namespace oatpp { namespace concurrency {
|
||||
|
||||
v_int32 Thread::setThreadAffinityToOneCpu(std::thread::native_handle_type nativeHandle, v_int32 cpuIndex) {
|
||||
v_int32 setThreadAffinityToOneCpu(std::thread::native_handle_type nativeHandle, v_int32 cpuIndex) {
|
||||
return setThreadAffinityToCpuRange(nativeHandle, cpuIndex, cpuIndex);
|
||||
}
|
||||
|
||||
v_int32 Thread::setThreadAffinityToCpuRange(std::thread::native_handle_type nativeHandle, v_int32 fromCpu, v_int32 toCpu) {
|
||||
v_int32 setThreadAffinityToCpuRange(std::thread::native_handle_type nativeHandle, v_int32 firstCpuIndex, v_int32 lastCpuIndex) {
|
||||
#if defined(_GNU_SOURCE)
|
||||
|
||||
cpu_set_t cpuset;
|
||||
CPU_ZERO(&cpuset);
|
||||
|
||||
for(v_int32 i = fromCpu; i <= toCpu; i++) {
|
||||
for(v_int32 i = firstCpuIndex; i <= lastCpuIndex; i++) {
|
||||
CPU_SET(i, &cpuset);
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ v_int32 Thread::setThreadAffinityToCpuRange(std::thread::native_handle_type nati
|
||||
#endif
|
||||
}
|
||||
|
||||
v_int32 Thread::calcHardwareConcurrency() {
|
||||
v_int32 calcHardwareConcurrency() {
|
||||
#if !defined(OATPP_THREAD_HARDWARE_CONCURRENCY)
|
||||
v_int32 concurrency = std::thread::hardware_concurrency();
|
||||
if(concurrency == 0) {
|
||||
@ -69,7 +69,7 @@ v_int32 Thread::calcHardwareConcurrency() {
|
||||
#endif
|
||||
}
|
||||
|
||||
v_int32 Thread::getHardwareConcurrency() {
|
||||
v_int32 getHardwareConcurrency() {
|
||||
static v_int32 concurrency = calcHardwareConcurrency();
|
||||
return concurrency;
|
||||
}
|
||||
|
@ -25,70 +25,37 @@
|
||||
#ifndef oatpp_concurrency_Thread_hpp
|
||||
#define oatpp_concurrency_Thread_hpp
|
||||
|
||||
#include "./Runnable.hpp"
|
||||
|
||||
#include "oatpp/core/base/memory/ObjectPool.hpp"
|
||||
#include "oatpp/core/base/Countable.hpp"
|
||||
|
||||
#include "oatpp/core/base/Environment.hpp"
|
||||
#include <thread>
|
||||
|
||||
namespace oatpp { namespace concurrency {
|
||||
|
||||
class Thread : public base::Countable {
|
||||
public:
|
||||
OBJECT_POOL(Thread_Pool, Thread, 32)
|
||||
SHARED_OBJECT_POOL(Shared_Thread_Pool, Thread, 32)
|
||||
private:
|
||||
static v_int32 calcHardwareConcurrency();
|
||||
public:
|
||||
|
||||
/**
|
||||
* Set thread affinity one thread
|
||||
*/
|
||||
static v_int32 setThreadAffinityToOneCpu(std::thread::native_handle_type nativeHandle, v_int32 cpuIndex);
|
||||
|
||||
/**
|
||||
* Set thread affinity [fromCpu..toCpu].
|
||||
* from and to indexes included
|
||||
*/
|
||||
static v_int32 setThreadAffinityToCpuRange(std::thread::native_handle_type nativeHandle, v_int32 fromCpu, v_int32 toCpu);
|
||||
|
||||
/**
|
||||
* returns OATPP_THREAD_HARDWARE_CONCURRENCY config value if set.
|
||||
* else return std::thread::hardware_concurrency()
|
||||
* else return 1
|
||||
*/
|
||||
static v_int32 getHardwareConcurrency();
|
||||
|
||||
private:
|
||||
std::thread m_thread;
|
||||
public:
|
||||
|
||||
Thread(const std::shared_ptr<Runnable>& runnable) {
|
||||
m_thread = std::thread([runnable]{
|
||||
runnable->run();
|
||||
});
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static std::shared_ptr<Thread> createShared(const std::shared_ptr<Runnable>& runnable){
|
||||
return Shared_Thread_Pool::allocateShared(runnable);
|
||||
}
|
||||
|
||||
void join(){
|
||||
m_thread.join();
|
||||
}
|
||||
|
||||
void detach(){
|
||||
m_thread.detach();
|
||||
}
|
||||
|
||||
std::thread* getStdThread() {
|
||||
return &m_thread;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Set thread affinity to one CPU.
|
||||
* @param nativeHandle - `std::thread::native_handle_type`.
|
||||
* @param cpuIndex - index of CPU.
|
||||
* @return - zero on success. Negative value on failure.
|
||||
* -1 if platform that runs application does not support this call.
|
||||
*/
|
||||
v_int32 setThreadAffinityToOneCpu(std::thread::native_handle_type nativeHandle, v_int32 cpuIndex);
|
||||
|
||||
/**
|
||||
* Set thread affinity [firstCpuIndex..lastCpuIndex].
|
||||
* @param nativeHandle - `std::thread::native_handle_type`.
|
||||
* @param firstCpuIndex - from CPU-index.
|
||||
* @param lastCpuIndex - to CPU-index included.
|
||||
* @return - zero on success. Negative value on failure.
|
||||
* -1 if platform that runs application does not support this call.
|
||||
*/
|
||||
v_int32 setThreadAffinityToCpuRange(std::thread::native_handle_type nativeHandle, v_int32 firstCpuIndex, v_int32 lastCpuIndex);
|
||||
|
||||
/**
|
||||
* Get hardware concurrency.
|
||||
* @return - OATPP_THREAD_HARDWARE_CONCURRENCY config value if set <br>
|
||||
* else return std::thread::hardware_concurrency() <br>
|
||||
* else return 1. <br>
|
||||
*/
|
||||
v_int32 getHardwareConcurrency();
|
||||
|
||||
}}
|
||||
|
||||
|
@ -29,15 +29,19 @@
|
||||
|
||||
namespace oatpp { namespace data {
|
||||
|
||||
/**
|
||||
* Represents I/O handle (ex.: file descriptor).
|
||||
*/
|
||||
typedef int v_io_handle;
|
||||
|
||||
/**
|
||||
* All I/O buffer operations (like read/write(buffer, size)) should return
|
||||
* v_io_size.
|
||||
* All I/O buffer operations (like read/write(buffer, size)) should return v_io_size. <br>
|
||||
*
|
||||
* Possible return values:
|
||||
* On Success - [1..max_int64]
|
||||
* On Error - IOError values.
|
||||
* <ul>
|
||||
* <li>**On Success** - [1..max_int64].</li>
|
||||
* <li>**On Error** - IOError values.</li>
|
||||
* </ul>
|
||||
*
|
||||
* All other values are considered to be a fatal error.
|
||||
* application should be terminated.
|
||||
|
@ -36,10 +36,6 @@ FIFOBuffer::FIFOBuffer(void* buffer, v_io_size bufferSize,
|
||||
, m_canRead(canRead)
|
||||
{}
|
||||
|
||||
FIFOBuffer::FIFOBuffer(void* buffer, v_io_size bufferSize)
|
||||
: FIFOBuffer(buffer, bufferSize, 0, 0, false)
|
||||
{}
|
||||
|
||||
void FIFOBuffer::setBufferPosition(data::v_io_size readPosition, data::v_io_size writePosition, bool canRead) {
|
||||
m_readPosition = readPosition;
|
||||
m_writePosition = writePosition;
|
||||
@ -367,11 +363,6 @@ SynchronizedFIFOBuffer::SynchronizedFIFOBuffer(void* buffer, v_io_size bufferSiz
|
||||
, m_atom(false)
|
||||
{}
|
||||
|
||||
SynchronizedFIFOBuffer::SynchronizedFIFOBuffer(void* buffer, v_io_size bufferSize)
|
||||
: m_fifo(buffer, bufferSize)
|
||||
, m_atom(false)
|
||||
{}
|
||||
|
||||
void SynchronizedFIFOBuffer::setBufferPosition(data::v_io_size readPosition, data::v_io_size writePosition, bool canRead) {
|
||||
oatpp::concurrency::SpinLock lock(m_atom);
|
||||
m_fifo.setBufferPosition(readPosition, writePosition, canRead);
|
||||
@ -387,10 +378,6 @@ data::v_io_size SynchronizedFIFOBuffer::availableToWrite() {
|
||||
return m_fifo.availableToWrite();
|
||||
}
|
||||
|
||||
data::v_io_size SynchronizedFIFOBuffer::getBufferSize() const {
|
||||
return m_fifo.getBufferSize();
|
||||
}
|
||||
|
||||
data::v_io_size SynchronizedFIFOBuffer::read(void *data, data::v_io_size count) {
|
||||
oatpp::concurrency::SpinLock lock(m_atom);
|
||||
return m_fifo.read(data, count);
|
||||
|
@ -45,17 +45,44 @@ private:
|
||||
bool m_canRead;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param buffer - pointer to buffer used for reads/writes.
|
||||
* @param bufferSize - buffer size.
|
||||
* @param readPosition - initial read position in buffer.
|
||||
* @param writePosition - initial write position in buffer.
|
||||
* @param canRead - flag to resolve ambiguity when readPosition == writePosition. If(readPosition == writePosition && canRead) then
|
||||
* &l:FIFOBuffer::availableToRead (); returns buffer size, and &l:FIFOBuffer::availableToWrite (); returns 0.
|
||||
*/
|
||||
FIFOBuffer(void* buffer, v_io_size bufferSize,
|
||||
data::v_io_size readPosition, data::v_io_size writePosition,
|
||||
bool canRead);
|
||||
|
||||
FIFOBuffer(void* buffer, v_io_size bufferSize);
|
||||
data::v_io_size readPosition = 0, data::v_io_size writePosition = 0,
|
||||
bool canRead = false);
|
||||
|
||||
/**
|
||||
* Set read and write positions in buffer.
|
||||
* @param readPosition - read position in buffer.
|
||||
* @param writePosition - write position in buffer.
|
||||
* @param canRead - flag to resolve ambiguity when readPosition == writePosition. If(readPosition == writePosition && canRead) then
|
||||
* &l:FIFOBuffer::availableToRead (); returns buffer size, and &l:FIFOBuffer::availableToWrite (); returns 0.
|
||||
*/
|
||||
void setBufferPosition(data::v_io_size readPosition, data::v_io_size writePosition, bool canRead);
|
||||
|
||||
/**
|
||||
* Amount of bytes currently available to read from buffer.
|
||||
* @return &id:oatpp::data::v_io_size;.
|
||||
*/
|
||||
data::v_io_size availableToRead() const;
|
||||
|
||||
/**
|
||||
* Amount of buffer space currently available for data writes.
|
||||
* @return &id:oatpp::data::v_io_size;.
|
||||
*/
|
||||
data::v_io_size availableToWrite() const;
|
||||
|
||||
/**
|
||||
* Get FIFOBuffer size.
|
||||
* @return - FIFOBuffer size.
|
||||
*/
|
||||
data::v_io_size getBufferSize() const;
|
||||
|
||||
/**
|
||||
@ -63,7 +90,6 @@ public:
|
||||
* @param data
|
||||
* @param count
|
||||
* @return [1..count], IOErrors.
|
||||
*
|
||||
*/
|
||||
data::v_io_size read(void *data, data::v_io_size count);
|
||||
|
||||
@ -75,7 +101,6 @@ public:
|
||||
*/
|
||||
data::v_io_size write(const void *data, data::v_io_size count);
|
||||
|
||||
|
||||
/**
|
||||
* call read and then write bytes read to output stream
|
||||
* @param stream
|
||||
@ -121,20 +146,54 @@ private:
|
||||
oatpp::concurrency::SpinLock::Atom m_atom;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param buffer - pointer to buffer used for reads/writes.
|
||||
* @param bufferSize - buffer size.
|
||||
* @param readPosition - initial read position in buffer.
|
||||
* @param writePosition - initial write position in buffer.
|
||||
* @param canRead - flag to resolve ambiguity when readPosition == writePosition. If(readPosition == writePosition && canRead) then
|
||||
* &l:SynchronizedFIFOBuffer::availableToRead (); returns buffer size, and &l:SynchronizedFIFOBuffer::availableToWrite (); returns 0.
|
||||
*/
|
||||
SynchronizedFIFOBuffer(void* buffer, v_io_size bufferSize,
|
||||
data::v_io_size readPosition, data::v_io_size writePosition,
|
||||
bool canRead);
|
||||
|
||||
SynchronizedFIFOBuffer(void* buffer, v_io_size bufferSize);
|
||||
data::v_io_size readPosition = 0, data::v_io_size writePosition = 0,
|
||||
bool canRead = false);
|
||||
|
||||
/**
|
||||
* Set read and write positions in buffer.
|
||||
* @param readPosition - read position in buffer.
|
||||
* @param writePosition - write position in buffer.
|
||||
* @param canRead - flag to resolve ambiguity when readPosition == writePosition. If(readPosition == writePosition && canRead) then
|
||||
* &l:SynchronizedFIFOBuffer::availableToRead (); returns buffer size, and &l:SynchronizedFIFOBuffer::availableToWrite (); returns 0.
|
||||
*/
|
||||
void setBufferPosition(data::v_io_size readPosition, data::v_io_size writePosition, bool canRead);
|
||||
|
||||
/**
|
||||
* Amount of bytes currently available to read from buffer.
|
||||
* @return &id:oatpp::data::v_io_size;.
|
||||
*/
|
||||
data::v_io_size availableToRead();
|
||||
|
||||
/**
|
||||
* Amount of buffer space currently available for data writes.
|
||||
* @return &id:oatpp::data::v_io_size;.
|
||||
*/
|
||||
data::v_io_size availableToWrite();
|
||||
|
||||
data::v_io_size getBufferSize() const;
|
||||
|
||||
/**
|
||||
* read up to count bytes from the buffer to data
|
||||
* @param data
|
||||
* @param count
|
||||
* @return [1..count], IOErrors.
|
||||
*/
|
||||
data::v_io_size read(void *data, data::v_io_size count);
|
||||
|
||||
/**
|
||||
* write up to count bytes from data to buffer
|
||||
* @param data
|
||||
* @param count
|
||||
* @return [1..count], IOErrors.
|
||||
*/
|
||||
data::v_io_size write(const void *data, data::v_io_size count);
|
||||
|
||||
/* No implementation of other methods */
|
||||
|
@ -25,7 +25,25 @@
|
||||
#include "IOBuffer.hpp"
|
||||
|
||||
namespace oatpp { namespace data{ namespace buffer {
|
||||
|
||||
const v_int32 IOBuffer::BUFFER_SIZE = 4096;
|
||||
|
||||
IOBuffer::IOBuffer()
|
||||
: m_entry(getBufferPool().obtain())
|
||||
{}
|
||||
|
||||
std::shared_ptr<IOBuffer> IOBuffer::createShared(){
|
||||
return Shared_IOBuffer_Pool::allocateShared();
|
||||
}
|
||||
|
||||
IOBuffer::~IOBuffer() {
|
||||
oatpp::base::memory::MemoryPool::free(m_entry);
|
||||
}
|
||||
|
||||
void* IOBuffer::getData(){
|
||||
return m_entry;
|
||||
}
|
||||
|
||||
v_int32 IOBuffer::getSize(){
|
||||
return BUFFER_SIZE;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
@ -28,44 +28,57 @@
|
||||
#include "oatpp/core/base/memory/ObjectPool.hpp"
|
||||
#include "oatpp/core/base/Countable.hpp"
|
||||
|
||||
|
||||
namespace oatpp { namespace data{ namespace buffer {
|
||||
|
||||
|
||||
/**
|
||||
* Predefined buffer implementation for I/O operations.
|
||||
* Allocates buffer bytes using &id:oatpp::base::memory::ThreadDistributedMemoryPool;.
|
||||
*/
|
||||
class IOBuffer : public oatpp::base::Countable {
|
||||
public:
|
||||
OBJECT_POOL(IOBuffer_Pool, IOBuffer, 32)
|
||||
SHARED_OBJECT_POOL(Shared_IOBuffer_Pool, IOBuffer, 32)
|
||||
public:
|
||||
static const v_int32 BUFFER_SIZE;
|
||||
/**
|
||||
* Buffer size constant.
|
||||
*/
|
||||
static constexpr v_int32 BUFFER_SIZE = 4096;
|
||||
private:
|
||||
// TODO FastAlloc
|
||||
static oatpp::base::memory::ThreadDistributedMemoryPool& getBufferPool(){
|
||||
static oatpp::base::memory::ThreadDistributedMemoryPool pool("IOBuffer_Buffer_Pool", BUFFER_SIZE, 32);
|
||||
static oatpp::base::memory::ThreadDistributedMemoryPool pool("IOBuffer_Buffer_Pool", BUFFER_SIZE, 16);
|
||||
return pool;
|
||||
}
|
||||
private:
|
||||
void* m_entry;
|
||||
public:
|
||||
IOBuffer()
|
||||
: m_entry(getBufferPool().obtain())
|
||||
{}
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
IOBuffer();
|
||||
public:
|
||||
|
||||
static std::shared_ptr<IOBuffer> createShared(){
|
||||
return Shared_IOBuffer_Pool::allocateShared();
|
||||
}
|
||||
|
||||
~IOBuffer() {
|
||||
oatpp::base::memory::MemoryPool::free(m_entry);
|
||||
}
|
||||
|
||||
void* getData(){
|
||||
return m_entry;
|
||||
}
|
||||
|
||||
v_int32 getSize(){
|
||||
return BUFFER_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create shared IOBuffer.
|
||||
* @return
|
||||
*/
|
||||
static std::shared_ptr<IOBuffer> createShared();
|
||||
|
||||
/**
|
||||
* Virtual destructor.
|
||||
*/
|
||||
~IOBuffer();
|
||||
|
||||
/**
|
||||
* Get pointer to buffer data.
|
||||
* @return
|
||||
*/
|
||||
void* getData();
|
||||
|
||||
/**
|
||||
* Get buffer size.
|
||||
* @return - should always return &l:IOBuffer::BUFFER_SIZE;.
|
||||
*/
|
||||
v_int32 getSize();
|
||||
|
||||
};
|
||||
|
||||
|
@ -23,3 +23,21 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "ObjectMapper.hpp"
|
||||
|
||||
namespace oatpp { namespace data { namespace mapping {
|
||||
|
||||
ObjectMapper::ObjectMapper(const Info& info)
|
||||
: m_info(info)
|
||||
{}
|
||||
|
||||
const ObjectMapper::Info& ObjectMapper::getInfo() const {
|
||||
return m_info;
|
||||
}
|
||||
|
||||
oatpp::String ObjectMapper::writeToString(const type::AbstractObjectWrapper& variant) const {
|
||||
auto stream = stream::ChunkedBuffer::createShared();
|
||||
write(stream, variant);
|
||||
return stream->toString();
|
||||
}
|
||||
|
||||
}}}
|
@ -36,45 +36,80 @@
|
||||
#include "oatpp/core/parser/ParsingError.hpp"
|
||||
|
||||
namespace oatpp { namespace data { namespace mapping {
|
||||
|
||||
|
||||
/**
|
||||
* Abstract ObjectMapper class.
|
||||
*/
|
||||
class ObjectMapper {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Metadata for ObjectMapper.
|
||||
*/
|
||||
class Info {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param _http_content_type
|
||||
*/
|
||||
Info(const char* _http_content_type)
|
||||
: http_content_type(_http_content_type)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Value for Content-Type http header when DTO is serialized via specified ObjectMapper.
|
||||
*/
|
||||
const char* const http_content_type;
|
||||
|
||||
};
|
||||
private:
|
||||
Info m_info;
|
||||
public:
|
||||
|
||||
ObjectMapper(const Info& info)
|
||||
: m_info(info)
|
||||
{}
|
||||
|
||||
const Info& getInfo() const {
|
||||
return m_info;
|
||||
}
|
||||
|
||||
virtual void write(const std::shared_ptr<oatpp::data::stream::OutputStream>& stream,
|
||||
const type::AbstractObjectWrapper& variant) const = 0;
|
||||
|
||||
virtual type::AbstractObjectWrapper read(oatpp::parser::Caret& caret,
|
||||
const type::Type* const type) const = 0;
|
||||
|
||||
oatpp::String writeToString(const type::AbstractObjectWrapper& variant) const {
|
||||
auto stream = stream::ChunkedBuffer::createShared();
|
||||
write(stream, variant);
|
||||
return stream->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param info - Metadata for ObjectMapper.
|
||||
*/
|
||||
ObjectMapper(const Info& info);
|
||||
|
||||
/**
|
||||
* Get ObjectMapper metadata.
|
||||
* @return - ObjectMapper metadata.
|
||||
*/
|
||||
const Info& getInfo() const;
|
||||
|
||||
/**
|
||||
* Serialize object to stream. Implement this method.
|
||||
* @param stream - &id:oatpp::data::stream::OutputStream; to serialize object to.
|
||||
* @param variant - Object to serialize.
|
||||
*/
|
||||
virtual void write(const std::shared_ptr<oatpp::data::stream::OutputStream>& stream,
|
||||
const type::AbstractObjectWrapper& variant) const = 0;
|
||||
|
||||
/**
|
||||
* Deserialize object. Implement this method.
|
||||
* @param caret - &id:oatpp::parser::Caret; over serialized buffer.
|
||||
* @param type - pointer to object type. See &id:oatpp::data::mapping::type::Type;.
|
||||
* @return - deserialized object wrapped in &id:oatpp::data::mapping::type::AbstractObjectWrapper;.
|
||||
*/
|
||||
virtual mapping::type::AbstractObjectWrapper read(oatpp::parser::Caret& caret,
|
||||
const mapping::type::Type* const type) const = 0;
|
||||
|
||||
/**
|
||||
* Serialize object to String.
|
||||
* @param variant - Object to serialize.
|
||||
* @return - serialized object as &id:oatpp::String;.
|
||||
*/
|
||||
oatpp::String writeToString(const type::AbstractObjectWrapper& variant) const;
|
||||
|
||||
/**
|
||||
* Deserialize object.
|
||||
* If nullptr is returned - check caret.getError()
|
||||
* @tparam Class
|
||||
* @param caret
|
||||
* @return
|
||||
* @tparam Class - object class.
|
||||
* @param caret - &id:oatpp::parser::Caret; over serialized buffer.
|
||||
* @return - deserialized Object.
|
||||
* @throws - depends on implementation.
|
||||
*/
|
||||
template<class Class>
|
||||
typename Class::ObjectWrapper readFromCaret(oatpp::parser::Caret& caret) const {
|
||||
@ -83,10 +118,12 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will throw on error
|
||||
* @tparam Class
|
||||
* @param str
|
||||
* @return
|
||||
* Deserialize object.
|
||||
* @tparam Class - object class.
|
||||
* @param str - serialized data.
|
||||
* @return - deserialized Object.
|
||||
* @throws - &id:oatpp::parser::ParsingError;
|
||||
* @throws - depends on implementation.
|
||||
*/
|
||||
template<class Class>
|
||||
typename Class::ObjectWrapper readFromString(const oatpp::String& str) const {
|
||||
|
@ -37,16 +37,27 @@
|
||||
namespace oatpp { namespace data { namespace mapping { namespace type {
|
||||
|
||||
namespace __class {
|
||||
|
||||
|
||||
/**
|
||||
* AbstractObject class.
|
||||
*/
|
||||
class AbstractObject {
|
||||
public:
|
||||
static const char* const CLASS_NAME;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Template for Object class of type T.
|
||||
* @tparam T - object type.
|
||||
*/
|
||||
template<class T>
|
||||
class Object : public AbstractObject {
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Get type describing this class.
|
||||
* @return - &id:oatpp::data::mapping::type::Type;
|
||||
*/
|
||||
static Type* getType(){
|
||||
static Type* type = static_cast<Type*>(T::Z__CLASS_GET_TYPE());
|
||||
return type;
|
||||
@ -55,7 +66,11 @@ namespace __class {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Base class for all DTO objects.
|
||||
* For more info about Data Transfer Object (DTO) see [Data Transfer Object (DTO)](https://oatpp.io/docs/components/dto/).
|
||||
*/
|
||||
class Object : public oatpp::base::Countable {
|
||||
public:
|
||||
typedef oatpp::data::mapping::type::String String;
|
||||
|
@ -48,6 +48,9 @@ namespace __class {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping-enables String is &id:oatpp::data::mapping::type::ObjectWrapper; over &id:oatpp::base::StrBuffer;
|
||||
*/
|
||||
class String : public oatpp::data::mapping::type::ObjectWrapper<oatpp::base::StrBuffer, __class::String> {
|
||||
public:
|
||||
String(const std::shared_ptr<oatpp::base::StrBuffer>& ptr, const type::Type* const valueType);
|
||||
@ -124,14 +127,22 @@ public:
|
||||
String operator + (const char* a, const String& b);
|
||||
String operator + (const String& b, const char* a);
|
||||
String operator + (const String& a, const String& b);
|
||||
|
||||
|
||||
/**
|
||||
* Template for primitive mapping-enabled types.
|
||||
* @tparam ValueType - type of the value ex.: v_int32.
|
||||
* @tparam Clazz - Class holding static class information.
|
||||
*/
|
||||
template<typename ValueType, class Clazz>
|
||||
class Primitive : public oatpp::base::Countable {
|
||||
public:
|
||||
OBJECT_POOL(Primitive_Type_Pool, Primitive, 32)
|
||||
SHARED_OBJECT_POOL(Shared_Primitive_Type_Pool, Primitive, 32)
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* ObjectWrapper template for &l:Primitive;.
|
||||
*/
|
||||
class ObjectWrapper : public oatpp::data::mapping::type::ObjectWrapper<Primitive, Clazz> {
|
||||
public:
|
||||
ObjectWrapper(const std::shared_ptr<Primitive>& ptr, const type::Type* const valueType)
|
||||
@ -205,35 +216,84 @@ private:
|
||||
ValueType m_value;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param value - initial value.
|
||||
*/
|
||||
Primitive(const ValueType& value)
|
||||
: m_value(value)
|
||||
{}
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Create shared primitive.
|
||||
* @param value - initial value.
|
||||
* @return - `std::shared_ptr` to Primitive.
|
||||
*/
|
||||
static std::shared_ptr<Primitive> createShared(const ValueType& value){
|
||||
return Shared_Primitive_Type_Pool::allocateShared(value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create shared primitive upcasted to &id:oatpp::base::Countable;.
|
||||
* @param value - initial value.
|
||||
* @return - `std::shared_ptr` to primitive upcasted to &id:oatpp::base::Countable;.
|
||||
*/
|
||||
static std::shared_ptr<Countable> createAbstract(const ValueType& value){
|
||||
return std::static_pointer_cast<Countable>(Shared_Primitive_Type_Pool::allocateShared(value));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set value.
|
||||
* @param value.
|
||||
*/
|
||||
void setValue(const ValueType& value) {
|
||||
m_value = value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get value.
|
||||
* @return - value.
|
||||
*/
|
||||
ValueType getValue() {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Int8 is an ObjectWrapper over &l:Primitive; and __class::Int8.
|
||||
*/
|
||||
typedef Primitive<v_int8, __class::Int8>::ObjectWrapper Int8;
|
||||
|
||||
/**
|
||||
* Int16 is an ObjectWrapper over &l:Primitive; and __class::Int16.
|
||||
*/
|
||||
typedef Primitive<v_int16, __class::Int16>::ObjectWrapper Int16;
|
||||
|
||||
/**
|
||||
* Int32 is an ObjectWrapper over &l:Primitive; and __class::Int32.
|
||||
*/
|
||||
typedef Primitive<v_int32, __class::Int32>::ObjectWrapper Int32;
|
||||
|
||||
/**
|
||||
* Int64 is an ObjectWrapper over &l:Primitive; and __class::Int64.
|
||||
*/
|
||||
typedef Primitive<v_int64, __class::Int64>::ObjectWrapper Int64;
|
||||
|
||||
/**
|
||||
* Float32 is an ObjectWrapper over &l:Primitive; and __class::Float32.
|
||||
*/
|
||||
typedef Primitive<v_float32, __class::Float32>::ObjectWrapper Float32;
|
||||
|
||||
/**
|
||||
* Float64 is an ObjectWrapper over &l:Primitive; and __class::Float64.
|
||||
*/
|
||||
typedef Primitive<v_float64, __class::Float64>::ObjectWrapper Float64;
|
||||
|
||||
/**
|
||||
* Boolean is an ObjectWrapper over &l:Primitive; and __class::Boolean.
|
||||
*/
|
||||
typedef Primitive<bool, __class::Boolean>::ObjectWrapper Boolean;
|
||||
|
||||
namespace __class {
|
||||
|
@ -37,7 +37,10 @@ namespace __class {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Type::Properties
|
||||
|
||||
void Type::Properties::pushBack(Property* property) {
|
||||
m_map.insert({property->name, property});
|
||||
m_list.push_back(property);
|
||||
@ -47,5 +50,55 @@ void Type::Properties::pushFrontAll(Properties* properties) {
|
||||
m_map.insert(properties->m_map.begin(), properties->m_map.end());
|
||||
m_list.insert(m_list.begin(), properties->m_list.begin(), properties->m_list.end());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Type::Property
|
||||
|
||||
Type::Property::Property(Properties* properties, v_int64 pOffset, const char* pName, Type* pType)
|
||||
: offset(pOffset)
|
||||
, name(pName)
|
||||
, type(pType)
|
||||
{
|
||||
properties->pushBack(this);
|
||||
}
|
||||
|
||||
void Type::Property::set(void* object, const AbstractObjectWrapper& value) {
|
||||
AbstractObjectWrapper* property = (AbstractObjectWrapper*)(((v_int64) object) + offset);
|
||||
*property = value;
|
||||
}
|
||||
|
||||
AbstractObjectWrapper Type::Property::get(void* object) {
|
||||
AbstractObjectWrapper* property = (AbstractObjectWrapper*)(((v_int64) object) + offset);
|
||||
return *property;
|
||||
}
|
||||
|
||||
AbstractObjectWrapper& Type::Property::getAsRef(void* object) {
|
||||
AbstractObjectWrapper* property = (AbstractObjectWrapper*)(((v_int64) object) + offset);
|
||||
return *property;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Type
|
||||
|
||||
Type::Type(const char* pName, const char* pNameQualifier)
|
||||
: name(pName)
|
||||
, nameQualifier(pNameQualifier)
|
||||
, creator(nullptr)
|
||||
, properties(nullptr)
|
||||
{}
|
||||
|
||||
Type::Type(const char* pName, const char* pNameQualifier, Creator pCreator)
|
||||
: name(pName)
|
||||
, nameQualifier(pNameQualifier)
|
||||
, creator(pCreator)
|
||||
, properties(nullptr)
|
||||
{}
|
||||
|
||||
Type::Type(const char* pName, const char* pNameQualifier, Creator pCreator, Properties* pProperties)
|
||||
: name(pName)
|
||||
, nameQualifier(pNameQualifier)
|
||||
, creator(pCreator)
|
||||
, properties(pProperties)
|
||||
{}
|
||||
|
||||
}}}}
|
||||
|
@ -36,20 +36,42 @@ namespace oatpp { namespace data { namespace mapping { namespace type {
|
||||
class Type; // FWD
|
||||
|
||||
namespace __class {
|
||||
/**
|
||||
* Void Object Class.
|
||||
*/
|
||||
class Void {
|
||||
public:
|
||||
/**
|
||||
* Name of the class - CLASS_NAME = "Void".
|
||||
*/
|
||||
static const char* const CLASS_NAME;
|
||||
|
||||
/**
|
||||
* Get class type information.
|
||||
* @return - &l:Type;
|
||||
*/
|
||||
static Type* getType();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* PolymorphicWrapper holds std::shared_ptr to object, object static type, plus object dynamic type information.
|
||||
* @tparam T - Object Type
|
||||
*/
|
||||
template <class T>
|
||||
class PolymorphicWrapper {
|
||||
protected:
|
||||
std::shared_ptr<T> m_ptr;
|
||||
public:
|
||||
/**
|
||||
* Static object type
|
||||
*/
|
||||
typedef T ObjectType;
|
||||
public:
|
||||
/**
|
||||
* PolymorphicWrapper has no static object Class info.
|
||||
* It treats object as of class &id:oatpp::data::mapping::type::__class::Void;.
|
||||
*/
|
||||
typedef __class::Void Class;
|
||||
public:
|
||||
|
||||
@ -133,7 +155,11 @@ public:
|
||||
explicit operator bool() const {
|
||||
return m_ptr.operator bool();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Value type information.
|
||||
* See &l:Type;.
|
||||
*/
|
||||
const Type* const valueType;
|
||||
|
||||
};
|
||||
@ -142,12 +168,23 @@ template<class T, class F>
|
||||
inline PolymorphicWrapper<T> static_wrapper_cast(const F& from){
|
||||
return PolymorphicWrapper<T>(std::static_pointer_cast<T>(from.getPtr()), from.valueType);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ObjectWrapper holds std::shared_ptr to object, object static type, object static class information, plus object dynamic type information.
|
||||
* @tparam T - Object type.
|
||||
* @tparam Clazz - Static Object class information.
|
||||
*/
|
||||
template <class T, class Clazz>
|
||||
class ObjectWrapper : public PolymorphicWrapper<T>{
|
||||
public:
|
||||
/**
|
||||
* Object type.
|
||||
*/
|
||||
typedef T ObjectType;
|
||||
public:
|
||||
/**
|
||||
* Static object class information.
|
||||
*/
|
||||
typedef Clazz Class;
|
||||
public:
|
||||
ObjectWrapper(const std::shared_ptr<T>& ptr, const type::Type* const valueType)
|
||||
@ -202,105 +239,162 @@ public:
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* PolymorphicWrapper over &id:oatpp::base::Countable; object.
|
||||
*/
|
||||
typedef PolymorphicWrapper<oatpp::base::Countable> AbstractObjectWrapper;
|
||||
|
||||
|
||||
/**
|
||||
* Object type data.
|
||||
*/
|
||||
class Type {
|
||||
public:
|
||||
typedef AbstractObjectWrapper (*Creator)();
|
||||
public:
|
||||
class Property; // FWD
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Object type properties table.
|
||||
*/
|
||||
class Properties {
|
||||
private:
|
||||
std::unordered_map<std::string, Property*> m_map;
|
||||
std::list<Property*> m_list;
|
||||
public:
|
||||
|
||||
void pushBack(Property* property);
|
||||
void pushFrontAll(Properties* properties);
|
||||
|
||||
|
||||
/**
|
||||
* get properties as unordered map for random access
|
||||
* Add property to the end of the list.
|
||||
* @param property
|
||||
*/
|
||||
void pushBack(Property* property);
|
||||
|
||||
/**
|
||||
* Add all properties to the beginning of the list.
|
||||
* @param properties
|
||||
*/
|
||||
void pushFrontAll(Properties* properties);
|
||||
|
||||
/**
|
||||
* Get properties as unordered map for random access.
|
||||
* @return reference to std::unordered_map of std::string to &id:oatpp::data::mapping::type::Type::Property;*.
|
||||
*/
|
||||
const std::unordered_map<std::string, Property*>& getMap() const {
|
||||
return m_map;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get properties in ordered way
|
||||
* Get properties in ordered way.
|
||||
* @return std::list of &id:oatpp::data::mapping::type::Type::Property;*.
|
||||
*/
|
||||
const std::list<Property*>& getList() const {
|
||||
return m_list;
|
||||
}
|
||||
|
||||
};
|
||||
//typedef std::unordered_map<std::string, Property*> Properties;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Class to map object properties.
|
||||
*/
|
||||
class Property {
|
||||
private:
|
||||
const v_int64 offset;
|
||||
public:
|
||||
|
||||
Property(Properties* properties, v_int64 pOffset, const char* pName, Type* pType)
|
||||
: offset(pOffset)
|
||||
, name(pName)
|
||||
, type(pType)
|
||||
{
|
||||
properties->pushBack(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param properties - &l:Type::Properties;*. to push this property to.
|
||||
* @param pOffset - memory offset of object field from object start address.
|
||||
* @param pName - name of the property.
|
||||
* @param pType - &l:Type; of the property.
|
||||
*/
|
||||
Property(Properties* properties, v_int64 pOffset, const char* pName, Type* pType);
|
||||
|
||||
/**
|
||||
* Property name.
|
||||
*/
|
||||
const char* const name;
|
||||
|
||||
/**
|
||||
* Property type.
|
||||
*/
|
||||
const Type* const type;
|
||||
|
||||
void set(void* object, const AbstractObjectWrapper& value) {
|
||||
AbstractObjectWrapper* property = (AbstractObjectWrapper*)(((v_int64) object) + offset);
|
||||
*property = value;
|
||||
}
|
||||
|
||||
AbstractObjectWrapper get(void* object) {
|
||||
AbstractObjectWrapper* property = (AbstractObjectWrapper*)(((v_int64) object) + offset);
|
||||
return *property;
|
||||
}
|
||||
|
||||
AbstractObjectWrapper& getAsRef(void* object) {
|
||||
AbstractObjectWrapper* property = (AbstractObjectWrapper*)(((v_int64) object) + offset);
|
||||
return *property;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value of object field mapped by this property.
|
||||
* @param object - object address.
|
||||
* @param value - value to set.
|
||||
*/
|
||||
void set(void* object, const AbstractObjectWrapper& value);
|
||||
|
||||
/**
|
||||
* Get value of object field mapped by this property.
|
||||
* @param object - object address.
|
||||
* @return - value of the field.
|
||||
*/
|
||||
AbstractObjectWrapper get(void* object);
|
||||
|
||||
/**
|
||||
* Get reference to ObjectWrapper of the object field.
|
||||
* @param object - object address.
|
||||
* @return - reference to ObjectWrapper of the object field.
|
||||
*/
|
||||
AbstractObjectWrapper& getAsRef(void* object);
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
Type(const char* pName, const char* pNameQualifier)
|
||||
: name(pName)
|
||||
, nameQualifier(pNameQualifier)
|
||||
, creator(nullptr)
|
||||
, properties(nullptr)
|
||||
{}
|
||||
|
||||
Type(const char* pName, const char* pNameQualifier, Creator pCreator)
|
||||
: name(pName)
|
||||
, nameQualifier(pNameQualifier)
|
||||
, creator(pCreator)
|
||||
, properties(nullptr)
|
||||
{}
|
||||
|
||||
Type(const char* pName, const char* pNameQualifier, Creator pCreator, Properties* pProperties)
|
||||
: name(pName)
|
||||
, nameQualifier(pNameQualifier)
|
||||
, creator(pCreator)
|
||||
, properties(pProperties)
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param pName - type name.
|
||||
* @param pNameQualifier - type name qualifier.
|
||||
*/
|
||||
Type(const char* pName, const char* pNameQualifier);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param pName - type name.
|
||||
* @param pNameQualifier - type name qualifier.
|
||||
* @param pCreator - function pointer of Creator - function to create instance of this type.
|
||||
*/
|
||||
Type(const char* pName, const char* pNameQualifier, Creator pCreator);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param pName - type name.
|
||||
* @param pNameQualifier - type name qualifier.
|
||||
* @param pCreator - function pointer of Creator - function to create instance of this type.
|
||||
* @param pProperties - pointer to type properties.
|
||||
*/
|
||||
Type(const char* pName, const char* pNameQualifier, Creator pCreator, Properties* pProperties);
|
||||
|
||||
/**
|
||||
* Type name.
|
||||
*/
|
||||
const char* const name;
|
||||
|
||||
/**
|
||||
* Type name qualifier.
|
||||
*/
|
||||
const char* const nameQualifier;
|
||||
|
||||
/**
|
||||
* List of type parameters - for templated types.
|
||||
*/
|
||||
std::list<Type*> params;
|
||||
|
||||
|
||||
/**
|
||||
* Creator - function to create instance of this type.
|
||||
*/
|
||||
const Creator creator;
|
||||
|
||||
|
||||
/**
|
||||
* Pointer to type properties.
|
||||
*/
|
||||
const Properties* const properties;
|
||||
|
||||
};
|
||||
|
@ -31,7 +31,9 @@
|
||||
namespace oatpp { namespace data { namespace share {
|
||||
|
||||
/**
|
||||
* MemoryLabel represent a part of the whole memory buffer refered by handle
|
||||
* MemoryLabel represent a part of the whole memory buffer refered by handle.
|
||||
* Advantage of MemoryLabel use is that you may just "label" some data instead of allocating buffer for it's copy.
|
||||
* You may allocate separate buffer for data copy later once you need it.
|
||||
*/
|
||||
class MemoryLabel {
|
||||
protected:
|
||||
@ -39,32 +41,66 @@ protected:
|
||||
p_char8 m_data;
|
||||
v_int32 m_size;
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Default constructor. Null MemoryLabel.
|
||||
*/
|
||||
MemoryLabel()
|
||||
: m_memoryHandle(nullptr)
|
||||
, m_data(nullptr)
|
||||
, m_size(0)
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param memHandle - memory handle. `std::shared_ptr` to buffer pointed by a memory label.
|
||||
* @param data - pointer to data.
|
||||
* @param size - size of the data in bytes.
|
||||
*/
|
||||
MemoryLabel(const std::shared_ptr<base::StrBuffer>& memHandle, p_char8 data, v_int32 size);
|
||||
|
||||
|
||||
/**
|
||||
* Get pointer to labeled data.
|
||||
* @return - pointer to data.
|
||||
*/
|
||||
p_char8 getData() const {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get data size.
|
||||
* @return - size of the data.
|
||||
*/
|
||||
v_int32 getSize() const {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get memory handle which this memory label holds.
|
||||
* @return - `std::shared_ptr` to &id:oatpp::base::StrBuffer;.
|
||||
*/
|
||||
std::shared_ptr<base::StrBuffer> getMemoryHandle() const {
|
||||
return m_memoryHandle;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if labeled data equals to data specified.
|
||||
* Data is compared using &id:oatpp::base::StrBuffer::equals;.
|
||||
* @param data - data to compare with labeled data.
|
||||
* @return - `true` if equals.
|
||||
*/
|
||||
bool equals(const char* data) const {
|
||||
v_int32 size = (v_int32) std::strlen(data);
|
||||
return m_size == size && base::StrBuffer::equals(m_data, data, m_size);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if labeled data equals to data specified.
|
||||
* Data is compared using &id:oatpp::base::StrBuffer::equals;.
|
||||
* @param data - data to compare with labeled data.
|
||||
* @param size - data size.
|
||||
* @return - `true` if equals.
|
||||
*/
|
||||
bool equals(const void* data, v_int32 size) const {
|
||||
return m_size == size && base::StrBuffer::equals(m_data, data, m_size);
|
||||
}
|
||||
|
@ -34,7 +34,18 @@ const data::v_io_size ChunkedBuffer::CHUNK_ENTRY_SIZE_INDEX_SHIFT = 11;
|
||||
const data::v_io_size ChunkedBuffer::CHUNK_ENTRY_SIZE =
|
||||
(1 << ChunkedBuffer::CHUNK_ENTRY_SIZE_INDEX_SHIFT);
|
||||
const data::v_io_size ChunkedBuffer::CHUNK_CHUNK_SIZE = 32;
|
||||
|
||||
|
||||
ChunkedBuffer::ChunkedBuffer()
|
||||
: m_size(0)
|
||||
, m_chunkPos(0)
|
||||
, m_firstEntry(nullptr)
|
||||
, m_lastEntry(nullptr)
|
||||
{}
|
||||
|
||||
ChunkedBuffer::~ChunkedBuffer() {
|
||||
clear();
|
||||
}
|
||||
|
||||
ChunkedBuffer::ChunkEntry* ChunkedBuffer::obtainNewEntry(){
|
||||
auto result = new ChunkEntry(getSegemntPool().obtain(), nullptr);
|
||||
if(m_firstEntry == nullptr) {
|
||||
@ -187,19 +198,22 @@ oatpp::String ChunkedBuffer::getSubstring(data::v_io_size pos,
|
||||
readSubstring(str->getData(), pos, count);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
// TODO - refactor this.
|
||||
bool ChunkedBuffer::flushToStream(const std::shared_ptr<OutputStream>& stream){
|
||||
data::v_io_size pos = m_size;
|
||||
auto curr = m_firstEntry;
|
||||
while (pos > 0) {
|
||||
if(pos > CHUNK_ENTRY_SIZE) {
|
||||
auto res = stream->write(curr->chunk, CHUNK_ENTRY_SIZE);
|
||||
// TODO handle I/O errors.
|
||||
if(res != CHUNK_ENTRY_SIZE) {
|
||||
return false;
|
||||
}
|
||||
pos -= res;
|
||||
} else {
|
||||
auto res = stream->write(curr->chunk, pos);
|
||||
// TODO handle I/O errors.
|
||||
if(res != pos) {
|
||||
return false;
|
||||
}
|
||||
|
@ -31,7 +31,10 @@
|
||||
#include "oatpp/core/async/Coroutine.hpp"
|
||||
|
||||
namespace oatpp { namespace data{ namespace stream {
|
||||
|
||||
|
||||
/**
|
||||
* Buffer wich can grow by chunks and implements &id:oatpp::data::stream::OutputStream; interface.
|
||||
*/
|
||||
class ChunkedBuffer : public oatpp::base::Countable, public OutputStream, public std::enable_shared_from_this<ChunkedBuffer> {
|
||||
public:
|
||||
static const char* ERROR_ASYNC_FAILED_TO_WRITE_ALL_DATA;
|
||||
@ -126,54 +129,102 @@ private:
|
||||
|
||||
public:
|
||||
|
||||
ChunkedBuffer()
|
||||
: m_size(0)
|
||||
, m_chunkPos(0)
|
||||
, m_firstEntry(nullptr)
|
||||
, m_lastEntry(nullptr)
|
||||
{}
|
||||
|
||||
~ChunkedBuffer() {
|
||||
clear();
|
||||
}
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
ChunkedBuffer();
|
||||
|
||||
/**
|
||||
* Virtual Destructor.
|
||||
*/
|
||||
~ChunkedBuffer();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Deleted copy constructor.
|
||||
*/
|
||||
ChunkedBuffer(const ChunkedBuffer&) = delete;
|
||||
|
||||
ChunkedBuffer& operator=(const ChunkedBuffer&) = delete;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Create shared ChunkedBuffer.
|
||||
* @return `std::shared_ptr` to ChunkedBuffer.
|
||||
*/
|
||||
static std::shared_ptr<ChunkedBuffer> createShared(){
|
||||
return Shared_ChunkedBuffer_Pool::allocateShared();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write data to ChunkedBuffer. Implementation of &id:oatpp::data::stream::OutputStream::write; method.
|
||||
* @param data - data to write.
|
||||
* @param count - size of data in bytes.
|
||||
* @return - actual number of bytes written.
|
||||
*/
|
||||
data::v_io_size write(const void *data, data::v_io_size count) override;
|
||||
|
||||
data::v_io_size readSubstring(void *buffer,
|
||||
data::v_io_size pos,
|
||||
data::v_io_size count);
|
||||
/**
|
||||
* Read part of ChunkedBuffer to buffer.
|
||||
* @param buffer - buffer to write data to.
|
||||
* @param pos - starting position in ChunkedBuffer to read data from.
|
||||
* @param count - number of bytes to read.
|
||||
* @return - actual number of bytes read from ChunkedBuffer and written to buffer.
|
||||
*/
|
||||
data::v_io_size readSubstring(void *buffer, data::v_io_size pos, data::v_io_size count);
|
||||
|
||||
/**
|
||||
* return substring of the data written to stream; NOT NULL
|
||||
* Create &id:oatpp::String; from part of ChunkedBuffer.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create &id:oatpp::String; from part of ChunkedBuffer.
|
||||
* @param pos - starting position in ChunkedBuffer.
|
||||
* @param count - size of bytes to write to substring.
|
||||
* @return - &id:oatpp::String;
|
||||
*/
|
||||
oatpp::String getSubstring(data::v_io_size pos, data::v_io_size count);
|
||||
|
||||
/**
|
||||
* return data written to stream as oatpp::String; NOT NULL
|
||||
* Create &id:oatpp::String; from all data in ChunkedBuffer.
|
||||
* @return - &id:oatpp::String;
|
||||
*/
|
||||
oatpp::String toString() {
|
||||
return getSubstring(0, m_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write all data from ChunkedBuffer to &id:oatpp::data::stream::OutputStream;.
|
||||
* ChunkedBuffer will not be cleared during this call!
|
||||
* @param stream - &id:oatpp::data::stream::OutputStream; stream to write all data to.
|
||||
* @return - `true` if no errors occured. **will be refactored to return actual amount of bytes flushed**.
|
||||
*/
|
||||
bool flushToStream(const std::shared_ptr<OutputStream>& stream);
|
||||
|
||||
/**
|
||||
* Write all data from ChunkedBuffer to &id:oatpp::data::stream::OutputStream; in asynchronous manner.
|
||||
* @param parentCoroutine - caller coroutine. &id:oatpp::async::AbstractCoroutine;.
|
||||
* @param actionOnFinish - action to do once finished. &id:oatpp::async::Action;.
|
||||
* @param stream - &id:oatpp::data::stream::OutputStream; stream to write all data to.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
oatpp::async::Action flushToStreamAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
|
||||
const oatpp::async::Action& actionOnFinish,
|
||||
const std::shared_ptr<OutputStream>& stream);
|
||||
|
||||
std::shared_ptr<Chunks> getChunks();
|
||||
|
||||
/**
|
||||
* Get number of bytes written to ChunkedBuffer.
|
||||
* @return - number of bytes written to ChunkedBuffer.
|
||||
*/
|
||||
data::v_io_size getSize();
|
||||
|
||||
/**
|
||||
* Clear data in ChunkedBuffer.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
};
|
||||
|
@ -28,14 +28,31 @@
|
||||
#include "./Stream.hpp"
|
||||
|
||||
namespace oatpp { namespace data{ namespace stream {
|
||||
|
||||
|
||||
/**
|
||||
* Stream writer delegate which can write data to stream provided.
|
||||
*/
|
||||
class WriterDelegate {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Write data to provided stream.
|
||||
* @param stream - stream to write data to.
|
||||
* @return - actual number of bytes written to stream. &id:oatpp::data::v_io_size;.
|
||||
*/
|
||||
virtual data::v_io_size writeToStream(const std::shared_ptr<OutputStream>& stream) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Stream reader delegate which can read data from stream provided.
|
||||
*/
|
||||
class ReaderDelegate {
|
||||
public:
|
||||
/**
|
||||
* Read data from provided stream.
|
||||
* @param stream - stream to read data from.
|
||||
* @return - actual number of bytes read. &id:oatpp::data::v_io_size;.
|
||||
*/
|
||||
virtual data::v_io_size readFromStream(const std::shared_ptr<InputStream>& stream) = 0;
|
||||
};
|
||||
|
||||
|
@ -51,45 +51,110 @@ public:
|
||||
static const char* const ERROR_ASYNC_UNKNOWN_CODE;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Output Stream.
|
||||
*/
|
||||
class OutputStream {
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Write data to stream up to count bytes, and return number of bytes actually written
|
||||
* It is a legal case if return result < count. Caller should handle this!
|
||||
* @param data - data to write.
|
||||
* @param count - number of bytes to write.
|
||||
* @return - actual number of bytes written. &id:oatpp::data::v_io_size;.
|
||||
*/
|
||||
virtual data::v_io_size write(const void *data, data::v_io_size count) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Same as `write((p_char8)data, std::strlen(data));`.
|
||||
* @param data - data to write.
|
||||
* @return - actual number of bytes written. &id:oatpp::data::v_io_size;.
|
||||
*/
|
||||
data::v_io_size write(const char* data){
|
||||
return write((p_char8)data, std::strlen(data));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Same as `write(str->getData(), str->getSize());`
|
||||
* @param str - data to write.
|
||||
* @return - actual number of bytes written. &id:oatpp::data::v_io_size;.
|
||||
*/
|
||||
data::v_io_size write(const oatpp::String& str){
|
||||
return write(str->getData(), str->getSize());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Same as `write(&c, 1);`.
|
||||
* @param c - one char to write.
|
||||
* @return - actual number of bytes written. &id:oatpp::data::v_io_size;.
|
||||
*/
|
||||
data::v_io_size writeChar(v_char8 c){
|
||||
return write(&c, 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert value to string and write to stream.
|
||||
* @param value
|
||||
* @return - actual number of bytes written. &id:oatpp::data::v_io_size;. <br>
|
||||
* **Careful!!!** - use this method on your own risk as it's hard to understand if all data was written to stream.
|
||||
*/
|
||||
data::v_io_size writeAsString(v_int32 value);
|
||||
|
||||
/**
|
||||
* Convert value to string and write to stream.
|
||||
* @param value
|
||||
* @return - actual number of bytes written. &id:oatpp::data::v_io_size;. <br>
|
||||
* **Careful!!!** - use this method on your own risk as it's hard to understand if all data was written to stream.
|
||||
*/
|
||||
data::v_io_size writeAsString(v_int64 value);
|
||||
|
||||
/**
|
||||
* Convert value to string and write to stream.
|
||||
* @param value
|
||||
* @return - actual number of bytes written. &id:oatpp::data::v_io_size;. <br>
|
||||
* **Careful!!!** - use this method on your own risk as it's hard to understand if all data was written to stream.
|
||||
*/
|
||||
data::v_io_size writeAsString(v_float32 value);
|
||||
|
||||
/**
|
||||
* Convert value to string and write to stream.
|
||||
* @param value
|
||||
* @return - actual number of bytes written. &id:oatpp::data::v_io_size;. <br>
|
||||
* **Careful!!!** - use this method on your own risk as it's hard to understand if all data was written to stream.
|
||||
*/
|
||||
data::v_io_size writeAsString(v_float64 value);
|
||||
|
||||
/**
|
||||
* Convert value to string and write to stream.
|
||||
* @param value
|
||||
* @return - actual number of bytes written. &id:oatpp::data::v_io_size;. <br>
|
||||
* **Careful!!!** - use this method on your own risk as it's hard to understand if all data was written to stream.
|
||||
*/
|
||||
data::v_io_size writeAsString(bool value);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Input Stream.
|
||||
*/
|
||||
class InputStream {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Read data from stream up to count bytes, and return number of bytes actually read
|
||||
* It is a legal case if return result < count. Caller should handle this!
|
||||
* @param data - buffer to read dat to.
|
||||
* @param count - size of the buffer.
|
||||
* @return - actual number of bytes read.
|
||||
*/
|
||||
virtual data::v_io_size read(void *data, data::v_io_size count) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* I/O Stream.
|
||||
*/
|
||||
class IOStream : public InputStream, public OutputStream {
|
||||
public:
|
||||
typedef data::v_io_size v_size;
|
||||
|
@ -22,6 +22,10 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/**[info]
|
||||
* This file contains source code for basic helper macros used for code-generator.
|
||||
*/
|
||||
|
||||
#ifndef oatpp_macro_ForEach_hpp
|
||||
#define oatpp_macro_ForEach_hpp
|
||||
|
||||
|
@ -22,6 +22,19 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/**[info]
|
||||
* This file contains source code for `OATPP_CODEGEN_BEGIN(NAME)` and `OATPP_CODEGEN_END(NAME)` macros. <br>
|
||||
* <br>
|
||||
*
|
||||
* More about use of `OATPP_CODEGEN_BEGIN` and `OATPP_CODEGEN_BEGIN` see: <br>
|
||||
* <ul>
|
||||
* <li>[ApiController component](https://oatpp.io/docs/components/api-controller/)</li>
|
||||
* <li>[ApiClient component](https://oatpp.io/docs/components/api-client/)</li>
|
||||
* <li>[Data Transfer Object(DTO) component](https://oatpp.io/docs/components/dto/)</li>
|
||||
* </ul>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef codegen_hpp
|
||||
#define codegen_hpp
|
||||
|
||||
|
@ -22,6 +22,18 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/**[info]
|
||||
* This file contains source code for `OATPP_CREATE_COMPONENT` and `OATPP_COMPONENT` macros which are part of
|
||||
* oatpp Dependency Injection (DI) framework. <br>
|
||||
* <br>
|
||||
* For usage examples see example-projects:
|
||||
* <ul>
|
||||
* <li>[CRUD - example](https://github.com/oatpp/example-crud)</li>
|
||||
* <li>[HLS Media Stream - example](https://github.com/oatpp/example-hls-media-stream)</li>
|
||||
* <li>[Async API - example](https://github.com/oatpp/example-async-api)</li>
|
||||
* </ul>
|
||||
*/
|
||||
|
||||
#ifndef oatpp_macro_component_hpp
|
||||
#define oatpp_macro_component_hpp
|
||||
|
||||
@ -62,10 +74,21 @@ OATPP_MACRO_COMPONENT_(X, TYPE, NAME, LIST)
|
||||
#define OATPP_MACRO_COMPONENT___(TYPE, NAME, LIST) \
|
||||
OATPP_MACRO_COMPONENT__(OATPP_MACRO_HAS_ARGS LIST, TYPE, NAME, LIST)
|
||||
|
||||
/**
|
||||
* Inject component. Create variable of type=TYPE and name=NAME and assign registered component to it.
|
||||
* @param TYPE - type of the component.
|
||||
* @param NAME - name of the variable.
|
||||
* @param QUALIFIER_NAME - qualifier name is needed if there are multiple components registered of the same type.
|
||||
* If there is one component registered only then TYPE info is enought to search for component.
|
||||
*/
|
||||
#define OATPP_COMPONENT(TYPE, NAME, ...) \
|
||||
OATPP_MACRO_COMPONENT___(TYPE, NAME, (__VA_ARGS__))
|
||||
|
||||
|
||||
/**
|
||||
* Create component that then can be injected in other application classes.
|
||||
* @param TYPE - type of the component.
|
||||
* @param NAME - name of the component field.
|
||||
*/
|
||||
#define OATPP_CREATE_COMPONENT(TYPE, NAME) \
|
||||
oatpp::base::Environment::Component<TYPE> NAME = oatpp::base::Environment::Component<TYPE>
|
||||
|
||||
|
@ -43,27 +43,70 @@ public:
|
||||
static const char* const ERROR_NAME_EXPECTED;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Class to label parsing data.
|
||||
*/
|
||||
class Label {
|
||||
private:
|
||||
Caret* m_caret;
|
||||
v_int32 m_start;
|
||||
v_int32 m_end;
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param caret.
|
||||
*/
|
||||
Label(Caret* caret);
|
||||
|
||||
|
||||
/**
|
||||
* Set current caret position as a starting point for label.
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* Fix current caret position as an end point for label.
|
||||
*/
|
||||
void end();
|
||||
|
||||
/**
|
||||
* Get pointer to a labeled data.
|
||||
* @return
|
||||
*/
|
||||
p_char8 getData();
|
||||
|
||||
/**
|
||||
* Get size of labeled data.
|
||||
* @return
|
||||
*/
|
||||
v_int32 getSize();
|
||||
|
||||
/**
|
||||
* Create &id:oatpp::String; from labeled data.
|
||||
* @param saveAsOwnData - `true` - allocate new memory block for string. `false` - string will point to the same data as label.
|
||||
* @return - &id:oatpp::String;.
|
||||
*/
|
||||
oatpp::String toString(bool saveAsOwnData);
|
||||
|
||||
/**
|
||||
* Same as`toString(true).`
|
||||
* @return - &id:oatpp::String;.
|
||||
*/
|
||||
oatpp::String toString();
|
||||
|
||||
/**
|
||||
* Create `std::string` from labeled data.
|
||||
* @return - `std::string`.
|
||||
*/
|
||||
std::string std_str();
|
||||
|
||||
explicit operator bool() const;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Caret state saver guard.
|
||||
*/
|
||||
class StateSaveGuard {
|
||||
private:
|
||||
Caret& m_caret;
|
||||
@ -72,11 +115,33 @@ public:
|
||||
v_int32 m_savedErrorCode;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param caret.
|
||||
*/
|
||||
StateSaveGuard(Caret& caret);
|
||||
|
||||
/**
|
||||
* Destructor. Restore saved state.
|
||||
*/
|
||||
~StateSaveGuard();
|
||||
|
||||
/**
|
||||
* Get caret saved position.
|
||||
* @return
|
||||
*/
|
||||
v_int32 getSavedPosition();
|
||||
|
||||
/**
|
||||
* Get caret saved error message.
|
||||
* @return
|
||||
*/
|
||||
const char* getSavedErrorMessage();
|
||||
|
||||
/**
|
||||
* Get caret saved error code.
|
||||
* @return
|
||||
*/
|
||||
v_int32 getSavedErrorCode();
|
||||
|
||||
};
|
||||
|
@ -35,26 +35,101 @@
|
||||
#include <string>
|
||||
|
||||
namespace oatpp { namespace utils { namespace conversion {
|
||||
|
||||
|
||||
/**
|
||||
* String to 32-bit integer.
|
||||
* @param str - string as `const char*`.
|
||||
* @return - 32-bit integer value.
|
||||
*/
|
||||
v_int32 strToInt32(const char* str);
|
||||
|
||||
/**
|
||||
* String to 32-bit integer.
|
||||
* @param str - string as `oatpp::String`.
|
||||
* @param success - out parameter. `true` if operation was successful. `false` otherwise.
|
||||
* @return - 32-bit integer value.
|
||||
*/
|
||||
v_int32 strToInt32(const oatpp::String& str, bool& success);
|
||||
|
||||
/**
|
||||
* String to 64-bit integer.
|
||||
* @param str - string as `const char*`.
|
||||
* @return - 64-bit integer value.
|
||||
*/
|
||||
v_int64 strToInt64(const char* str);
|
||||
|
||||
/**
|
||||
* String to 64-bit integer.
|
||||
* @param str - string as `oatpp::String`.
|
||||
* @param success - out parameter. `true` if operation was successful. `false` otherwise.
|
||||
* @return - 64-bit integer value.
|
||||
*/
|
||||
v_int64 strToInt64(const oatpp::String& str, bool& success);
|
||||
|
||||
|
||||
/**
|
||||
* Convert 32-bit integer to it's string representation.
|
||||
* @param value - 32-bit integer value.
|
||||
* @param data - buffer to write data to.
|
||||
* @return - length of the resultant string.
|
||||
*/
|
||||
v_int32 int32ToCharSequence(v_int32 value, p_char8 data);
|
||||
|
||||
/**
|
||||
* Convert 64-bit integer to it's string representation.
|
||||
* @param value - 64-bit integer value.
|
||||
* @param data - buffer to write data to.
|
||||
* @return - length of the resultant string.
|
||||
*/
|
||||
v_int32 int64ToCharSequence(v_int64 value, p_char8 data);
|
||||
|
||||
|
||||
/**
|
||||
* Convert 32-bit integer to it's string representation.
|
||||
* @param value - 32-bit integer value.
|
||||
* @return - value as `oatpp::String`
|
||||
*/
|
||||
oatpp::String int32ToStr(v_int32 value);
|
||||
|
||||
/**
|
||||
* Convert 64-bit integer to it's string representation.
|
||||
* @param value - 64-bit integer value.
|
||||
* @return - value as `oatpp::String`
|
||||
*/
|
||||
oatpp::String int64ToStr(v_int64 value);
|
||||
|
||||
|
||||
/**
|
||||
* Convert 32-bit integer to it's string representation.
|
||||
* @param value - 32-bit integer value.
|
||||
* @return - value as `std::string`
|
||||
*/
|
||||
std::string int32ToStdStr(v_int32 value);
|
||||
|
||||
/**
|
||||
* Convert 64-bit integer to it's string representation.
|
||||
* @param value - 64-bit integer value.
|
||||
* @return - value as `std::string`
|
||||
*/
|
||||
std::string int64ToStdStr(v_int64 value);
|
||||
|
||||
|
||||
/**
|
||||
* Write value of primitive type (int, float, etc.) as it's string representation with pattern.
|
||||
* @tparam T - primitive value type (int, float, etc.).
|
||||
* @param value - actual value.
|
||||
* @param data - buffer to write data to.
|
||||
* @param pattern - pattern as for `sprintf`.
|
||||
* @return - length of the resultant string.
|
||||
*/
|
||||
template<typename T>
|
||||
v_int32 primitiveToCharSequence(T value, p_char8 data, const char* pattern){
|
||||
return sprintf((char*)data, pattern, value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write value of primitive type (int, float, etc.) as it's string representation with pattern.
|
||||
* @tparam T - primitive value type (int, float, etc.).
|
||||
* @param value - actual value.
|
||||
* @param pattern - pattern as for `sprintf`.
|
||||
* @return - length of the resultant string.
|
||||
*/
|
||||
template<typename T>
|
||||
oatpp::String primitiveToStr(T value, const char* pattern){
|
||||
v_char8 buff [100];
|
||||
@ -64,21 +139,88 @@ namespace oatpp { namespace utils { namespace conversion {
|
||||
}
|
||||
return oatpp::String::empty();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* String to 32-bit float.
|
||||
* @param str - string as `const char*`.
|
||||
* @return - 32-bit float value.
|
||||
*/
|
||||
v_float32 strToFloat32(const char* str);
|
||||
|
||||
/**
|
||||
* String to 32-bit float.
|
||||
* @param str - string as `oatpp::String`.
|
||||
* @param success - out parameter. `true` if operation was successful. `false` otherwise.
|
||||
* @return - 32-bit float value.
|
||||
*/
|
||||
v_float32 strToFloat32(const oatpp::String& str, bool& success);
|
||||
|
||||
/**
|
||||
* String to 64-bit float.
|
||||
* @param str - string as `const char*`.
|
||||
* @return - 64-bit float value.
|
||||
*/
|
||||
v_float64 strToFloat64(const char* str);
|
||||
|
||||
/**
|
||||
* String to 64-bit float.
|
||||
* @param str - string as `oatpp::String`.
|
||||
* @param success - out parameter. `true` if operation was successful. `false` otherwise.
|
||||
* @return - 64-bit float value.
|
||||
*/
|
||||
v_float64 strToFloat64(const oatpp::String& str, bool& success);
|
||||
|
||||
|
||||
/**
|
||||
* Convert 32-bit float to it's string representation.
|
||||
* @param value - 32-bit float value.
|
||||
* @param data - buffer to write data to.
|
||||
* @return - length of the resultant string.
|
||||
*/
|
||||
v_int32 float32ToCharSequence(v_float32 value, p_char8 data);
|
||||
|
||||
/**
|
||||
* Convert 64-bit float to it's string representation.
|
||||
* @param value - 64-bit float value.
|
||||
* @param data - buffer to write data to.
|
||||
* @return - length of the resultant string.
|
||||
*/
|
||||
v_int32 float64ToCharSequence(v_float64 value, p_char8 data);
|
||||
|
||||
|
||||
/**
|
||||
* Convert 32-bit float to it's string representation.
|
||||
* @param value - 32-bit float value.
|
||||
* @return - value as `oatpp::String`
|
||||
*/
|
||||
oatpp::String float32ToStr(v_float32 value);
|
||||
|
||||
/**
|
||||
* Convert 64-bit float to it's string representation.
|
||||
* @param value - 64-bit float value.
|
||||
* @return - value as `oatpp::String`
|
||||
*/
|
||||
oatpp::String float64ToStr(v_float64 value);
|
||||
|
||||
|
||||
/**
|
||||
* Convert boolean to it's string representation.
|
||||
* @param value - boolean value.
|
||||
* @return - value as `oatpp::String`;
|
||||
*/
|
||||
oatpp::String boolToStr(bool value);
|
||||
|
||||
/**
|
||||
* parse string to boolean value.
|
||||
* @param str - string to parse.
|
||||
* @param success - out parameter. `true` if operation was successful. `false` otherwise.
|
||||
* @return - boolean value.
|
||||
*/
|
||||
bool strToBool(const oatpp::String& str, bool& success);
|
||||
|
||||
|
||||
/**
|
||||
* Write value of oatpp-primitive type (oatpp::Int32, oatpp::Int64, oatpp::Boolean, etc.) as it's string representation.
|
||||
* @tparam T - oatpp-primitive type (oatpp::Int32, oatpp::Int64, oatpp::Boolean, etc.).
|
||||
* @param primitive - ObjectWrapper.
|
||||
* @return - value as string.
|
||||
*/
|
||||
template<class T>
|
||||
oatpp::String
|
||||
primitiveToStr(const oatpp::data::mapping::type::PolymorphicWrapper<T>& primitive) {
|
||||
|
@ -28,13 +28,23 @@
|
||||
#include "oatpp/core/Types.hpp"
|
||||
|
||||
namespace oatpp { namespace encoding {
|
||||
|
||||
|
||||
/**
|
||||
* Base64 - encoder/decoder.
|
||||
*/
|
||||
class Base64 {
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* DecodingError.
|
||||
*/
|
||||
class DecodingError : public std::runtime_error {
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param message - error message.
|
||||
*/
|
||||
DecodingError(const char* message)
|
||||
:std::runtime_error(message)
|
||||
{}
|
||||
@ -47,57 +57,103 @@ private:
|
||||
|
||||
public:
|
||||
/**
|
||||
* Alphabet is array of 65 chars. 64 chars encoding chars, and 65th padding char
|
||||
* Standard base64 Alphabet - `['A'-'Z', 'a'-'z', '0'-'9', '+', '/', '=']`.
|
||||
* Alphabet is array of 65 chars. 64 chars encoding chars, and 65th padding char.<br>
|
||||
*/
|
||||
static const char* const ALPHABET_BASE64;
|
||||
|
||||
/**
|
||||
* URL base64 Alphabet - `['A'-'Z', 'a'-'z', '0'-'9', '-', '_', '=']`.
|
||||
* Alphabet is array of 65 chars. 64 chars encoding chars, and 65th padding char.<br>
|
||||
*/
|
||||
static const char* const ALPHABET_BASE64_URL;
|
||||
|
||||
/**
|
||||
* URL safe base64 Alphabet - `['A'-'Z', 'a'-'z', '0'-'9', '.', '_', '-']`.
|
||||
* Alphabet is array of 65 chars. 64 chars encoding chars, and 65th padding char.<br>
|
||||
*/
|
||||
static const char* const ALPHABET_BASE64_URL_SAFE;
|
||||
|
||||
/**
|
||||
* alphabet auxiliary chars - last 3 chars of alphabet including padding char.
|
||||
* Standard base64 Alphabet auxiliary chars ['+', '/', '='].
|
||||
* alphabet auxiliary chars - last 3 chars of alphabet including padding char.
|
||||
*/
|
||||
static const char* const ALPHABET_BASE64_AUXILIARY_CHARS;
|
||||
static const char* const ALPHABET_BASE64_URL_AUXILIARY_CHARS;
|
||||
static const char* const ALPHABET_BASE64_URL_SAFE_AUXILIARY_CHARS;
|
||||
|
||||
|
||||
/**
|
||||
* Returns size of encoding result of a string of the given size
|
||||
* URL base64 Alphabet auxiliary chars ['-', '_', '='].
|
||||
* alphabet auxiliary chars - last 3 chars of alphabet including padding char.
|
||||
*/
|
||||
static const char* const ALPHABET_BASE64_URL_AUXILIARY_CHARS;
|
||||
|
||||
/**
|
||||
* URL safe base64 Alphabet auxiliary chars ['.', '_', '='].
|
||||
* alphabet auxiliary chars - last 3 chars of alphabet including padding char.
|
||||
*/
|
||||
static const char* const ALPHABET_BASE64_URL_SAFE_AUXILIARY_CHARS;
|
||||
|
||||
/**
|
||||
* Calculate size of encoding result of a string of the given size.
|
||||
* @param size - size of string to encode.
|
||||
* @return - size of encoding result of a string of the given size
|
||||
*/
|
||||
static v_int32 calcEncodedStringSize(v_int32 size);
|
||||
|
||||
|
||||
/**
|
||||
* Returns size of decoding result. this method assumes that data passed as a param consists of standard base64 set of chars
|
||||
* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 and three configurable auxiliary chars.
|
||||
*
|
||||
* if data passed is not a base64 string then -1 is returned
|
||||
* Calculate size of decoding result. this method assumes that data passed as a param consists of standard base64 set of chars
|
||||
* `['A'-'Z', 'a'-'z', '0'-'9']` and three configurable auxiliary chars.
|
||||
* @param data - pointer to data.
|
||||
* @param size - size of the data.
|
||||
* @param base64StrLength - out parameter. Size of base64 valid encoded string. It may appear to be less then size.
|
||||
* @param auxiliaryChars - configurable auxiliary chars.
|
||||
* @return - size of decoded data. If data passed is not a base64 string then -1 is returned.
|
||||
*/
|
||||
static v_int32 calcDecodedStringSize(const char* data, v_int32 size, v_int32& base64StrLength, const char* auxiliaryChars = ALPHABET_BASE64_AUXILIARY_CHARS);
|
||||
|
||||
|
||||
/**
|
||||
* return (calcDecodedStringSize(data, size, auxiliaryChars) >= 0);
|
||||
* Check if data is a valid base64 encoded string.
|
||||
* @param data - pointer to data.
|
||||
* @param size - data size.
|
||||
* @param auxiliaryChars - configurable auxiliary chars.
|
||||
* @return `(calcDecodedStringSize(data, size, base64StrLength, auxiliaryChars) >= 0)`.
|
||||
*/
|
||||
static bool isBase64String(const char* data, v_int32 size, const char* auxiliaryChars = ALPHABET_BASE64_AUXILIARY_CHARS);
|
||||
|
||||
|
||||
/**
|
||||
* encode data as base64 string
|
||||
* Encode data as base64 string.
|
||||
* @param data - pointer to data.
|
||||
* @param size - data size.
|
||||
* @param alphabet - base64 alphabet to use.
|
||||
* @return - encoded base64 string as &id:oatpp::String;.
|
||||
*/
|
||||
static oatpp::String encode(const void* data, v_int32 size, const char* alphabet = ALPHABET_BASE64);
|
||||
|
||||
|
||||
/**
|
||||
* return encode(data->getData(), data->getSize(), alphabet);
|
||||
* Encode data as base64 string.
|
||||
* @param data - data to encode.
|
||||
* @param alphabet - base64 alphabet to use.
|
||||
* @return - encoded base64 string as &id:oatpp::String;.
|
||||
*/
|
||||
static oatpp::String encode(const oatpp::String& data, const char* alphabet = ALPHABET_BASE64);
|
||||
|
||||
|
||||
/**
|
||||
* decode() this method assumes that data passed as a param consists of standard base64 set of chars
|
||||
* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 and three configurable auxiliary chars.
|
||||
*
|
||||
* throws DecodingError(). in case invalid char found
|
||||
* Decode base64 encoded data. This method assumes that data passed as a param consists of standard base64 set of chars
|
||||
* `['A'-'Z', 'a'-'z', '0'-'9']` and three configurable auxiliary chars.
|
||||
* @param data - pointer to data to decode.
|
||||
* @param size - encoded data size.
|
||||
* @param auxiliaryChars - configurable auxiliary chars.
|
||||
* @return - decoded data as &id:oatpp::String;.
|
||||
* @throws - &l:Base64::DecodingError;
|
||||
*/
|
||||
static oatpp::String decode(const char* data, v_int32 size, const char* auxiliaryChars = ALPHABET_BASE64_AUXILIARY_CHARS);
|
||||
|
||||
/**
|
||||
* return decode(data->getData(), data->getSize(), auxiliaryChars);
|
||||
* Decode base64 encoded data. This method assumes that data passed as a param consists of standard base64 set of chars
|
||||
* `['A'-'Z', 'a'-'z', '0'-'9']` and three configurable auxiliary chars.
|
||||
* @param data - data to decode.
|
||||
* @param auxiliaryChars - configurable auxiliary chars.
|
||||
* @return - decoded data as &id:oatpp::String;.
|
||||
* @throws - &l:Base64::DecodingError;
|
||||
*/
|
||||
static oatpp::String decode(const oatpp::String& data, const char* auxiliaryChars = ALPHABET_BASE64_AUXILIARY_CHARS);
|
||||
|
||||
|
@ -27,8 +27,6 @@
|
||||
|
||||
namespace oatpp { namespace encoding {
|
||||
|
||||
const char* const Hex::ERROR_UNKNOWN_SYMBOL = "UNKNOWN_SYMBOL";
|
||||
|
||||
const v_char8 Hex::A_D[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
/*
|
||||
const v_word16 Hex::A_W16[] = {
|
||||
@ -103,7 +101,7 @@ void Hex::writeWord32(v_word32 value, p_char8 buffer){
|
||||
writeWord16(value, buffer + 4);
|
||||
}
|
||||
|
||||
const char* Hex::readWord16(p_char8 buffer, v_word16& value) {
|
||||
v_int32 Hex::readWord16(p_char8 buffer, v_word16& value) {
|
||||
value = 0;
|
||||
for(v_int32 i = 0; i < 4; i++){
|
||||
v_char8 a = buffer[i];
|
||||
@ -117,10 +115,10 @@ const char* Hex::readWord16(p_char8 buffer, v_word16& value) {
|
||||
return ERROR_UNKNOWN_SYMBOL;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* Hex::readWord32(p_char8 buffer, v_word32& value) {
|
||||
v_int32 Hex::readWord32(p_char8 buffer, v_word32& value) {
|
||||
value = 0;
|
||||
for(v_int32 i = 0; i < 8; i++){
|
||||
v_char8 a = buffer[i];
|
||||
@ -134,7 +132,7 @@ const char* Hex::readWord32(p_char8 buffer, v_word32& value) {
|
||||
return ERROR_UNKNOWN_SYMBOL;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
}}
|
||||
|
@ -31,20 +31,50 @@
|
||||
#include "oatpp/core/base/Environment.hpp"
|
||||
|
||||
namespace oatpp { namespace encoding {
|
||||
|
||||
|
||||
/**
|
||||
* Utility class for hex string encoding/decoding .
|
||||
*/
|
||||
class Hex {
|
||||
public:
|
||||
static const v_char8 A_D[];
|
||||
static const v_word16 A_W16[];
|
||||
public:
|
||||
static const char* const ERROR_UNKNOWN_SYMBOL;
|
||||
/**
|
||||
* Unknown symbol error.
|
||||
*/
|
||||
static constexpr v_int32 ERROR_UNKNOWN_SYMBOL = 1;
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Write value as hex string to buffer.
|
||||
* @param value - value to write.
|
||||
* @param buffer - buffer for resultant string.
|
||||
*/
|
||||
static void writeWord16(v_word16 value, p_char8 buffer);
|
||||
|
||||
/**
|
||||
* Write value as hex string to buffer.
|
||||
* @param value - value to write.
|
||||
* @param buffer - buffer for resultant string.
|
||||
*/
|
||||
static void writeWord32(v_word32 value, p_char8 buffer);
|
||||
|
||||
static const char* readWord16(p_char8 buffer, v_word16& value);
|
||||
static const char* readWord32(p_char8 buffer, v_word32& value);
|
||||
|
||||
/**
|
||||
* Parse 4-char hex string to int16.
|
||||
* @param buffer - buffer containing string to parse.
|
||||
* @param value - out parameter. Resultant value.
|
||||
* @return - 0 on success. Negative value on failure.
|
||||
*/
|
||||
static v_int32 readWord16(p_char8 buffer, v_word16& value);
|
||||
|
||||
/**
|
||||
* Parse 8-char hex string to int32.
|
||||
* @param buffer - buffer containing string to parse.
|
||||
* @param value - out parameter. Resultant value.
|
||||
* @return - 0 on success. Negative value on failure.
|
||||
*/
|
||||
static v_int32 readWord32(p_char8 buffer, v_word32& value);
|
||||
|
||||
};
|
||||
|
||||
|
@ -28,14 +28,56 @@
|
||||
#include "oatpp/core/base/Environment.hpp"
|
||||
|
||||
namespace oatpp { namespace encoding {
|
||||
|
||||
|
||||
/**
|
||||
* Helper class for processing unicode characters.
|
||||
*/
|
||||
class Unicode {
|
||||
public:
|
||||
/**
|
||||
* Get length in bytes of UTF-8 character by its first byte.
|
||||
* @param firstByte - first byte of UTF-8 character.
|
||||
* @return - length in bytes of UTF-8 character.
|
||||
*/
|
||||
static v_int32 getUtf8CharSequenceLength(v_char8 firstByte);
|
||||
|
||||
/**
|
||||
* Get length in bytes of UTF-8 character by its code.
|
||||
* @param code - code of UTF-8 character.
|
||||
* @return - length in bytes of UTF-8 character.
|
||||
*/
|
||||
static v_int32 getUtf8CharSequenceLengthForCode(v_word32 code);
|
||||
static v_int32 encodeUtf8Char(p_char8 sequence, v_int32& length); // returns code
|
||||
static v_int32 decodeUtf8Char(v_int32 code, p_char8 buffer); // returns length
|
||||
|
||||
/**
|
||||
* Get code of UTF-8 character.
|
||||
* @param sequence - pointer to first byte of UTF-8 character.
|
||||
* @param length - out parameter. Length in bytes of UTF-8 character.
|
||||
* @return - code of UTF-8 character.
|
||||
*/
|
||||
static v_int32 encodeUtf8Char(p_char8 sequence, v_int32& length);
|
||||
|
||||
/**
|
||||
* Write UTF-8 character to buffer.
|
||||
* @param code - UTF-8 character code.
|
||||
* @param buffer - pointer to write UTF-8 character to.
|
||||
* @return - length in bytes of UTF-8 character.
|
||||
*/
|
||||
static v_int32 decodeUtf8Char(v_int32 code, p_char8 buffer);
|
||||
|
||||
/**
|
||||
* Get corresponding UTF-16 surrogate pair for symbol code.
|
||||
* @param code - symbol code.
|
||||
* @param high - out parameter. High surrogate.
|
||||
* @param low - out parameter. Low surrogate.
|
||||
*/
|
||||
static void codeToUtf16SurrogatePair(v_int32 code, v_int16& high, v_int16& low);
|
||||
|
||||
/**
|
||||
* Get symbol code of corresponding UTF-16 surrogate pair.
|
||||
* @param high - High surrogate.
|
||||
* @param low - Low surrogate.
|
||||
* @return - symbol code.
|
||||
*/
|
||||
static v_int32 utf16SurrogatePairToCode(v_int16 high, v_int16 low);
|
||||
};
|
||||
|
||||
|
@ -29,7 +29,10 @@
|
||||
#include "oatpp/core/data/stream/Stream.hpp"
|
||||
|
||||
namespace oatpp { namespace network {
|
||||
|
||||
|
||||
/**
|
||||
* TCP Connection implementation. Extends &id:oatpp::base::Countable; and &id:oatpp::data::stream::IOStream;.
|
||||
*/
|
||||
class Connection : public oatpp::base::Countable, public oatpp::data::stream::IOStream {
|
||||
public:
|
||||
OBJECT_POOL(Connection_Pool, Connection, 32);
|
||||
@ -37,20 +40,53 @@ public:
|
||||
private:
|
||||
data::v_io_handle m_handle;
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param handle - file descriptor (socket handle). See &id:oatpp::data::v_io_handle;.
|
||||
*/
|
||||
Connection(data::v_io_handle handle);
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Create shared Connection.
|
||||
* @param handle - file descriptor (socket handle). See &id:oatpp::data::v_io_handle;.
|
||||
* @return - shared_ptr to Connection.
|
||||
*/
|
||||
static std::shared_ptr<Connection> createShared(data::v_io_handle handle){
|
||||
return Shared_Connection_Pool::allocateShared(handle);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Virtual Destructor (See &id:oatpp::base::Countable;).
|
||||
* Close socket handle.
|
||||
*/
|
||||
~Connection();
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of &id:oatpp::data::stream::IOStream::write;.
|
||||
* @param buff - buffer containing data to write.
|
||||
* @param count - bytes count you want to write.
|
||||
* @return - actual amount of bytes written. See &id:oatpp::data::v_io_size;.
|
||||
*/
|
||||
data::v_io_size write(const void *buff, data::v_io_size count) override;
|
||||
|
||||
/**
|
||||
* Implementation of &id:oatpp::data::stream::IOStream::read;.
|
||||
* @param buff - buffer to read data to.
|
||||
* @param count - buffer size.
|
||||
* @return - actual amount of bytes read. See &id:oatpp::data::v_io_size;.
|
||||
*/
|
||||
data::v_io_size read(void *buff, data::v_io_size count) override;
|
||||
|
||||
|
||||
/**
|
||||
* Close socket handle.
|
||||
*/
|
||||
void close();
|
||||
|
||||
|
||||
/**
|
||||
* Get socket handle.
|
||||
* @return - socket handle. &id:oatpp::data::v_io_handle;.
|
||||
*/
|
||||
data::v_io_handle getHandle(){
|
||||
return m_handle;
|
||||
}
|
||||
|
@ -33,30 +33,63 @@
|
||||
namespace oatpp { namespace network {
|
||||
|
||||
/**
|
||||
* Abstract ConnectionProvider.
|
||||
* It may be anything that returns oatpp::data::stream::IOStream
|
||||
* Abstract ConnectionProvider. <br>
|
||||
* Basically it returns whatever stream (&id:oatpp::data::stream::IOStream;). <br>
|
||||
* User of ConnectionProvider should care about IOStream only.
|
||||
* All other properties are optional
|
||||
* All other properties are optional.
|
||||
*/
|
||||
class ConnectionProvider {
|
||||
public:
|
||||
/**
|
||||
* Predefined property key for HOST.
|
||||
*/
|
||||
static const char* const PROPERTY_HOST;
|
||||
|
||||
/**
|
||||
* Predefined property key for PORT.
|
||||
*/
|
||||
static const char* const PROPERTY_PORT;
|
||||
public:
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::data::stream::IOStream;.
|
||||
*/
|
||||
typedef oatpp::data::stream::IOStream IOStream;
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::async::Action;.
|
||||
*/
|
||||
typedef oatpp::async::Action Action;
|
||||
typedef oatpp::async::Action (oatpp::async::AbstractCoroutine::*AsyncCallback)(const std::shared_ptr<IOStream>&);
|
||||
private:
|
||||
std::unordered_map<oatpp::data::share::StringKeyLabelCI, oatpp::data::share::StringKeyLabel> m_properties;
|
||||
protected:
|
||||
/**
|
||||
|
||||
/*
|
||||
* Set optional property
|
||||
*/
|
||||
void setProperty(const oatpp::String& key, const oatpp::String& value);
|
||||
public:
|
||||
virtual ~ConnectionProvider() {}
|
||||
|
||||
/**
|
||||
* Virtual default destructor.
|
||||
*/
|
||||
virtual ~ConnectionProvider() = default;
|
||||
|
||||
/**
|
||||
* Implement this method.
|
||||
* Get IOStream representing connection to resource.
|
||||
* @return - &id:oatpp::data::stream::IOStream;.
|
||||
*/
|
||||
virtual std::shared_ptr<IOStream> getConnection() = 0;
|
||||
|
||||
/**
|
||||
* Implement this method.
|
||||
* Obtain IOStream representing connection to resource.
|
||||
* IOStream should be returned as a parameter to callback.
|
||||
* @param parentCoroutine - caller coroutine. &id:oatpp::async::AbstractCoroutine;.
|
||||
* @param callback - pointer to callback function.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
virtual Action getConnectionAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
|
||||
AsyncCallback callback) = 0;
|
||||
|
||||
@ -66,8 +99,8 @@ public:
|
||||
virtual void close() = 0;
|
||||
|
||||
/**
|
||||
* Some optional properties that user might want to know.
|
||||
* All properties are optional and user should not rely on this
|
||||
* Some optional properties that user might want to know. <br>
|
||||
* Note: All properties are optional and user should not rely on this.
|
||||
*/
|
||||
const std::unordered_map<oatpp::data::share::StringKeyLabelCI, oatpp::data::share::StringKeyLabel>& getProperties();
|
||||
|
||||
|
@ -35,67 +35,97 @@
|
||||
namespace oatpp { namespace network {
|
||||
|
||||
|
||||
// TODO - refactor to use oatpp::data::share::MemoryLabel
|
||||
class Url : public oatpp::base::Countable {
|
||||
/**
|
||||
* Class holding URL information.
|
||||
*/
|
||||
class Url {
|
||||
public:
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::data::share::StringKeyLabel;.
|
||||
*/
|
||||
typedef oatpp::data::share::StringKeyLabel StringKeyLabel;
|
||||
public:
|
||||
/**
|
||||
* Parameters - map string to string.
|
||||
*/
|
||||
typedef std::unordered_map<oatpp::String, oatpp::String> Parameters;
|
||||
|
||||
/**
|
||||
* Parameters as &id:oatpp::data::share::StringKeyLabel;.
|
||||
* Advantage of oatpp::data::share::StringKeyLabel - is that there is no memory allocations needed to create "Memory Label".
|
||||
*/
|
||||
typedef std::unordered_map<StringKeyLabel, StringKeyLabel> ParametersAsLabels;
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Structure representing URL Authority information.
|
||||
*/
|
||||
struct Authority {
|
||||
/**
|
||||
* User info.
|
||||
*/
|
||||
oatpp::String userInfo;
|
||||
|
||||
/**
|
||||
* Host.
|
||||
*/
|
||||
oatpp::String host;
|
||||
|
||||
/**
|
||||
* Port. Treat -1 as undefined or as default.
|
||||
*/
|
||||
v_int32 port = -1;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Url parser.
|
||||
*/
|
||||
class Parser {
|
||||
public:
|
||||
|
||||
/**
|
||||
* parse "<scheme>:"
|
||||
* example "http", "https", "ftp"
|
||||
* returns lowercase string before ':' char
|
||||
* caret should be at the first char of the scheme
|
||||
* parse `<scheme>`:
|
||||
* example "http", "https", "ftp"
|
||||
* returns lowercase string before ':' char
|
||||
* caret should be at the first char of the scheme
|
||||
*/
|
||||
static oatpp::String parseScheme(oatpp::parser::Caret& caret);
|
||||
|
||||
/**
|
||||
* parse url authority components.
|
||||
* userinfo is not parsed into login and password separately as
|
||||
* inclusion of password in userinfo is deprecated and ignored here
|
||||
* caret should be at the first char of the authority (not at "//")
|
||||
* parse url authority components.
|
||||
* userinfo is not parsed into login and password separately as
|
||||
* inclusion of password in userinfo is deprecated and ignored here
|
||||
* caret should be at the first char of the authority (not at "//")
|
||||
*/
|
||||
static Url::Authority parseAuthority(oatpp::parser::Caret& caret);
|
||||
|
||||
/**
|
||||
* parse path of the url
|
||||
* caret should be at the first char of the path
|
||||
* parse path of the url
|
||||
* caret should be at the first char of the path
|
||||
*/
|
||||
static oatpp::String parsePath(oatpp::parser::Caret& caret);
|
||||
|
||||
/**
|
||||
* parse query params in form of "?<paramName>=<paramValue>&<paramName>=<paramValue>..." referred by ParsingCaret
|
||||
* and put that params to Parameters map
|
||||
* parse query params in form of `"?<paramName>=<paramValue>&<paramName>=<paramValue>..."` referred by ParsingCaret
|
||||
* and put that params to Parameters map
|
||||
*/
|
||||
static void parseQueryParamsToMap(Url::Parameters& params, oatpp::parser::Caret& caret);
|
||||
|
||||
/**
|
||||
* parse query params in form of "?<paramName>=<paramValue>&<paramName>=<paramValue>..." referred by str
|
||||
* and put that params to Parameters map
|
||||
* parse query params in form of `"?<paramName>=<paramValue>&<paramName>=<paramValue>..."` referred by str
|
||||
* and put that params to Parameters map
|
||||
*/
|
||||
static void parseQueryParamsToMap(Url::Parameters& params, const oatpp::String& str);
|
||||
|
||||
/**
|
||||
* parse query params in form of "?<paramName>=<paramValue>&<paramName>=<paramValue>..." referred by ParsingCaret
|
||||
* parse query params in form of `"?<paramName>=<paramValue>&<paramName>=<paramValue>..."` referred by ParsingCaret
|
||||
*/
|
||||
static Url::Parameters parseQueryParams(oatpp::parser::Caret& caret);
|
||||
|
||||
/**
|
||||
* parse query params in form of "?<paramName>=<paramValue>&<paramName>=<paramValue>..." referred by str
|
||||
* parse query params in form of `"?<paramName>=<paramValue>&<paramName>=<paramValue>..."` referred by str
|
||||
*/
|
||||
static Url::Parameters parseQueryParams(const oatpp::String& str);
|
||||
|
||||
@ -103,7 +133,7 @@ public:
|
||||
* Same as parseQueryParams() but use StringKeyLabel instead of a String.
|
||||
* Zero allocations. Use this method for better performance.
|
||||
* @param str
|
||||
* @return std::unordered_map<StringKeyLabel, StringKeyLabel>
|
||||
* @return `std::unordered_map<StringKeyLabel, StringKeyLabel>`. See &l:Url::StringKeyLabel;.
|
||||
*/
|
||||
static ParametersAsLabels labelQueryParams(const oatpp::String& str);
|
||||
|
||||
@ -124,10 +154,25 @@ public:
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Url scheme. Ex.: [http, https, ftp, etc.]
|
||||
*/
|
||||
oatpp::String scheme;
|
||||
|
||||
/**
|
||||
* Utl authority.
|
||||
*/
|
||||
Authority authority;
|
||||
|
||||
/**
|
||||
* Path to resource.
|
||||
*/
|
||||
oatpp::String path;
|
||||
|
||||
/**
|
||||
* Query params.
|
||||
*/
|
||||
Parameters queryParams;
|
||||
|
||||
};
|
||||
|
@ -31,30 +31,66 @@
|
||||
#include "oatpp/core/Types.hpp"
|
||||
|
||||
namespace oatpp { namespace network { namespace client {
|
||||
|
||||
|
||||
/**
|
||||
* Simple provider of clinet TCP connections.
|
||||
*/
|
||||
class SimpleTCPConnectionProvider : public base::Countable, public ClientConnectionProvider {
|
||||
protected:
|
||||
oatpp::String m_host;
|
||||
v_word16 m_port;
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param host - host name without schema and port. Ex.: "oatpp.io", "127.0.0.1", "localhost".
|
||||
* @param port - server port.
|
||||
*/
|
||||
SimpleTCPConnectionProvider(const oatpp::String& host, v_word16 port);
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Create shared client SimpleTCPConnectionProvider.
|
||||
* @param host - host name without schema and port. Ex.: "oatpp.io", "127.0.0.1", "localhost".
|
||||
* @param port - server port.
|
||||
* @return - `std::shared_ptr` to SimpleTCPConnectionProvider.
|
||||
*/
|
||||
static std::shared_ptr<SimpleTCPConnectionProvider> createShared(const oatpp::String& host, v_word16 port){
|
||||
return std::make_shared<SimpleTCPConnectionProvider>(host, port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements &id:oatpp::network::ConnectionProvider::close;. Here does nothing.
|
||||
*/
|
||||
void close() override {
|
||||
// DO NOTHING
|
||||
}
|
||||
|
||||
/**
|
||||
* Get connection.
|
||||
* @return - `std::shared_ptr` to &id:oatpp::data::stream::IOStream;.
|
||||
*/
|
||||
std::shared_ptr<IOStream> getConnection() override;
|
||||
|
||||
/**
|
||||
* Get connection in asynchronous manner.
|
||||
* @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;.
|
||||
* @param callback - pointer to callback function.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
Action getConnectionAsync(oatpp::async::AbstractCoroutine* parentCoroutine, AsyncCallback callback) override;
|
||||
|
||||
|
||||
/**
|
||||
* Get host name.
|
||||
* @return - host name.
|
||||
*/
|
||||
oatpp::String getHost() {
|
||||
return m_host;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get port.
|
||||
* @return - port.
|
||||
*/
|
||||
v_word16 getPort(){
|
||||
return m_port;
|
||||
}
|
||||
|
@ -29,13 +29,16 @@
|
||||
|
||||
|
||||
namespace oatpp { namespace network { namespace server {
|
||||
|
||||
|
||||
/**
|
||||
* Abstract ConnectionHandler.
|
||||
*/
|
||||
class ConnectionHandler {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Handle provided connection here
|
||||
* @param connection
|
||||
* @param connection - see &id:oatpp::data::stream::IOStream;.
|
||||
*/
|
||||
virtual void handleConnection(const std::shared_ptr<oatpp::data::stream::IOStream>& connection) = 0;
|
||||
|
||||
|
@ -34,6 +34,13 @@ const v_int32 Server::STATUS_RUNNING = 1;
|
||||
const v_int32 Server::STATUS_STOPPING = 2;
|
||||
const v_int32 Server::STATUS_DONE = 3;
|
||||
|
||||
Server::Server(const std::shared_ptr<ServerConnectionProvider>& connectionProvider,
|
||||
const std::shared_ptr<ConnectionHandler>& connectionHandler)
|
||||
: m_status(STATUS_CREATED)
|
||||
, m_connectionProvider(connectionProvider)
|
||||
, m_connectionHandler(connectionHandler)
|
||||
{}
|
||||
|
||||
void Server::mainLoop(){
|
||||
|
||||
setStatus(STATUS_CREATED, STATUS_RUNNING);
|
||||
|
@ -29,8 +29,6 @@
|
||||
|
||||
#include "oatpp/network/ConnectionProvider.hpp"
|
||||
|
||||
#include "oatpp/core/concurrency/Runnable.hpp"
|
||||
|
||||
#include "oatpp/core/Types.hpp"
|
||||
|
||||
#include "oatpp/core/base/Countable.hpp"
|
||||
@ -40,7 +38,11 @@
|
||||
|
||||
namespace oatpp { namespace network { namespace server {
|
||||
|
||||
class Server : public base::Countable, public concurrency::Runnable{
|
||||
/**
|
||||
* Server calls &id:oatpp::network::ConnectionProvider::getConnection; in the loop and passes obtained Connection
|
||||
* to &id:oatpp::network::server::ConnectionHandler;.
|
||||
*/
|
||||
class Server : public base::Countable {
|
||||
private:
|
||||
|
||||
void mainLoop();
|
||||
@ -58,32 +60,70 @@ private:
|
||||
std::shared_ptr<ConnectionHandler> m_connectionHandler;
|
||||
|
||||
public:
|
||||
|
||||
Server(
|
||||
const std::shared_ptr<ServerConnectionProvider>& connectionProvider,
|
||||
const std::shared_ptr<ConnectionHandler>& connectionHandler
|
||||
)
|
||||
: m_status(STATUS_CREATED)
|
||||
, m_connectionProvider(connectionProvider)
|
||||
, m_connectionHandler(connectionHandler)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param connectionProvider - &id:oatpp::network::ConnectionProvider;.
|
||||
* @param connectionHandler - &id:oatpp::network::server::ConnectionHandler;.
|
||||
*/
|
||||
Server(const std::shared_ptr<ServerConnectionProvider>& connectionProvider,
|
||||
const std::shared_ptr<ConnectionHandler>& connectionHandler);
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Status constant.
|
||||
*/
|
||||
static const v_int32 STATUS_CREATED;
|
||||
|
||||
/**
|
||||
* Status constant.
|
||||
*/
|
||||
static const v_int32 STATUS_RUNNING;
|
||||
|
||||
/**
|
||||
* Status constant.
|
||||
*/
|
||||
static const v_int32 STATUS_STOPPING;
|
||||
|
||||
/**
|
||||
* Status constant.
|
||||
*/
|
||||
static const v_int32 STATUS_DONE;
|
||||
|
||||
|
||||
/**
|
||||
* Create shared Server.
|
||||
* @param connectionProvider - &id:oatpp::network::ConnectionProvider;.
|
||||
* @param connectionHandler - &id:oatpp::network::server::ConnectionHandler;.
|
||||
* @return - `std::shared_ptr` to Server.
|
||||
*/
|
||||
static std::shared_ptr<Server> createShared(const std::shared_ptr<ServerConnectionProvider>& connectionProvider,
|
||||
const std::shared_ptr<ConnectionHandler>& connectionHandler){
|
||||
const std::shared_ptr<ConnectionHandler>& connectionHandler){
|
||||
return std::make_shared<Server>(connectionProvider, connectionHandler);
|
||||
}
|
||||
|
||||
void run() override;
|
||||
|
||||
|
||||
/**
|
||||
* Call &id:oatpp::network::ConnectionProvider::getConnection; in the loop and passes obtained Connection
|
||||
* to &id:oatpp::network::server::ConnectionHandler;.
|
||||
*/
|
||||
void run();
|
||||
|
||||
/**
|
||||
* Break server loop.
|
||||
* Note: thread can still be blocked on the &l:Server::run (); call as it may be waiting for ConnectionProvider to provide connection.
|
||||
*/
|
||||
void stop();
|
||||
|
||||
|
||||
/**
|
||||
* Get server status.
|
||||
* @return - one of:<br>
|
||||
* <ul>
|
||||
* <li>&l:Server::STATUS_CREATED;</li>
|
||||
* <li>&l:Server::STATUS_RUNNING;</li>
|
||||
* <li>&l:Server::STATUS_STOPPING;</li>
|
||||
* <li>&l:Server::STATUS_DONE;</li>
|
||||
* </ul>
|
||||
*/
|
||||
v_int32 getStatus();
|
||||
|
||||
};
|
||||
|
@ -31,7 +31,10 @@
|
||||
#include "oatpp/core/Types.hpp"
|
||||
|
||||
namespace oatpp { namespace network { namespace server {
|
||||
|
||||
|
||||
/**
|
||||
* Simple provider of TCP connections.
|
||||
*/
|
||||
class SimpleTCPConnectionProvider : public base::Countable, public ServerConnectionProvider {
|
||||
private:
|
||||
v_word16 m_port;
|
||||
@ -41,22 +44,52 @@ private:
|
||||
private:
|
||||
oatpp::data::v_io_handle instantiateServer();
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param port - port to listen for incoming connections.
|
||||
* @param nonBlocking - set `true` to provide non-blocking &id:oatpp::data::stream::IOStream; for connection.
|
||||
* `false` for blocking &id:oatpp::data::stream::IOStream;. Default `false`.
|
||||
*/
|
||||
SimpleTCPConnectionProvider(v_word16 port, bool nonBlocking = false);
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Create shared SimpleTCPConnectionProvider.
|
||||
* @param port - port to listen for incoming connections.
|
||||
* @param nonBlocking - set `true` to provide non-blocking &id:oatpp::data::stream::IOStream; for connection.
|
||||
* `false` for blocking &id:oatpp::data::stream::IOStream;. Default `false`.
|
||||
*/
|
||||
static std::shared_ptr<SimpleTCPConnectionProvider> createShared(v_word16 port, bool nonBlocking = false){
|
||||
return std::make_shared<SimpleTCPConnectionProvider>(port, nonBlocking);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Virtual destructor.
|
||||
*/
|
||||
~SimpleTCPConnectionProvider();
|
||||
|
||||
/**
|
||||
* Close accept-socket.
|
||||
*/
|
||||
void close() override;
|
||||
|
||||
|
||||
/**
|
||||
* Get incoming connection.
|
||||
* @return &id:oatpp::data::stream::IOStream;.
|
||||
*/
|
||||
std::shared_ptr<IOStream> getConnection() override;
|
||||
|
||||
|
||||
/**
|
||||
* No need to implement this.<br>
|
||||
* For Asynchronous IO in oatpp it is considered to be a good practice
|
||||
* to accept connections in a seperate thread with the blocking accept()
|
||||
* and then process connections in Asynchronous manner with non-blocking read/write.
|
||||
* <br>
|
||||
* *It may be implemented later*
|
||||
*/
|
||||
Action getConnectionAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
|
||||
AsyncCallback callback) override {
|
||||
/**
|
||||
/*
|
||||
* No need to implement this.
|
||||
* For Asynchronous IO in oatpp it is considered to be a good practice
|
||||
* to accept connections in a seperate thread with the blocking accept()
|
||||
@ -66,7 +99,11 @@ public:
|
||||
*/
|
||||
throw std::runtime_error("[oatpp::network::server::SimpleTCPConnectionProvider::getConnectionAsync()]: Error. Not implemented.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get port.
|
||||
* @return
|
||||
*/
|
||||
v_word16 getPort(){
|
||||
return m_port;
|
||||
}
|
||||
|
@ -30,10 +30,17 @@
|
||||
#include "oatpp/core/collection/LinkedList.hpp"
|
||||
|
||||
namespace oatpp { namespace network { namespace virtual_ {
|
||||
|
||||
|
||||
/**
|
||||
* "Virtual" Interface provides functionality for accepting "virtual" connections.
|
||||
* "virtual" connection is represented by &id:oatpp::network::virtual_::Socket;.
|
||||
*/
|
||||
class Interface : public oatpp::base::Countable {
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* "Future" for &id:oatpp::network::virtual_::Socket;.
|
||||
*/
|
||||
class ConnectionSubmission {
|
||||
private:
|
||||
std::shared_ptr<Socket> m_socket;
|
||||
@ -41,12 +48,35 @@ public:
|
||||
std::condition_variable m_condition;
|
||||
bool m_pending;
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
ConnectionSubmission() : m_pending(true) {}
|
||||
|
||||
|
||||
/**
|
||||
* Set socket to be returned in call to &l:Interface::ConnectionSubmission::getSocket ();/&l:Interface::ConnectionSubmission::getSocketNonBlocking ();.
|
||||
* @param socket - &id:oatpp::network::virtual_::Socket;.
|
||||
*/
|
||||
void setSocket(const std::shared_ptr<Socket>& socket);
|
||||
|
||||
/**
|
||||
* Block and wait for socket.
|
||||
* @return - `std::shared_ptr` to &id:oatpp::network::virtual_::Socket;.
|
||||
*/
|
||||
std::shared_ptr<Socket> getSocket();
|
||||
|
||||
/**
|
||||
* Check if socket already available.
|
||||
* User should repeat call if `(!socket && isPending())`.
|
||||
* @return - `std::shared_ptr` to &id:oatpp::network::virtual_::Socket;.
|
||||
*/
|
||||
std::shared_ptr<Socket> getSocketNonBlocking();
|
||||
|
||||
/**
|
||||
* Check if submission has not been processed yet.
|
||||
* @return - `true` if still waiting for acceptor to accept connection submission.
|
||||
*/
|
||||
bool isPending();
|
||||
|
||||
};
|
||||
@ -59,25 +89,49 @@ private:
|
||||
std::condition_variable m_condition;
|
||||
oatpp::collection::LinkedList<std::shared_ptr<ConnectionSubmission>> m_submissions;
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param name - interface name.
|
||||
*/
|
||||
Interface(const oatpp::String& name)
|
||||
: m_name(name)
|
||||
{}
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Create shared Interface.
|
||||
* @param name - interface name.
|
||||
* @return - `std::shared_ptr` to Interface.
|
||||
*/
|
||||
static std::shared_ptr<Interface> createShared(const oatpp::String& name) {
|
||||
return std::make_shared<Interface>(name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Connect to interface.
|
||||
* @return - &l:Interface::ConnectionSubmission;.
|
||||
*/
|
||||
std::shared_ptr<ConnectionSubmission> connect();
|
||||
|
||||
/**
|
||||
* Connect to interface.
|
||||
* @return - &l:Interface::ConnectionSubmission; on success. Empty `std::shared_ptr` on failure.
|
||||
*/
|
||||
std::shared_ptr<ConnectionSubmission> connectNonBlocking();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param waitingHandle
|
||||
* @return
|
||||
* Block and wait for incloming connection.
|
||||
* @param waitingHandle - reference to a boolean variable.
|
||||
* User may set waitingHandle = false and call &l:Interface::notifyAcceptors (); in order to break waiting loop. and exit accept() method.
|
||||
* @return - `std::shared_ptr` to &id:oatpp::network::virtual_::Socket;.
|
||||
*/
|
||||
std::shared_ptr<Socket> accept(const bool& waitingHandle = true);
|
||||
|
||||
/**
|
||||
* Check if incoming connection is available. NonBlocking.
|
||||
* @return - `std::shared_ptr` to &id:oatpp::network::virtual_::Socket; if available.
|
||||
* Empty `std::shared_ptr` if no incoming connection is available at the moment.
|
||||
*/
|
||||
std::shared_ptr<Socket> acceptNonBlocking();
|
||||
|
||||
/**
|
||||
@ -85,7 +139,11 @@ public:
|
||||
* Those threads that have waitingHandle changed to false will be unblocked.
|
||||
*/
|
||||
void notifyAcceptors();
|
||||
|
||||
|
||||
/**
|
||||
* Get interface name.
|
||||
* @return - &id:oatpp::String;.
|
||||
*/
|
||||
oatpp::String getName() {
|
||||
return m_name;
|
||||
}
|
||||
|
@ -113,5 +113,34 @@ data::v_io_size Pipe::Writer::write(const void *data, data::v_io_size count) {
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
Pipe::Pipe()
|
||||
: m_open(true)
|
||||
, m_writer(this)
|
||||
, m_reader(this)
|
||||
, m_buffer()
|
||||
, m_fifo(m_buffer.getData(), m_buffer.getSize())
|
||||
{}
|
||||
|
||||
std::shared_ptr<Pipe> Pipe::createShared(){
|
||||
return std::make_shared<Pipe>();
|
||||
}
|
||||
|
||||
Pipe::Writer* Pipe::getWriter() {
|
||||
return &m_writer;
|
||||
}
|
||||
|
||||
Pipe::Reader* Pipe::getReader() {
|
||||
return &m_reader;
|
||||
}
|
||||
|
||||
void Pipe::close() {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_open = false;
|
||||
}
|
||||
m_conditionRead.notify_one();
|
||||
m_conditionWrite.notify_one();
|
||||
}
|
||||
|
||||
}}}
|
||||
|
@ -37,67 +37,111 @@
|
||||
|
||||
namespace oatpp { namespace network { namespace virtual_ {
|
||||
|
||||
/**
|
||||
* Virtual pipe implementation. Can be used for unidirectional data transfer between different threads of the same process. <br>
|
||||
* Under the hood it uses &id:oatpp::data::buffer::SynchronizedFIFOBuffer; over the &id:oatpp::data::buffer::IOBuffer;.
|
||||
*/
|
||||
class Pipe : public oatpp::base::Countable {
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Pipe Reader. Extends &id:oatpp::data::stream::InputStream;.
|
||||
* Provides read interface for the pipe. Can work in both blocking and nonblocking regime.
|
||||
*/
|
||||
class Reader : public oatpp::data::stream::InputStream {
|
||||
friend Pipe;
|
||||
private:
|
||||
Pipe* m_pipe;
|
||||
bool m_nonBlocking;
|
||||
|
||||
/**
|
||||
/*
|
||||
* this one used for testing purposes only
|
||||
*/
|
||||
data::v_io_size m_maxAvailableToRead;
|
||||
public:
|
||||
protected:
|
||||
|
||||
Reader(Pipe* pipe, bool nonBlocking = false)
|
||||
: m_pipe(pipe)
|
||||
, m_nonBlocking(nonBlocking)
|
||||
, m_maxAvailableToRead(-1)
|
||||
{}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Set `true` to make non-blocking reads using &l:Pipe::Reader::read ();.
|
||||
* @param nonBlocking - `true` for nonblocking read.
|
||||
*/
|
||||
void setNonBlocking(bool nonBlocking) {
|
||||
m_nonBlocking = nonBlocking;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* this one used for testing purposes only
|
||||
* set to -1 in order to ignore this value
|
||||
* Limit the available amount of bytes to read from pipe.<br>
|
||||
* This method is used for testing purposes only.<br>
|
||||
* set to -1 in order to ignore this value.<br>
|
||||
* @param maxAvailableToRead - maximum available amount of bytes to read.
|
||||
*/
|
||||
void setMaxAvailableToRead(data::v_io_size maxAvailableToRead);
|
||||
|
||||
|
||||
/**
|
||||
* Implements &id:oatpp::data::stream::InputStream::read; method.
|
||||
* Read data from pipe.
|
||||
* @param data - buffer to read data to.
|
||||
* @param count - max count of bytes to read.
|
||||
* @return - &id:oatpp::data::v_io_size;.
|
||||
*/
|
||||
data::v_io_size read(void *data, data::v_io_size count) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Pipe writer. Extends &id:oatpp::data::stream::OutputStream;.
|
||||
* Provides write interface for the pipe. Can work in both blocking and nonblocking regime.
|
||||
*/
|
||||
class Writer : public oatpp::data::stream::OutputStream {
|
||||
friend Pipe;
|
||||
private:
|
||||
Pipe* m_pipe;
|
||||
bool m_nonBlocking;
|
||||
|
||||
/**
|
||||
/*
|
||||
* this one used for testing purposes only
|
||||
*/
|
||||
data::v_io_size m_maxAvailableToWrtie;
|
||||
public:
|
||||
protected:
|
||||
|
||||
Writer(Pipe* pipe, bool nonBlocking = false)
|
||||
: m_pipe(pipe)
|
||||
, m_nonBlocking(nonBlocking)
|
||||
, m_maxAvailableToWrtie(-1)
|
||||
{}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Set `true` to make non-blocking writes using &l:Pipe::Writer::write ();.
|
||||
* @param nonBlocking - `true` for nonblocking write.
|
||||
*/
|
||||
void setNonBlocking(bool nonBlocking) {
|
||||
m_nonBlocking = nonBlocking;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* this one used for testing purposes only
|
||||
* set to -1 in order to ignore this value
|
||||
* Limit the available space for data writes in pipe.<br>
|
||||
* This method is used for testing purposes only.<br>
|
||||
* set to -1 in order to ignore this value.<br>
|
||||
* @param maxAvailableToWrite - maximum available amount of bytes to write.
|
||||
*/
|
||||
void setMaxAvailableToWrite(data::v_io_size maxAvailableToWrite);
|
||||
|
||||
|
||||
/**
|
||||
* Implements &id:oatpp::data::stream::OutputStream::write; method.
|
||||
* Write data to pipe.
|
||||
* @param data - data to write to pipe.
|
||||
* @param count - data size.
|
||||
* @return - &id:oatpp::data::v_io_size;.
|
||||
*/
|
||||
data::v_io_size write(const void *data, data::v_io_size count) override;
|
||||
|
||||
};
|
||||
@ -114,35 +158,37 @@ private:
|
||||
std::condition_variable m_conditionRead;
|
||||
std::condition_variable m_conditionWrite;
|
||||
public:
|
||||
|
||||
Pipe()
|
||||
: m_open(true)
|
||||
, m_writer(this)
|
||||
, m_reader(this)
|
||||
, m_buffer()
|
||||
, m_fifo(m_buffer.getData(), m_buffer.getSize())
|
||||
{}
|
||||
|
||||
static std::shared_ptr<Pipe> createShared(){
|
||||
return std::make_shared<Pipe>();
|
||||
}
|
||||
|
||||
Writer* getWriter() {
|
||||
return &m_writer;
|
||||
}
|
||||
|
||||
Reader* getReader() {
|
||||
return &m_reader;
|
||||
}
|
||||
|
||||
void close() {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_open = false;
|
||||
}
|
||||
m_conditionRead.notify_one();
|
||||
m_conditionWrite.notify_one();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
Pipe();
|
||||
|
||||
/**
|
||||
* Create shared pipe.
|
||||
* @return - `std::shared_ptr` to Pipe.
|
||||
*/
|
||||
static std::shared_ptr<Pipe> createShared();
|
||||
|
||||
/**
|
||||
* Get pointer to &l:Pipe::Writer; for this pipe.
|
||||
* There can be only one &l:Pipe::Writer; per pipe.
|
||||
* @return - &l:Pipe::Writer;.
|
||||
*/
|
||||
Writer* getWriter();
|
||||
|
||||
|
||||
/**
|
||||
* Get pointer to &l:Pipe::Reader; for this pipe.
|
||||
* There can be only one &l:Pipe::Reader; per pipe.
|
||||
* @return - &l:Pipe::Reader;.
|
||||
*/
|
||||
Reader* getReader();
|
||||
|
||||
/**
|
||||
* Mark pipe as closed.
|
||||
*/
|
||||
void close();
|
||||
|
||||
};
|
||||
|
||||
|
@ -25,7 +25,20 @@
|
||||
#include "Socket.hpp"
|
||||
|
||||
namespace oatpp { namespace network { namespace virtual_ {
|
||||
|
||||
|
||||
Socket::Socket(const std::shared_ptr<Pipe>& pipeIn, const std::shared_ptr<Pipe>& pipeOut)
|
||||
: m_pipeIn(pipeIn)
|
||||
, m_pipeOut(pipeOut)
|
||||
{}
|
||||
|
||||
Socket::~Socket() {
|
||||
close();
|
||||
}
|
||||
|
||||
std::shared_ptr<Socket> Socket::createShared(const std::shared_ptr<Pipe>& pipeIn, const std::shared_ptr<Pipe>& pipeOut) {
|
||||
return std::make_shared<Socket>(pipeIn, pipeOut);
|
||||
}
|
||||
|
||||
void Socket::setMaxAvailableToReadWrtie(data::v_io_size maxToRead, data::v_io_size maxToWrite) {
|
||||
m_pipeIn->getReader()->setMaxAvailableToRead(maxToRead);
|
||||
m_pipeOut->getWriter()->setMaxAvailableToWrite(maxToWrite);
|
||||
|
@ -28,37 +28,71 @@
|
||||
#include "./Pipe.hpp"
|
||||
|
||||
namespace oatpp { namespace network { namespace virtual_ {
|
||||
|
||||
|
||||
/**
|
||||
* Virtual socket implementation. Can be used as a bidirectional data transfer between different threads of the same process. <br>
|
||||
* Under the hood it uses a pair of &id:oatpp::network::virtual_::Pipe;. One to write data to, and one to read data from.
|
||||
* Extends &id:oatpp::base::Countable; and &id:oatpp::data::stream::IOStream;.
|
||||
*/
|
||||
class Socket : public oatpp::base::Countable, public oatpp::data::stream::IOStream {
|
||||
private:
|
||||
std::shared_ptr<Pipe> m_pipeIn;
|
||||
std::shared_ptr<Pipe> m_pipeOut;
|
||||
public:
|
||||
Socket(const std::shared_ptr<Pipe>& pipeIn, const std::shared_ptr<Pipe>& pipeOut)
|
||||
: m_pipeIn(pipeIn)
|
||||
, m_pipeOut(pipeOut)
|
||||
{}
|
||||
public:
|
||||
|
||||
static std::shared_ptr<Socket> createShared(const std::shared_ptr<Pipe>& pipeIn, const std::shared_ptr<Pipe>& pipeOut) {
|
||||
return std::make_shared<Socket>(pipeIn, pipeOut);
|
||||
}
|
||||
|
||||
~Socket() {
|
||||
close();
|
||||
}
|
||||
|
||||
/**
|
||||
* this one used for testing purposes only
|
||||
* set to -1 in order to ignore this value
|
||||
* Constructor.
|
||||
* @param pipeIn - pipe to read data from.
|
||||
* @param pipeOut - pipe to write data to.
|
||||
*/
|
||||
Socket(const std::shared_ptr<Pipe>& pipeIn, const std::shared_ptr<Pipe>& pipeOut);
|
||||
public:
|
||||
|
||||
/**
|
||||
* Create shared socket.
|
||||
* @param pipeIn - pipe to read data from.
|
||||
* @param pipeOut - pipe to write data to.
|
||||
* @return - `std::shared_ptr` to Socket.
|
||||
*/
|
||||
static std::shared_ptr<Socket> createShared(const std::shared_ptr<Pipe>& pipeIn, const std::shared_ptr<Pipe>& pipeOut);
|
||||
|
||||
/**
|
||||
* Virtual destructor. Close corresponding pipes.
|
||||
*/
|
||||
~Socket();
|
||||
|
||||
/**
|
||||
* Limit the available amount of bytes to read from socket and limit the available amount of bytes to write to socket. <br>
|
||||
* This method is used for testing purposes only.<br>
|
||||
* @param maxToRead - maximum available amount of bytes to read.
|
||||
* @param maxToWrite - maximum available amount of bytes to write.
|
||||
*/
|
||||
void setMaxAvailableToReadWrtie(data::v_io_size maxToRead, data::v_io_size maxToWrite);
|
||||
|
||||
|
||||
/**
|
||||
* Read data from socket.
|
||||
* @param data - buffer to read data to.
|
||||
* @param count - buffer size.
|
||||
* @return - actual amount of data read from socket.
|
||||
*/
|
||||
data::v_io_size read(void *data, data::v_io_size count) override;
|
||||
|
||||
/**
|
||||
* Write data to socket.
|
||||
* @param data - data to write to socket.
|
||||
* @param count - data size.
|
||||
* @return - actual amount of data written to socket.
|
||||
*/
|
||||
data::v_io_size write(const void *data, data::v_io_size count) override;
|
||||
|
||||
|
||||
/**
|
||||
* Set socket for nonblocking I/O.
|
||||
* @param nonBlocking - `true` for nonblocking.
|
||||
*/
|
||||
void setNonBlocking(bool nonBlocking);
|
||||
|
||||
|
||||
/**
|
||||
* Close socket pipes.
|
||||
*/
|
||||
void close();
|
||||
|
||||
};
|
||||
|
@ -26,6 +26,19 @@
|
||||
|
||||
namespace oatpp { namespace network { namespace virtual_ { namespace client {
|
||||
|
||||
ConnectionProvider::ConnectionProvider(const std::shared_ptr<virtual_::Interface>& interface)
|
||||
: m_interface(interface)
|
||||
, m_maxAvailableToRead(-1)
|
||||
, m_maxAvailableToWrite(-1)
|
||||
{
|
||||
setProperty(PROPERTY_HOST, m_interface->getName());
|
||||
setProperty(PROPERTY_PORT, "0");
|
||||
}
|
||||
|
||||
std::shared_ptr<ConnectionProvider> ConnectionProvider::createShared(const std::shared_ptr<virtual_::Interface>& interface) {
|
||||
return std::make_shared<ConnectionProvider>(interface);
|
||||
}
|
||||
|
||||
void ConnectionProvider::close() {
|
||||
|
||||
}
|
||||
|
@ -29,40 +29,60 @@
|
||||
#include "oatpp/network/ConnectionProvider.hpp"
|
||||
|
||||
namespace oatpp { namespace network { namespace virtual_ { namespace client {
|
||||
|
||||
|
||||
/**
|
||||
* Provider of "virtual" connections for client.
|
||||
* See &id:oatpp::network::virtual_::Interface;, &id:oatpp::network::virtual_::Socket; <br>
|
||||
* Extends &id:oatpp::network::ClientConnectionProvider;.
|
||||
*/
|
||||
class ConnectionProvider : public oatpp::network::ClientConnectionProvider {
|
||||
private:
|
||||
std::shared_ptr<virtual_::Interface> m_interface;
|
||||
data::v_io_size m_maxAvailableToRead;
|
||||
data::v_io_size m_maxAvailableToWrite;
|
||||
public:
|
||||
|
||||
ConnectionProvider(const std::shared_ptr<virtual_::Interface>& interface)
|
||||
: m_interface(interface)
|
||||
, m_maxAvailableToRead(-1)
|
||||
, m_maxAvailableToWrite(-1)
|
||||
{
|
||||
setProperty(PROPERTY_HOST, m_interface->getName());
|
||||
setProperty(PROPERTY_PORT, "0");
|
||||
}
|
||||
|
||||
static std::shared_ptr<ConnectionProvider> createShared(const std::shared_ptr<virtual_::Interface>& interface) {
|
||||
return std::make_shared<ConnectionProvider>(interface);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* this one used for testing purposes only
|
||||
* set to -1 in order to ignore this value
|
||||
* Constructor.
|
||||
* @param interface - &id:oatpp::network::virtual_::Interface;.
|
||||
*/
|
||||
ConnectionProvider(const std::shared_ptr<virtual_::Interface>& interface);
|
||||
|
||||
/**
|
||||
* Create shared ConnectionProvider.
|
||||
* @param interface - &id:oatpp::network::virtual_::Interface;.
|
||||
* @return - `std::shared_ptr` to ConnectionProvider.
|
||||
*/
|
||||
static std::shared_ptr<ConnectionProvider> createShared(const std::shared_ptr<virtual_::Interface>& interface);
|
||||
|
||||
/**
|
||||
* Limit the available amount of bytes to read from socket and limit the available amount of bytes to write to socket. <br>
|
||||
* This method is used for testing purposes only.<br>
|
||||
* @param maxToRead - maximum available amount of bytes to read.
|
||||
* @param maxToWrite - maximum available amount of bytes to write.
|
||||
*/
|
||||
void setSocketMaxAvailableToReadWrtie(data::v_io_size maxToRead, data::v_io_size maxToWrite) {
|
||||
m_maxAvailableToRead = maxToRead;
|
||||
m_maxAvailableToWrite = maxToWrite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of &id:oatpp::network::ClientConnection::Close; method.
|
||||
*/
|
||||
void close() override;
|
||||
|
||||
|
||||
/**
|
||||
* Get connection.
|
||||
* @return - `std::shared_ptr` to &id:oatpp::data::stream::IOStream;.
|
||||
*/
|
||||
std::shared_ptr<IOStream> getConnection() override;
|
||||
|
||||
|
||||
/**
|
||||
* Get connection in asynchronous manner.
|
||||
* @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;.
|
||||
* @param callback - pointer to callback function.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
Action getConnectionAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
|
||||
AsyncCallback callback) override;
|
||||
|
||||
|
@ -26,6 +26,26 @@
|
||||
|
||||
namespace oatpp { namespace network { namespace virtual_ { namespace server {
|
||||
|
||||
ConnectionProvider::ConnectionProvider(const std::shared_ptr<virtual_::Interface>& interface, bool nonBlocking)
|
||||
: m_interface(interface)
|
||||
, m_nonBlocking(nonBlocking)
|
||||
, m_open(true)
|
||||
, m_maxAvailableToRead(-1)
|
||||
, m_maxAvailableToWrite(-1)
|
||||
{
|
||||
setProperty(PROPERTY_HOST, m_interface->getName());
|
||||
setProperty(PROPERTY_PORT, "0");
|
||||
}
|
||||
|
||||
std::shared_ptr<ConnectionProvider> ConnectionProvider::createShared(const std::shared_ptr<virtual_::Interface>& interface, bool nonBlocking) {
|
||||
return std::make_shared<ConnectionProvider>(interface, nonBlocking);
|
||||
}
|
||||
|
||||
void ConnectionProvider::setSocketMaxAvailableToReadWrtie(data::v_io_size maxToRead, data::v_io_size maxToWrite) {
|
||||
m_maxAvailableToRead = maxToRead;
|
||||
m_maxAvailableToWrite = maxToWrite;
|
||||
}
|
||||
|
||||
void ConnectionProvider::close() {
|
||||
m_open = false;
|
||||
m_interface->notifyAcceptors();
|
||||
|
@ -29,7 +29,12 @@
|
||||
#include "oatpp/network/ConnectionProvider.hpp"
|
||||
|
||||
namespace oatpp { namespace network { namespace virtual_ { namespace server {
|
||||
|
||||
|
||||
/**
|
||||
* Provider of "virtual" connections.
|
||||
* See &id:oatpp::network::virtual_::Interface;, &id:oatpp::network::virtual_::Socket; <br>
|
||||
* Extends &id:oatpp::network::ServerConnectionProvider;.
|
||||
*/
|
||||
class ConnectionProvider : public oatpp::network::ServerConnectionProvider {
|
||||
private:
|
||||
std::shared_ptr<virtual_::Interface> m_interface;
|
||||
@ -38,38 +43,53 @@ private:
|
||||
data::v_io_size m_maxAvailableToRead;
|
||||
data::v_io_size m_maxAvailableToWrite;
|
||||
public:
|
||||
|
||||
ConnectionProvider(const std::shared_ptr<virtual_::Interface>& interface, bool nonBlocking = false)
|
||||
: m_interface(interface)
|
||||
, m_nonBlocking(nonBlocking)
|
||||
, m_open(true)
|
||||
, m_maxAvailableToRead(-1)
|
||||
, m_maxAvailableToWrite(-1)
|
||||
{
|
||||
setProperty(PROPERTY_HOST, m_interface->getName());
|
||||
setProperty(PROPERTY_PORT, "0");
|
||||
}
|
||||
|
||||
static std::shared_ptr<ConnectionProvider> createShared(const std::shared_ptr<virtual_::Interface>& interface, bool nonBlocking = false) {
|
||||
return std::make_shared<ConnectionProvider>(interface, nonBlocking);
|
||||
}
|
||||
|
||||
/**
|
||||
* this one used for testing purposes only
|
||||
* set to -1 in order to ignore this value
|
||||
* Constructor.
|
||||
* @param interface - &id:oatpp::network::virtual_::Interface;.
|
||||
* @param nonBlocking - `true` to set non blocking regime for provided connections.
|
||||
*/
|
||||
void setSocketMaxAvailableToReadWrtie(data::v_io_size maxToRead, data::v_io_size maxToWrite) {
|
||||
m_maxAvailableToRead = maxToRead;
|
||||
m_maxAvailableToWrite = maxToWrite;
|
||||
}
|
||||
ConnectionProvider(const std::shared_ptr<virtual_::Interface>& interface, bool nonBlocking = false);
|
||||
|
||||
/**
|
||||
* Create shared ConnectionProvider.
|
||||
* @param interface - &id:oatpp::network::virtual_::Interface;.
|
||||
* @param nonBlocking - `true` to set non blocking regime for provided connections.
|
||||
* @return - `std::shared_ptr` to ConnectionProvider.
|
||||
*/
|
||||
static std::shared_ptr<ConnectionProvider> createShared(const std::shared_ptr<virtual_::Interface>& interface, bool nonBlocking = false);
|
||||
|
||||
/**
|
||||
* Limit the available amount of bytes to read from socket and limit the available amount of bytes to write to socket. <br>
|
||||
* This method is used for testing purposes only.<br>
|
||||
* @param maxToRead - maximum available amount of bytes to read.
|
||||
* @param maxToWrite - maximum available amount of bytes to write.
|
||||
*/
|
||||
void setSocketMaxAvailableToReadWrtie(data::v_io_size maxToRead, data::v_io_size maxToWrite);
|
||||
|
||||
/**
|
||||
* Break accepting loop.
|
||||
*/
|
||||
void close() override;
|
||||
|
||||
|
||||
/**
|
||||
* Get incoming connection.
|
||||
* @return &id:oatpp::data::stream::IOStream;.
|
||||
*/
|
||||
std::shared_ptr<IOStream> getConnection() override;
|
||||
|
||||
|
||||
/**
|
||||
* **NOT IMPLEMENTED!**<br>
|
||||
* No need to implement this.<br>
|
||||
* For Asynchronous IO in oatpp it is considered to be a good practice
|
||||
* to accept connections in a seperate thread with the blocking accept()
|
||||
* and then process connections in Asynchronous manner with non-blocking read/write.
|
||||
* <br>
|
||||
* *It may be implemented later.*
|
||||
*/
|
||||
Action getConnectionAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
|
||||
AsyncCallback callback) override {
|
||||
/**
|
||||
/*
|
||||
* No need to implement this.
|
||||
* For Asynchronous IO in oatpp it is considered to be a good practice
|
||||
* to accept connections in a seperate thread with the blocking accept()
|
||||
|
@ -29,10 +29,6 @@
|
||||
|
||||
namespace oatpp { namespace parser { namespace json{
|
||||
|
||||
const char* const Utils::ERROR_INVALID_ESCAPED_CHAR = "ERROR_INVALID_ESCAPED_CHAR";
|
||||
const char* const Utils::ERROR_INVALID_SURROGATE_PAIR = "ERROR_INVALID_SURROGATE_PAIR";
|
||||
const char* const Utils::ERROR_PARSER_QUOTE_EXPECTED = "'\"' - EXPECTED";
|
||||
|
||||
v_int32 Utils::calcEscapedStringSize(p_char8 data, v_int32 size, v_int32& safeSize) {
|
||||
v_int32 result = 0;
|
||||
v_int32 i = 0;
|
||||
@ -77,8 +73,8 @@ v_int32 Utils::calcEscapedStringSize(p_char8 data, v_int32 size, v_int32& safeSi
|
||||
return result;
|
||||
}
|
||||
|
||||
v_int32 Utils::calcUnescapedStringSize(p_char8 data, v_int32 size, const char* & error, v_int32& errorPosition) {
|
||||
error = nullptr;
|
||||
v_int32 Utils::calcUnescapedStringSize(p_char8 data, v_int32 size, v_int32& errorCode, v_int32& errorPosition) {
|
||||
errorCode = 0;
|
||||
v_int32 result = 0;
|
||||
v_int32 i = 0;
|
||||
|
||||
@ -87,7 +83,7 @@ v_int32 Utils::calcUnescapedStringSize(p_char8 data, v_int32 size, const char* &
|
||||
if(a == '\\'){
|
||||
|
||||
if(i + 1 == size){
|
||||
error = ERROR_INVALID_ESCAPED_CHAR;
|
||||
errorCode = ERROR_CODE_INVALID_ESCAPED_CHAR;
|
||||
errorPosition = i;
|
||||
return 0;
|
||||
}
|
||||
@ -100,20 +96,20 @@ v_int32 Utils::calcUnescapedStringSize(p_char8 data, v_int32 size, const char* &
|
||||
} else if(b == 'u'){
|
||||
|
||||
if(i + 6 > size){
|
||||
error = ERROR_INVALID_ESCAPED_CHAR;
|
||||
errorCode = ERROR_CODE_INVALID_ESCAPED_CHAR;
|
||||
errorPosition = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(data[i + 2] == '+') { // not JSON standard case
|
||||
if(i + 11 > size){
|
||||
error = ERROR_INVALID_ESCAPED_CHAR;
|
||||
errorCode = ERROR_CODE_INVALID_ESCAPED_CHAR;
|
||||
errorPosition = i;
|
||||
return 0;
|
||||
}
|
||||
v_word32 code;
|
||||
error = encoding::Hex::readWord32(&data[i + 3], code);
|
||||
if(error != nullptr){
|
||||
errorCode = encoding::Hex::readWord32(&data[i + 3], code);
|
||||
if(errorCode != 0){
|
||||
errorPosition = i + 3;
|
||||
return 0;
|
||||
}
|
||||
@ -121,21 +117,21 @@ v_int32 Utils::calcUnescapedStringSize(p_char8 data, v_int32 size, const char* &
|
||||
result += encoding::Unicode::getUtf8CharSequenceLengthForCode(code);
|
||||
} else {
|
||||
v_word16 code;
|
||||
error = encoding::Hex::readWord16(&data[i + 2], code);
|
||||
if(error != nullptr){
|
||||
errorCode = encoding::Hex::readWord16(&data[i + 2], code);
|
||||
if(errorCode != 0){
|
||||
errorPosition = i + 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(code >= 0xD800 && code <= 0xDBFF){
|
||||
if(i + 12 > size){
|
||||
error = ERROR_INVALID_SURROGATE_PAIR;
|
||||
errorCode = ERROR_CODE_INVALID_SURROGATE_PAIR;
|
||||
errorPosition = i;
|
||||
return 0;
|
||||
}
|
||||
v_word16 low;
|
||||
error = encoding::Hex::readWord16(&data[i + 8], low);
|
||||
if(error != nullptr){
|
||||
errorCode = encoding::Hex::readWord16(&data[i + 8], low);
|
||||
if(errorCode != 0){
|
||||
errorPosition = i + 8;
|
||||
return 0;
|
||||
}
|
||||
@ -145,7 +141,7 @@ v_int32 Utils::calcUnescapedStringSize(p_char8 data, v_int32 size, const char* &
|
||||
i += 12;
|
||||
result += encoding::Unicode::getUtf8CharSequenceLengthForCode(bigCode);
|
||||
} else {
|
||||
error = ERROR_INVALID_SURROGATE_PAIR;
|
||||
errorCode = ERROR_CODE_INVALID_SURROGATE_PAIR;
|
||||
errorPosition = i;
|
||||
return 0;
|
||||
}
|
||||
@ -157,7 +153,7 @@ v_int32 Utils::calcUnescapedStringSize(p_char8 data, v_int32 size, const char* &
|
||||
}
|
||||
|
||||
} else {
|
||||
error = ERROR_INVALID_ESCAPED_CHAR;
|
||||
errorCode = ERROR_CODE_INVALID_ESCAPED_CHAR;
|
||||
errorPosition = i;
|
||||
return 0;
|
||||
}
|
||||
@ -322,10 +318,10 @@ void Utils::unescapeStringToBuffer(p_char8 data, v_int32 size, p_char8 resultDat
|
||||
|
||||
}
|
||||
|
||||
oatpp::String Utils::unescapeString(p_char8 data, v_int32 size, const char* & error, v_int32& errorPosition) {
|
||||
oatpp::String Utils::unescapeString(p_char8 data, v_int32 size, v_int32& errorCode, v_int32& errorPosition) {
|
||||
|
||||
v_int32 unescapedSize = calcUnescapedStringSize(data, size, error, errorPosition);
|
||||
if(error != nullptr){
|
||||
v_int32 unescapedSize = calcUnescapedStringSize(data, size, errorCode, errorPosition);
|
||||
if(errorCode != 0){
|
||||
return nullptr;
|
||||
}
|
||||
auto result = String(unescapedSize);
|
||||
@ -338,10 +334,10 @@ oatpp::String Utils::unescapeString(p_char8 data, v_int32 size, const char* & er
|
||||
|
||||
}
|
||||
|
||||
std::string Utils::unescapeStringToStdString(p_char8 data, v_int32 size, const char* & error, v_int32& errorPosition){
|
||||
std::string Utils::unescapeStringToStdString(p_char8 data, v_int32 size, v_int32& errorCode, v_int32& errorPosition){
|
||||
|
||||
v_int32 unescapedSize = calcUnescapedStringSize(data, size, error, errorPosition);
|
||||
if(error != nullptr){
|
||||
v_int32 unescapedSize = calcUnescapedStringSize(data, size, errorCode, errorPosition);
|
||||
if(errorCode != 0){
|
||||
return "";
|
||||
}
|
||||
std::string result;
|
||||
@ -394,11 +390,11 @@ oatpp::String Utils::parseString(ParsingCaret& caret) {
|
||||
|
||||
v_int32 pos = caret.getPosition();
|
||||
|
||||
const char* error;
|
||||
v_int32 errorCode;
|
||||
v_int32 errorPosition;
|
||||
auto result = unescapeString(data, size, error, errorPosition);
|
||||
if(error != nullptr){
|
||||
caret.setError("[oatpp::parser::json::Utils::parseString()]: Error. Call to unescapeString() failed");
|
||||
auto result = unescapeString(data, size, errorCode, errorPosition);
|
||||
if(errorCode != 0){
|
||||
caret.setError("[oatpp::parser::json::Utils::parseString()]: Error. Call to unescapeString() failed", errorCode);
|
||||
caret.setPosition(pos + errorPosition);
|
||||
} else {
|
||||
caret.setPosition(pos + size + 1);
|
||||
@ -421,11 +417,11 @@ std::string Utils::parseStringToStdString(ParsingCaret& caret){
|
||||
|
||||
v_int32 pos = caret.getPosition();
|
||||
|
||||
const char* error;
|
||||
v_int32 errorCode;
|
||||
v_int32 errorPosition;
|
||||
const std::string& result = unescapeStringToStdString(data, size, error, errorPosition);
|
||||
if(error != nullptr){
|
||||
caret.setError("[oatpp::parser::json::Utils::parseStringToStdString()]: Error. Call to unescapeStringToStdString() failed");
|
||||
const std::string& result = unescapeStringToStdString(data, size, errorCode, errorPosition);
|
||||
if(errorCode != 0){
|
||||
caret.setError("[oatpp::parser::json::Utils::parseStringToStdString()]: Error. Call to unescapeStringToStdString() failed", errorCode);
|
||||
caret.setPosition(pos + errorPosition);
|
||||
} else {
|
||||
caret.setPosition(pos + size + 1);
|
||||
|
@ -31,38 +31,27 @@
|
||||
#include <string>
|
||||
|
||||
namespace oatpp { namespace parser { namespace json{
|
||||
|
||||
|
||||
/**
|
||||
* Utility class for json serializer/deserializer.
|
||||
* Used by &id:oatpp::parser::json::mapping::Serializer;, &id:oatpp::parser::json::mapping::Deserializer;.
|
||||
*/
|
||||
class Utils {
|
||||
public:
|
||||
|
||||
/**
|
||||
* ERROR_INVALID_ESCAPED_CHAR = "ERROR_INVALID_ESCAPED_CHAR"
|
||||
*/
|
||||
static const char* const ERROR_INVALID_ESCAPED_CHAR;
|
||||
|
||||
/**
|
||||
* ERROR_INVALID_SURROGATE_PAIR = "ERROR_INVALID_SURROGATE_PAIR"
|
||||
*/
|
||||
static const char* const ERROR_INVALID_SURROGATE_PAIR;
|
||||
|
||||
/**
|
||||
* ERROR_PARSER_QUOTE_EXPECTED = "'\"' - EXPECTED"
|
||||
*/
|
||||
static const char* const ERROR_PARSER_QUOTE_EXPECTED;
|
||||
|
||||
/**
|
||||
* ERROR_CODE_INVALID_ESCAPED_CHAR = 1
|
||||
* ERROR_CODE_INVALID_ESCAPED_CHAR
|
||||
*/
|
||||
static constexpr v_int32 ERROR_CODE_INVALID_ESCAPED_CHAR = 1;
|
||||
|
||||
/**
|
||||
* ERROR_CODE_INVALID_SURROGATE_PAIR = 2
|
||||
* ERROR_CODE_INVALID_SURROGATE_PAIR
|
||||
*/
|
||||
static constexpr v_int32 ERROR_CODE_INVALID_SURROGATE_PAIR = 2;
|
||||
|
||||
/**
|
||||
* "'\"' - EXPECTED"
|
||||
* ERROR_CODE_PARSER_QUOTE_EXPECTED = 3
|
||||
* '\\' - EXPECTED"
|
||||
* ERROR_CODE_PARSER_QUOTE_EXPECTED
|
||||
*/
|
||||
static constexpr v_int32 ERROR_CODE_PARSER_QUOTE_EXPECTED = 3;
|
||||
|
||||
@ -72,19 +61,65 @@ public:
|
||||
private:
|
||||
static v_int32 escapeUtf8Char(p_char8 sequence, p_char8 buffer);
|
||||
static v_int32 calcEscapedStringSize(p_char8 data, v_int32 size, v_int32& safeSize);
|
||||
static v_int32 calcUnescapedStringSize(p_char8 data, v_int32 size, const char* & error, v_int32& errorPosition);
|
||||
static v_int32 calcUnescapedStringSize(p_char8 data, v_int32 size, v_int32& errorCode, v_int32& errorPosition);
|
||||
static void unescapeStringToBuffer(p_char8 data, v_int32 size, p_char8 resultData);
|
||||
static p_char8 preparseString(ParsingCaret& caret, v_int32& size);
|
||||
public:
|
||||
|
||||
/**
|
||||
* if(copyAsOwnData == false && escapedString == initialString) then result string will point to initial data
|
||||
* Escape string as for json standard. <br>
|
||||
* *Note:* if(copyAsOwnData == false && escapedString == initialString) then result string will point to initial data.
|
||||
* @param data - pointer to string to escape.
|
||||
* @param size - data size.
|
||||
* @param copyAsOwnData - see &id:oatpp::base::StrBuffer::StrBuffer;.
|
||||
* @return - &id:oatpp::String;.
|
||||
*/
|
||||
static String escapeString(p_char8 data, v_int32 size, bool copyAsOwnData = true);
|
||||
static String unescapeString(p_char8 data, v_int32 size, const char* & error, v_int32& errorPosition);
|
||||
static std::string unescapeStringToStdString(p_char8 data, v_int32 size,
|
||||
const char* & error, v_int32& errorPosition);
|
||||
|
||||
|
||||
/**
|
||||
* Unescape string as for json standard.
|
||||
* @param data - pointer to string to unescape.
|
||||
* @param size - data size.
|
||||
* @param errorCode - out parameter. Error code <br>
|
||||
* *One of:*<br>
|
||||
* <ul>
|
||||
* <li>&l:Utils::ERROR_CODE_INVALID_ESCAPED_CHAR;</li>
|
||||
* <li>&l:Utils::ERROR_CODE_INVALID_SURROGATE_PAIR;</li>
|
||||
* <li>&l:Utils::ERROR_CODE_PARSER_QUOTE_EXPECTED;</li>
|
||||
* </ul>
|
||||
* @param errorPosition - out parameter. Error position in data.
|
||||
* @return - &id:oatpp::String;.
|
||||
*/
|
||||
static String unescapeString(p_char8 data, v_int32 size, v_int32& errorCode, v_int32& errorPosition);
|
||||
|
||||
/**
|
||||
* Same as &l:Utils::unescapeString (); but return `std::string`.
|
||||
* @param data - pointer to string to unescape.
|
||||
* @param size - data size.
|
||||
* @param errorCode - out parameter. Error code <br>
|
||||
* *One of:*<br>
|
||||
* <ul>
|
||||
* <li>&l:Utils::ERROR_CODE_INVALID_ESCAPED_CHAR;</li>
|
||||
* <li>&l:Utils::ERROR_CODE_INVALID_SURROGATE_PAIR;</li>
|
||||
* <li>&l:Utils::ERROR_CODE_PARSER_QUOTE_EXPECTED;</li>
|
||||
* </ul>
|
||||
* @param errorPosition - out parameter. Error position in data.
|
||||
* @return - &id:oatpp::String;.
|
||||
*/
|
||||
static std::string unescapeStringToStdString(p_char8 data, v_int32 size, v_int32& errorCode, v_int32& errorPosition);
|
||||
|
||||
/**
|
||||
* Parse string enclosed in `"<string>"`.
|
||||
* @param caret - &id:oatpp::parser::Caret;.
|
||||
* @return - &id:oatpp::String;.
|
||||
*/
|
||||
static String parseString(ParsingCaret& caret);
|
||||
|
||||
/**
|
||||
* Parse string enclosed in `"<string>"`.
|
||||
* @param caret - &id:oatpp::parser::Caret;.
|
||||
* @return - `std::string`.
|
||||
*/
|
||||
static std::string parseStringToStdString(ParsingCaret& caret);
|
||||
|
||||
};
|
||||
|
@ -36,7 +36,11 @@
|
||||
#include "oatpp/core/Types.hpp"
|
||||
|
||||
namespace oatpp { namespace parser { namespace json { namespace mapping {
|
||||
|
||||
|
||||
/**
|
||||
* Json deserializer.
|
||||
* Deserializes json to oatpp DTO object. See [Data Transfer Object(DTO) component](https://oatpp.io/docs/components/dto/).
|
||||
*/
|
||||
class Deserializer {
|
||||
public:
|
||||
typedef oatpp::data::mapping::type::Type Type;
|
||||
@ -58,17 +62,31 @@ private:
|
||||
typedef oatpp::data::mapping::type::ListMap<String, AbstractObjectWrapper> AbstractListMap;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Deserializer config.
|
||||
*/
|
||||
class Config : public oatpp::base::Countable {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
Config()
|
||||
{}
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Create shared Config.
|
||||
* @return - `std::shared_ptr` to Config.
|
||||
*/
|
||||
static std::shared_ptr<Config> createShared(){
|
||||
return std::make_shared<Config>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do not fail if unknown field is found in json.
|
||||
* "unknown field" is the one which is not present in DTO object class.
|
||||
*/
|
||||
bool allowUnknownFields = true;
|
||||
|
||||
};
|
||||
@ -151,7 +169,14 @@ private:
|
||||
const std::shared_ptr<Config>& config);
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Deserialize json to oatpp DTO object.
|
||||
* @param caret - &id:oatpp::parser::Caret;.
|
||||
* @param config - &l:Deserializer::Config;.
|
||||
* @param type - &id:oatpp::data::mapping::type::Type;.
|
||||
* @return - &id:oatpp::data::mapping::type::AbstractObjectWrapper; containing deserialized object.
|
||||
*/
|
||||
static AbstractObjectWrapper deserialize(oatpp::parser::Caret& caret,
|
||||
const std::shared_ptr<Config>& config,
|
||||
const Type* const type) {
|
||||
|
@ -24,3 +24,28 @@
|
||||
|
||||
#include "ObjectMapper.hpp"
|
||||
|
||||
namespace oatpp { namespace parser { namespace json { namespace mapping {
|
||||
|
||||
ObjectMapper::ObjectMapper(const std::shared_ptr<Serializer::Config>& pSerializerConfig,
|
||||
const std::shared_ptr<Deserializer::Config>& pDeserializerConfig)
|
||||
: oatpp::data::mapping::ObjectMapper(getMapperInfo())
|
||||
, serializerConfig(pSerializerConfig)
|
||||
, deserializerConfig(pDeserializerConfig)
|
||||
{}
|
||||
|
||||
std::shared_ptr<ObjectMapper> ObjectMapper::createShared(const std::shared_ptr<Serializer::Config>& serializerConfig,
|
||||
const std::shared_ptr<Deserializer::Config>& deserializerConfig){
|
||||
return std::make_shared<ObjectMapper>(serializerConfig, deserializerConfig);
|
||||
}
|
||||
|
||||
void ObjectMapper::write(const std::shared_ptr<oatpp::data::stream::OutputStream>& stream,
|
||||
const oatpp::data::mapping::type::AbstractObjectWrapper& variant) const {
|
||||
Serializer::serialize(stream, variant, serializerConfig);
|
||||
}
|
||||
|
||||
oatpp::data::mapping::type::AbstractObjectWrapper ObjectMapper::read(oatpp::parser::Caret& caret,
|
||||
const oatpp::data::mapping::type::Type* const type) const {
|
||||
return Deserializer::deserialize(caret, deserializerConfig, type);
|
||||
}
|
||||
|
||||
}}}}
|
@ -31,7 +31,12 @@
|
||||
#include "oatpp/core/data/mapping/ObjectMapper.hpp"
|
||||
|
||||
namespace oatpp { namespace parser { namespace json { namespace mapping {
|
||||
|
||||
|
||||
/**
|
||||
* Json ObjectMapper. Serialized/Deserializes oatpp DTO objects to/from JSON.
|
||||
* See [Data Transfer Object(DTO) component](https://oatpp.io/docs/components/dto/). <br>
|
||||
* Extends &id:oatpp::base::Countable;, &id:oatpp::data::mapping::ObjectMapper;.
|
||||
*/
|
||||
class ObjectMapper : public oatpp::base::Countable, public oatpp::data::mapping::ObjectMapper {
|
||||
private:
|
||||
static Info& getMapperInfo() {
|
||||
@ -39,32 +44,50 @@ private:
|
||||
return info;
|
||||
}
|
||||
public:
|
||||
ObjectMapper(const std::shared_ptr<Serializer::Config>& pSerializerConfig,
|
||||
const std::shared_ptr<Deserializer::Config>& pDeserializerConfig)
|
||||
: oatpp::data::mapping::ObjectMapper(getMapperInfo())
|
||||
, serializerConfig(pSerializerConfig)
|
||||
, deserializerConfig(pDeserializerConfig)
|
||||
{}
|
||||
/**
|
||||
* Constructor.
|
||||
* @param pSerializerConfig - &id:oatpp::parser::json::mapping::Serializer::Config;.
|
||||
* @param pDeserializerConfig - &id:oatpp::parser::json::mapping::Deserializer::Config;.
|
||||
*/
|
||||
ObjectMapper(const std::shared_ptr<Serializer::Config>& pSerializerConfig = Serializer::Config::createShared(),
|
||||
const std::shared_ptr<Deserializer::Config>& pDeserializerConfig = Deserializer::Config::createShared());
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Create shared ObjectMapper.
|
||||
* @param serializerConfig - &id:oatpp::parser::json::mapping::Serializer::Config;.
|
||||
* @param deserializerConfig - &id:oatpp::parser::json::mapping::Deserializer::Config;.
|
||||
* @return - `std::shared_ptr` to ObjectMapper.
|
||||
*/
|
||||
static std::shared_ptr<ObjectMapper>
|
||||
createShared(const std::shared_ptr<Serializer::Config>& serializerConfig = Serializer::Config::createShared(),
|
||||
const std::shared_ptr<Deserializer::Config>& deserializerConfig = Deserializer::Config::createShared()){
|
||||
return std::make_shared<ObjectMapper>(serializerConfig, deserializerConfig);
|
||||
}
|
||||
|
||||
const std::shared_ptr<Deserializer::Config>& deserializerConfig = Deserializer::Config::createShared());
|
||||
|
||||
/**
|
||||
* Implementation of &id:oatpp::data::mapping::ObjectMapper::write;.
|
||||
* @param stream - stream to write serializerd data to &id:oatpp::data::stream::OutputStream;.
|
||||
* @param variant - object to serialize &id:oatpp::data::mapping::type::AbstractObjectWrapper;.
|
||||
*/
|
||||
void write(const std::shared_ptr<oatpp::data::stream::OutputStream>& stream,
|
||||
const oatpp::data::mapping::type::AbstractObjectWrapper& variant) const override {
|
||||
Serializer::serialize(stream, variant, serializerConfig);
|
||||
}
|
||||
|
||||
oatpp::data::mapping::type::AbstractObjectWrapper
|
||||
read(oatpp::parser::Caret& caret,
|
||||
const oatpp::data::mapping::type::Type* const type) const override {
|
||||
return Deserializer::deserialize(caret, deserializerConfig, type);
|
||||
}
|
||||
|
||||
const oatpp::data::mapping::type::AbstractObjectWrapper& variant) const override;
|
||||
|
||||
/**
|
||||
* Implementation of &id:oatpp::data::mapping::ObjectMapper::read;.
|
||||
* @param caret - &id:oatpp::parser::Caret;.
|
||||
* @param type - type of resultant object &id:oatpp::data::mapping::type::Type;.
|
||||
* @return - &id:oatpp::data::mapping::type::AbstractObjectWrapper; holding resultant object.
|
||||
*/
|
||||
oatpp::data::mapping::type::AbstractObjectWrapper read(oatpp::parser::Caret& caret,
|
||||
const oatpp::data::mapping::type::Type* const type) const override;
|
||||
|
||||
/**
|
||||
* Serializer config.
|
||||
*/
|
||||
std::shared_ptr<Serializer::Config> serializerConfig;
|
||||
|
||||
/**
|
||||
* Deserializer config.
|
||||
*/
|
||||
std::shared_ptr<Deserializer::Config> deserializerConfig;
|
||||
|
||||
};
|
||||
|
@ -38,7 +38,11 @@
|
||||
#include "oatpp/core/Types.hpp"
|
||||
|
||||
namespace oatpp { namespace parser { namespace json { namespace mapping {
|
||||
|
||||
|
||||
/**
|
||||
* Json Serializer.
|
||||
* Serializes oatpp DTO object to json. See [Data Transfer Object(DTO) component](https://oatpp.io/docs/components/dto/).
|
||||
*/
|
||||
class Serializer {
|
||||
public:
|
||||
typedef oatpp::data::mapping::type::Type Type;
|
||||
@ -56,18 +60,37 @@ public:
|
||||
typedef oatpp::data::mapping::type::ListMap<String, AbstractObjectWrapper> AbstractFieldsMap;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Serializer config.
|
||||
*/
|
||||
class Config : public oatpp::base::Countable {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
Config()
|
||||
{}
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Create shared config.
|
||||
* @return - `std::shared_ptr` to Config.
|
||||
*/
|
||||
static std::shared_ptr<Config> createShared(){
|
||||
return std::make_shared<Config>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Include fields with value == nullptr into serialized json.
|
||||
*/
|
||||
bool includeNullFields = true;
|
||||
|
||||
/**
|
||||
* If `true` - insert string `"<unknown-type>"` in json field value in case unknown field found.
|
||||
* Fail if `false`.
|
||||
* Known types for this serializer are:<br>
|
||||
* (String, Int8, Int16, Int32, Int64, Float32, Float64, Boolean, DTOs, List, Fields).
|
||||
*/
|
||||
bool throwOnUnknownTypes = true;
|
||||
|
||||
};
|
||||
@ -93,7 +116,16 @@ private:
|
||||
static void writeValue(oatpp::data::stream::OutputStream* stream, const AbstractObjectWrapper& polymorph, const std::shared_ptr<Config>& config);
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Serialize DTO object to stream.
|
||||
* @param stream - stream to write serialized object to. &id:oatpp::data::stream::OutputStream;. <br>
|
||||
* **WARNING** Serializer currently does't check call results of &id:oatpp::data::stream::OutputStream::write;.
|
||||
* Meaning that Serializer does not ensures that all data has been transferred successfully. <br>
|
||||
* **USE** output stream with guarantee that all data being successfully written. Like &id:oatpp::data::stream::ChunkedBuffer;.
|
||||
* @param polymorph - DTO object to serialize.
|
||||
* @param config - &l:Serializer::Config;.
|
||||
*/
|
||||
static void serialize(const std::shared_ptr<oatpp::data::stream::OutputStream>& stream,
|
||||
const oatpp::data::mapping::type::AbstractObjectWrapper& polymorph,
|
||||
const std::shared_ptr<Config>& config){
|
||||
|
@ -112,8 +112,8 @@ void ApiClient::addPathQueryParams(oatpp::data::stream::OutputStream* stream,
|
||||
|
||||
}
|
||||
|
||||
oatpp::web::protocol::http::Protocol::Headers ApiClient::convertParamsMap(const std::shared_ptr<StringToParamMap>& params) {
|
||||
oatpp::web::protocol::http::Protocol::Headers result;
|
||||
oatpp::web::protocol::http::Headers ApiClient::convertParamsMap(const std::shared_ptr<StringToParamMap>& params) {
|
||||
oatpp::web::protocol::http::Headers result;
|
||||
if(params) {
|
||||
auto curr = params->getFirstEntry();
|
||||
|
||||
@ -124,6 +124,64 @@ oatpp::web::protocol::http::Protocol::Headers ApiClient::convertParamsMap(const
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
oatpp::String ApiClient::formatPath(const PathPattern& pathPattern,
|
||||
const std::shared_ptr<StringToParamMap>& pathParams,
|
||||
const std::shared_ptr<StringToParamMap>& queryParams)
|
||||
{
|
||||
oatpp::data::stream::ChunkedBuffer stream;
|
||||
formatPath(&stream, pathPattern, pathParams);
|
||||
if(queryParams) {
|
||||
addPathQueryParams(&stream, queryParams);
|
||||
}
|
||||
return stream.toString();
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<RequestExecutor::ConnectionHandle> ApiClient::getConnection() {
|
||||
return m_requestExecutor->getConnection();
|
||||
}
|
||||
|
||||
oatpp::async::Action ApiClient::getConnectionAsync(oatpp::async::AbstractCoroutine* parentCoroutine, RequestExecutor::AsyncConnectionCallback callback) {
|
||||
return m_requestExecutor->getConnectionAsync(parentCoroutine, callback);
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<ApiClient::Response> ApiClient::executeRequest(const oatpp::String& method,
|
||||
const PathPattern& pathPattern,
|
||||
const std::shared_ptr<StringToParamMap>& headers,
|
||||
const std::shared_ptr<StringToParamMap>& pathParams,
|
||||
const std::shared_ptr<StringToParamMap>& queryParams,
|
||||
const std::shared_ptr<RequestExecutor::Body>& body,
|
||||
const std::shared_ptr<RequestExecutor::ConnectionHandle>& connectionHandle) {
|
||||
|
||||
return m_requestExecutor->execute(method,
|
||||
formatPath(pathPattern, pathParams, queryParams),
|
||||
convertParamsMap(headers),
|
||||
body,
|
||||
connectionHandle);
|
||||
|
||||
}
|
||||
|
||||
oatpp::async::Action ApiClient::executeRequestAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
|
||||
AsyncCallback callback,
|
||||
const oatpp::String& method,
|
||||
const PathPattern& pathPattern,
|
||||
const std::shared_ptr<StringToParamMap>& headers,
|
||||
const std::shared_ptr<StringToParamMap>& pathParams,
|
||||
const std::shared_ptr<StringToParamMap>& queryParams,
|
||||
const std::shared_ptr<RequestExecutor::Body>& body,
|
||||
const std::shared_ptr<RequestExecutor::ConnectionHandle>& connectionHandle) {
|
||||
|
||||
return m_requestExecutor->executeAsync(parentCoroutine,
|
||||
callback,
|
||||
method,
|
||||
formatPath(pathPattern, pathParams, queryParams),
|
||||
convertParamsMap(headers),
|
||||
body,
|
||||
connectionHandle);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}}}
|
||||
|
@ -50,7 +50,10 @@
|
||||
#include <unordered_map>
|
||||
|
||||
namespace oatpp { namespace web { namespace client {
|
||||
|
||||
|
||||
/**
|
||||
* ApiClient class provides convenient Retrofit-like interface over the oatpp::web::client::RequestExecutor.
|
||||
*/
|
||||
class ApiClient : public oatpp::base::Countable {
|
||||
public:
|
||||
static constexpr const char* const TAG = "Client";
|
||||
@ -67,18 +70,56 @@ private:
|
||||
oatpp::String
|
||||
> StringToStringMap;
|
||||
public:
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::web::protocol::http::Status;.
|
||||
*/
|
||||
typedef oatpp::web::protocol::http::Status Status;
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::web::protocol::http::Header;.
|
||||
*/
|
||||
typedef oatpp::web::protocol::http::Header Header;
|
||||
public:
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::data::mapping::type::String;.
|
||||
*/
|
||||
typedef oatpp::data::mapping::type::String String;
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::data::mapping::type::Int32;.
|
||||
*/
|
||||
typedef oatpp::data::mapping::type::Int32 Int32;
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::data::mapping::type::Int64;.
|
||||
*/
|
||||
typedef oatpp::data::mapping::type::Int64 Int64;
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::data::mapping::type::Float32;.
|
||||
*/
|
||||
typedef oatpp::data::mapping::type::Float32 Float32;
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::data::mapping::type::Float64;.
|
||||
*/
|
||||
typedef oatpp::data::mapping::type::Float64 Float64;
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::data::mapping::type::Boolean;.
|
||||
*/
|
||||
typedef oatpp::data::mapping::type::Boolean Boolean;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::web::protocol::http::incoming::Response;.
|
||||
*/
|
||||
typedef oatpp::web::protocol::http::incoming::Response Response;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::web::client::RequestExecutor::AsyncCallback;.
|
||||
*/
|
||||
typedef RequestExecutor::AsyncCallback AsyncCallback;
|
||||
protected:
|
||||
|
||||
@ -106,7 +147,7 @@ private:
|
||||
void addPathQueryParams(oatpp::data::stream::OutputStream* stream,
|
||||
const std::shared_ptr<StringToParamMap>& params);
|
||||
|
||||
oatpp::web::protocol::http::Protocol::Headers convertParamsMap(const std::shared_ptr<StringToParamMap>& params);
|
||||
oatpp::web::protocol::http::Headers convertParamsMap(const std::shared_ptr<StringToParamMap>& params);
|
||||
|
||||
protected:
|
||||
|
||||
@ -134,42 +175,33 @@ public:
|
||||
protected:
|
||||
|
||||
virtual oatpp::String formatPath(const PathPattern& pathPattern,
|
||||
const std::shared_ptr<StringToParamMap>& pathParams,
|
||||
const std::shared_ptr<StringToParamMap>& queryParams) {
|
||||
oatpp::data::stream::ChunkedBuffer stream;
|
||||
formatPath(&stream, pathPattern, pathParams);
|
||||
if(queryParams) {
|
||||
addPathQueryParams(&stream, queryParams);
|
||||
}
|
||||
return stream.toString();
|
||||
}
|
||||
const std::shared_ptr<StringToParamMap>& pathParams,
|
||||
const std::shared_ptr<StringToParamMap>& queryParams);
|
||||
|
||||
public:
|
||||
|
||||
virtual std::shared_ptr<RequestExecutor::ConnectionHandle> getConnection() {
|
||||
return m_requestExecutor->getConnection();
|
||||
}
|
||||
|
||||
virtual oatpp::async::Action getConnectionAsync(oatpp::async::AbstractCoroutine* parentCoroutine, RequestExecutor::AsyncConnectionCallback callback) {
|
||||
return m_requestExecutor->getConnectionAsync(parentCoroutine, callback);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call &id:oatpp::web::client::RequestExecutor::getConnection;.
|
||||
* @return - &id:oatpp::web::client::RequestExecutor::ConnectionHandle;.
|
||||
*/
|
||||
virtual std::shared_ptr<RequestExecutor::ConnectionHandle> getConnection();
|
||||
|
||||
/**
|
||||
* Call &id:oatpp::web::client::RequestExecutor::getConnectionAsync;.
|
||||
* @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*.
|
||||
* @param callback - function pointer to asynchronous callback.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
virtual oatpp::async::Action getConnectionAsync(oatpp::async::AbstractCoroutine* parentCoroutine, RequestExecutor::AsyncConnectionCallback callback);
|
||||
|
||||
|
||||
virtual std::shared_ptr<Response> executeRequest(const oatpp::String& method,
|
||||
const PathPattern& pathPattern,
|
||||
const std::shared_ptr<StringToParamMap>& headers,
|
||||
const std::shared_ptr<StringToParamMap>& pathParams,
|
||||
const std::shared_ptr<StringToParamMap>& queryParams,
|
||||
const std::shared_ptr<RequestExecutor::Body>& body,
|
||||
const std::shared_ptr<RequestExecutor::ConnectionHandle>& connectionHandle = nullptr) {
|
||||
|
||||
return m_requestExecutor->execute(method,
|
||||
formatPath(pathPattern, pathParams, queryParams),
|
||||
convertParamsMap(headers),
|
||||
body,
|
||||
connectionHandle);
|
||||
|
||||
}
|
||||
const std::shared_ptr<RequestExecutor::ConnectionHandle>& connectionHandle = nullptr);
|
||||
|
||||
virtual oatpp::async::Action executeRequestAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
|
||||
AsyncCallback callback,
|
||||
@ -179,17 +211,7 @@ public:
|
||||
const std::shared_ptr<StringToParamMap>& pathParams,
|
||||
const std::shared_ptr<StringToParamMap>& queryParams,
|
||||
const std::shared_ptr<RequestExecutor::Body>& body,
|
||||
const std::shared_ptr<RequestExecutor::ConnectionHandle>& connectionHandle = nullptr) {
|
||||
|
||||
return m_requestExecutor->executeAsync(parentCoroutine,
|
||||
callback,
|
||||
method,
|
||||
formatPath(pathPattern, pathParams, queryParams),
|
||||
convertParamsMap(headers),
|
||||
body,
|
||||
connectionHandle);
|
||||
|
||||
}
|
||||
const std::shared_ptr<RequestExecutor::ConnectionHandle>& connectionHandle = nullptr);
|
||||
|
||||
};
|
||||
|
||||
|
@ -40,7 +40,20 @@
|
||||
#include <unistd.h>
|
||||
|
||||
namespace oatpp { namespace web { namespace client {
|
||||
|
||||
|
||||
HttpRequestExecutor::HttpRequestExecutor(const std::shared_ptr<oatpp::network::ClientConnectionProvider>& connectionProvider,
|
||||
const std::shared_ptr<const oatpp::web::protocol::http::incoming::BodyDecoder>& bodyDecoder)
|
||||
: m_connectionProvider(connectionProvider)
|
||||
, m_bodyDecoder(bodyDecoder)
|
||||
{}
|
||||
|
||||
std::shared_ptr<HttpRequestExecutor>
|
||||
HttpRequestExecutor::createShared(const std::shared_ptr<oatpp::network::ClientConnectionProvider>& connectionProvider,
|
||||
const std::shared_ptr<const oatpp::web::protocol::http::incoming::BodyDecoder>& bodyDecoder)
|
||||
{
|
||||
return std::make_shared<HttpRequestExecutor>(connectionProvider, bodyDecoder);
|
||||
}
|
||||
|
||||
std::shared_ptr<HttpRequestExecutor::ConnectionHandle> HttpRequestExecutor::getConnection() {
|
||||
auto connection = m_connectionProvider->getConnection();
|
||||
if(!connection){
|
||||
|
@ -31,7 +31,10 @@
|
||||
#include "oatpp/network/ConnectionProvider.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace client {
|
||||
|
||||
|
||||
/**
|
||||
* Default implementation of &id:oatpp::web::client::RequestExecutor; for making http request.
|
||||
*/
|
||||
class HttpRequestExecutor : public oatpp::base::Countable, public RequestExecutor {
|
||||
private:
|
||||
typedef oatpp::web::protocol::http::Header Header;
|
||||
@ -39,42 +42,90 @@ protected:
|
||||
std::shared_ptr<oatpp::network::ClientConnectionProvider> m_connectionProvider;
|
||||
std::shared_ptr<const oatpp::web::protocol::http::incoming::BodyDecoder> m_bodyDecoder;
|
||||
public:
|
||||
/**
|
||||
* Connection handle for &l:HttpRequestExecutor; <br>
|
||||
* For more details see &id:oatpp::web::client::RequestExecutor::ConnectionHandle;.
|
||||
*/
|
||||
class HttpConnectionHandle : public ConnectionHandle {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param stream - &id:oatpp::network::ConnectionProvider::IOStream;.
|
||||
*/
|
||||
HttpConnectionHandle(const std::shared_ptr<oatpp::network::ConnectionProvider::IOStream>& stream)
|
||||
: connection(stream)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Connection.
|
||||
*/
|
||||
std::shared_ptr<oatpp::network::ConnectionProvider::IOStream> connection;
|
||||
};
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param connectionProvider - &id:oatpp::network::ClientConnectionProvider;.
|
||||
* @param bodyDecoder - &id:oatpp::web::protocol::http::incoming::BodyDecoder;.
|
||||
*/
|
||||
HttpRequestExecutor(const std::shared_ptr<oatpp::network::ClientConnectionProvider>& connectionProvider,
|
||||
const std::shared_ptr<const oatpp::web::protocol::http::incoming::BodyDecoder>& bodyDecoder =
|
||||
std::make_shared<oatpp::web::protocol::http::incoming::SimpleBodyDecoder>())
|
||||
: m_connectionProvider(connectionProvider)
|
||||
, m_bodyDecoder(bodyDecoder)
|
||||
{}
|
||||
std::make_shared<oatpp::web::protocol::http::incoming::SimpleBodyDecoder>());
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Create shared HttpRequestExecutor.
|
||||
* @param connectionProvider - &id:oatpp::network::ClientConnectionProvider;.
|
||||
* @param bodyDecoder - &id:oatpp::web::protocol::http::incoming::BodyDecoder;.
|
||||
* @return - `std::shared_ptr` to `HttpRequestExecutor`.
|
||||
*/
|
||||
static std::shared_ptr<HttpRequestExecutor>
|
||||
createShared(const std::shared_ptr<oatpp::network::ClientConnectionProvider>& connectionProvider,
|
||||
const std::shared_ptr<const oatpp::web::protocol::http::incoming::BodyDecoder>& bodyDecoder =
|
||||
std::make_shared<oatpp::web::protocol::http::incoming::SimpleBodyDecoder>()){
|
||||
return std::make_shared<HttpRequestExecutor>(connectionProvider, bodyDecoder);
|
||||
}
|
||||
|
||||
std::shared_ptr<ConnectionHandle> getConnection() override;
|
||||
|
||||
Action getConnectionAsync(oatpp::async::AbstractCoroutine* parentCoroutine, AsyncConnectionCallback callback) override;
|
||||
|
||||
std::make_shared<oatpp::web::protocol::http::incoming::SimpleBodyDecoder>());
|
||||
|
||||
/**
|
||||
* throws RequestExecutionError
|
||||
* Get &id:oatpp::web::client::RequestExecutor::ConnectionHandle;
|
||||
* @return - ConnectionHandle which is &l:HttpRequestExecutor::HttpConnectionHandle;.
|
||||
*/
|
||||
std::shared_ptr<ConnectionHandle> getConnection() override;
|
||||
|
||||
/**
|
||||
* Same as &l:HttpRequestExecutor::getConnection (); but async.
|
||||
* @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*.
|
||||
* @param callback - function pointer to asynchronous callback.
|
||||
* @return - &id:oatpp::async::Action;
|
||||
*/
|
||||
Action getConnectionAsync(oatpp::async::AbstractCoroutine* parentCoroutine, AsyncConnectionCallback callback) override;
|
||||
|
||||
/**
|
||||
* Execute http request.
|
||||
* @param method - method ex: ["GET", "POST", "PUT", etc.].
|
||||
* @param path - path to resource.
|
||||
* @param headers - headers map &id:oatpp::web::client::RequestExecutor::Headers;.
|
||||
* @param body - `std::shared_ptr` to &id:oatpp::web::client::RequestExecutor::Body; object.
|
||||
* @param connectionHandle - ConnectionHandle obtain in call to &l:HttpRequestExecutor::getConnection ();.
|
||||
* @return - &id:oatpp::web::protocol::http::incoming::Response;.
|
||||
* @throws - &id:oatpp::web::client::RequestExecutor::RequestExecutionError;
|
||||
*/
|
||||
std::shared_ptr<Response> execute(const String& method,
|
||||
const String& path,
|
||||
const Headers& headers,
|
||||
const std::shared_ptr<Body>& body,
|
||||
const std::shared_ptr<ConnectionHandle>& connectionHandle = nullptr) override;
|
||||
|
||||
|
||||
/**
|
||||
* Same as &l:HttpRequestExecutor::execute (); but Async.
|
||||
* @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*.
|
||||
* @param callback - function pointer to asynchronous callback.
|
||||
* @param method - method ex: ["GET", "POST", "PUT", etc.].
|
||||
* @param path - path to resource.
|
||||
* @param headers - headers map &id:oatpp::web::client::RequestExecutor::Headers;.
|
||||
* @param body - `std::shared_ptr` to &id:oatpp::web::client::RequestExecutor::Body; object.
|
||||
* @param connectionHandle - ConnectionHandle obtain in call to &l:HttpRequestExecutor::getConnection ();.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
Action executeAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
|
||||
AsyncCallback callback,
|
||||
const String& method,
|
||||
|
@ -23,3 +23,26 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "RequestExecutor.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace client {
|
||||
|
||||
RequestExecutor::RequestExecutionError::RequestExecutionError(v_int32 errorCode, const char* message, v_int32 readErrorCode)
|
||||
: std::runtime_error(message)
|
||||
, m_errorCode(errorCode)
|
||||
, m_message(message)
|
||||
, m_readErrorCode(readErrorCode)
|
||||
{}
|
||||
|
||||
v_int32 RequestExecutor::RequestExecutionError::getErrorCode() const {
|
||||
return m_errorCode;
|
||||
}
|
||||
|
||||
const char* RequestExecutor::RequestExecutionError::getMessage() const {
|
||||
return m_message;
|
||||
}
|
||||
|
||||
v_int32 RequestExecutor::RequestExecutionError::getReadErrorCode() const {
|
||||
return m_readErrorCode;
|
||||
}
|
||||
|
||||
}}}
|
@ -30,19 +30,41 @@
|
||||
#include "oatpp/web/protocol/http/Http.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace client {
|
||||
|
||||
|
||||
/**
|
||||
* Abstract RequestExecutor.
|
||||
* RequestExecutor is class responsible for making remote requests.
|
||||
*/
|
||||
class RequestExecutor {
|
||||
public:
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::String;.
|
||||
*/
|
||||
typedef oatpp::String String;
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::async::Action;.
|
||||
*/
|
||||
typedef oatpp::async::Action Action;
|
||||
public:
|
||||
typedef oatpp::web::protocol::http::Protocol::Headers Headers;
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::web::protocol::http::Headers;.
|
||||
*/
|
||||
typedef oatpp::web::protocol::http::Headers Headers;
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::web::protocol::http::incoming::Response;.
|
||||
*/
|
||||
typedef oatpp::web::protocol::http::incoming::Response Response;
|
||||
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::web::protocol::http::outgoing::Body;.
|
||||
*/
|
||||
typedef oatpp::web::protocol::http::outgoing::Body Body;
|
||||
public:
|
||||
|
||||
/**
|
||||
* ConnectionHandle is always specific to a RequestExecutor
|
||||
* ConnectionHandle is always specific to a RequestExecutor.
|
||||
* You can't pass ConnectionHandle retrieved by one RequestExecutor implementation
|
||||
* to another
|
||||
*/
|
||||
@ -55,65 +77,116 @@ public:
|
||||
typedef Action (oatpp::async::AbstractCoroutine::*AsyncCallback)(const std::shared_ptr<Response>&);
|
||||
typedef Action (oatpp::async::AbstractCoroutine::*AsyncConnectionCallback)(const std::shared_ptr<ConnectionHandle>&);
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Class representing Request Execution Error.
|
||||
*/
|
||||
class RequestExecutionError : public std::runtime_error {
|
||||
public:
|
||||
/**
|
||||
* Error code for "can't connect" error.
|
||||
*/
|
||||
constexpr static const v_int32 ERROR_CODE_CANT_CONNECT = 1;
|
||||
|
||||
/**
|
||||
* Error code for "can't parse starting line" error.
|
||||
*/
|
||||
constexpr static const v_int32 ERROR_CODE_CANT_PARSE_STARTING_LINE = 2;
|
||||
|
||||
/**
|
||||
* Error code for "can't parse headers" error.
|
||||
*/
|
||||
constexpr static const v_int32 ERROR_CODE_CANT_PARSE_HEADERS = 3;
|
||||
|
||||
/**
|
||||
* Error code for "can't read response" error.
|
||||
*/
|
||||
constexpr static const v_int32 ERROR_CODE_CANT_READ_RESPONSE = 4;
|
||||
|
||||
/**
|
||||
* Error code for "no response" error.
|
||||
*/
|
||||
constexpr static const v_int32 ERROR_CODE_NO_RESPONSE = 5;
|
||||
private:
|
||||
v_int32 m_errorCode;
|
||||
const char* m_message;
|
||||
v_int32 m_readErrorCode;
|
||||
public:
|
||||
|
||||
RequestExecutionError(v_int32 errorCode, const char* message, v_int32 readErrorCode = 0)
|
||||
:std::runtime_error(message)
|
||||
, m_errorCode(errorCode)
|
||||
, m_message(message)
|
||||
, m_readErrorCode(readErrorCode)
|
||||
{}
|
||||
|
||||
v_int32 getErrorCode() const {
|
||||
return m_errorCode;
|
||||
}
|
||||
|
||||
const char* getMessage() const {
|
||||
return m_message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param errorCode - error code.
|
||||
* @param message - error message.
|
||||
* @param readErrorCode - io error code.
|
||||
*/
|
||||
RequestExecutionError(v_int32 errorCode, const char* message, v_int32 readErrorCode = 0);
|
||||
|
||||
/**
|
||||
* Get error code.
|
||||
* @return - error code.
|
||||
*/
|
||||
v_int32 getErrorCode() const;
|
||||
|
||||
/**
|
||||
* Get error message.
|
||||
* @return - error message.
|
||||
*/
|
||||
const char* getMessage() const;
|
||||
|
||||
/**
|
||||
* This value is valid if errorCode == ERROR_CODE_CANT_READ_RESPONSE
|
||||
* This value is valid if errorCode == &l:RequestExecutor::RequestExecutionError::ERROR_CODE_CANT_READ_RESPONSE; <br>
|
||||
* For more information about the read error you get check out:
|
||||
* - oatpp::data::stream::IOStream for possible error codes
|
||||
* - implementation of Connection provided by your ConnectionProvider for implementation-specific behaviour
|
||||
* <ul>
|
||||
* <li>&id:oatpp::data::stream::IOStream; for possible error codes.</li>
|
||||
* <li>Implementation-specific behaviour of corresponding Connection and ConnectionProvider.</li>
|
||||
* </ul>
|
||||
*/
|
||||
v_int32 getReadErrorCode() const {
|
||||
return m_readErrorCode;
|
||||
}
|
||||
v_int32 getReadErrorCode() const;
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Obtain ConnectionHandle which then can be passed to execute()
|
||||
* Obtain &l:RequestExecutor::ConnectionHandle; which then can be passed to &l:RequestExecutor::execute ();.
|
||||
* @return std::shared_ptr to &l:RequestExecutor::ConnectionHandle;.
|
||||
*/
|
||||
virtual std::shared_ptr<ConnectionHandle> getConnection() = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Same as getConnection but Async
|
||||
* Same as &l:RequestExecutor::getConnection (); but Async.
|
||||
* @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*.
|
||||
* @param callback - function pointer to asynchronous callback.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
virtual Action getConnectionAsync(oatpp::async::AbstractCoroutine* parentCoroutine, AsyncConnectionCallback callback) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Execute request.
|
||||
* @param method - method ex: ["GET", "POST", "PUT", etc.].
|
||||
* @param path - path to resource.
|
||||
* @param headers - headers map &l:RequestExecutor::Headers;.
|
||||
* @param body - `std::shared_ptr` to &l:RequestExecutor::Body; object.
|
||||
* @param connectionHandle - &l:RequestExecutor::ConnectionHandle;
|
||||
* @return - &id:oatpp::web::protocol::http::incoming::Response;.
|
||||
*/
|
||||
virtual std::shared_ptr<Response> execute(const String& method,
|
||||
const String& path,
|
||||
const Headers& headers,
|
||||
const std::shared_ptr<Body>& body,
|
||||
const std::shared_ptr<ConnectionHandle>& connectionHandle = nullptr) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Same as &l:RequestExecutor::execute (); but Async.
|
||||
* @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*.
|
||||
* @param callback - function pointer to asynchronous callback.
|
||||
* @param method - method ex: ["GET", "POST", "PUT", etc.].
|
||||
* @param path - path to resource.
|
||||
* @param headers - headers map &l:RequestExecutor::Headers;.
|
||||
* @param body - `std::shared_ptr` to &l:RequestExecutor::Body; object.
|
||||
* @param connectionHandle - &l:RequestExecutor::ConnectionHandle;
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
virtual Action executeAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
|
||||
AsyncCallback callback,
|
||||
const String& method,
|
||||
|
@ -28,35 +28,75 @@
|
||||
#include "oatpp/core/data/IODefinitions.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace protocol {
|
||||
|
||||
|
||||
/**
|
||||
* Communication Error
|
||||
*/
|
||||
class CommunicationError : public std::runtime_error {
|
||||
private:
|
||||
oatpp::data::v_io_size m_ioStatus;
|
||||
oatpp::String m_message;
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param ioStatus - I/O error. See &id:oatpp::data::v_io_size;.
|
||||
* @param message - error message.
|
||||
*/
|
||||
CommunicationError(oatpp::data::v_io_size ioStatus, const oatpp::String& message);
|
||||
|
||||
/**
|
||||
* Get I/O error. See &id:oatpp::data::v_io_size;.
|
||||
* @return &id:oatpp::data::v_io_size;.
|
||||
*/
|
||||
oatpp::data::v_io_size getIOStatus();
|
||||
|
||||
/**
|
||||
* Get error message.
|
||||
* @return - error message.
|
||||
*/
|
||||
oatpp::String& getMessage();
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Protocol Error template.
|
||||
* @tparam Status - arbitrary data type.
|
||||
*/
|
||||
template<class Status>
|
||||
class ProtocolError : public CommunicationError {
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Protocol Error Info.
|
||||
*/
|
||||
struct Info {
|
||||
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
Info()
|
||||
: ioStatus(0)
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param pIOStatus - I/O level error. See &id:oatpp::data::v_io_size;.
|
||||
* @param pStatus - configurable arbitrary data type.
|
||||
*/
|
||||
Info(oatpp::data::v_io_size pIOStatus, const Status& pStatus)
|
||||
: ioStatus(pIOStatus)
|
||||
, status(pStatus)
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* Get I/O level error.
|
||||
*/
|
||||
oatpp::data::v_io_size ioStatus;
|
||||
|
||||
/**
|
||||
* Configurable arbitrary data type.
|
||||
*/
|
||||
Status status;
|
||||
|
||||
};
|
||||
@ -64,12 +104,21 @@ public:
|
||||
private:
|
||||
Info m_info;
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param info - &l:ProtocolError::Info ;.
|
||||
* @param message - error message.
|
||||
*/
|
||||
ProtocolError(const Info& info, const oatpp::String& message)
|
||||
: CommunicationError(info.ioStatus, message)
|
||||
, m_info(info)
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* Get error info.
|
||||
* @return - error info.
|
||||
*/
|
||||
Info getInfo() {
|
||||
return m_info;
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ ContentRange ContentRange::parse(const oatpp::String& str) {
|
||||
return parse(caret);
|
||||
}
|
||||
|
||||
oatpp::data::share::StringKeyLabelCI_FAST Protocol::parseHeaderNameLabel(const std::shared_ptr<oatpp::base::StrBuffer>& headersText,
|
||||
oatpp::data::share::StringKeyLabelCI_FAST Parser::parseHeaderNameLabel(const std::shared_ptr<oatpp::base::StrBuffer>& headersText,
|
||||
oatpp::parser::Caret& caret) {
|
||||
p_char8 data = caret.getData();
|
||||
for(v_int32 i = caret.getPosition(); i < caret.getDataSize(); i++) {
|
||||
@ -251,7 +251,7 @@ oatpp::data::share::StringKeyLabelCI_FAST Protocol::parseHeaderNameLabel(const s
|
||||
return oatpp::data::share::StringKeyLabelCI_FAST(nullptr, nullptr, 0);
|
||||
}
|
||||
|
||||
void Protocol::parseRequestStartingLine(RequestStartingLine& line,
|
||||
void Parser::parseRequestStartingLine(RequestStartingLine& line,
|
||||
const std::shared_ptr<oatpp::base::StrBuffer>& headersText,
|
||||
oatpp::parser::Caret& caret,
|
||||
Status& error) {
|
||||
@ -285,7 +285,7 @@ void Protocol::parseRequestStartingLine(RequestStartingLine& line,
|
||||
|
||||
}
|
||||
|
||||
void Protocol::parseResponseStartingLine(ResponseStartingLine& line,
|
||||
void Parser::parseResponseStartingLine(ResponseStartingLine& line,
|
||||
const std::shared_ptr<oatpp::base::StrBuffer>& headersText,
|
||||
oatpp::parser::Caret& caret,
|
||||
Status& error) {
|
||||
@ -312,7 +312,7 @@ void Protocol::parseResponseStartingLine(ResponseStartingLine& line,
|
||||
|
||||
}
|
||||
|
||||
void Protocol::parseOneHeader(Headers& headers,
|
||||
void Parser::parseOneHeader(Headers& headers,
|
||||
const std::shared_ptr<oatpp::base::StrBuffer>& headersText,
|
||||
oatpp::parser::Caret& caret,
|
||||
Status& error) {
|
||||
@ -335,7 +335,7 @@ void Protocol::parseOneHeader(Headers& headers,
|
||||
}
|
||||
}
|
||||
|
||||
void Protocol::parseHeaders(Headers& headers,
|
||||
void Parser::parseHeaders(Headers& headers,
|
||||
const std::shared_ptr<oatpp::base::StrBuffer>& headersText,
|
||||
oatpp::parser::Caret& caret,
|
||||
Status& error) {
|
||||
|
@ -38,88 +38,349 @@
|
||||
#include <unordered_map>
|
||||
|
||||
namespace oatpp { namespace web { namespace protocol { namespace http {
|
||||
|
||||
|
||||
/**
|
||||
* Http status.
|
||||
*/
|
||||
class Status{
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Continue.
|
||||
*/
|
||||
static const Status CODE_100;// Continue
|
||||
|
||||
/**
|
||||
* Switching Protocols.
|
||||
*/
|
||||
static const Status CODE_101;// Switching
|
||||
|
||||
/**
|
||||
* Processing.
|
||||
*/
|
||||
static const Status CODE_102;// Processing
|
||||
|
||||
|
||||
/**
|
||||
* OK.
|
||||
*/
|
||||
static const Status CODE_200;// OK
|
||||
|
||||
/**
|
||||
* Created.
|
||||
*/
|
||||
static const Status CODE_201;// Created
|
||||
|
||||
/**
|
||||
* Accepted.
|
||||
*/
|
||||
static const Status CODE_202;// Accepted
|
||||
|
||||
/**
|
||||
* Non-Authoritative Information.
|
||||
*/
|
||||
static const Status CODE_203;// Non-Authoritative Information
|
||||
|
||||
/**
|
||||
* No Content.
|
||||
*/
|
||||
static const Status CODE_204;// No Content
|
||||
|
||||
/**
|
||||
* Reset Content.
|
||||
*/
|
||||
static const Status CODE_205;// Reset Content
|
||||
|
||||
/**
|
||||
* Partial Content.
|
||||
*/
|
||||
static const Status CODE_206;// Partial Content
|
||||
|
||||
/**
|
||||
* Multi-Status.
|
||||
*/
|
||||
static const Status CODE_207;// Multi-Status
|
||||
|
||||
/**
|
||||
* IM Used.
|
||||
*/
|
||||
static const Status CODE_226;// IM Used
|
||||
|
||||
|
||||
/**
|
||||
* Multiple Choices.
|
||||
*/
|
||||
static const Status CODE_300;// Multiple Choices
|
||||
|
||||
/**
|
||||
* Moved Permanently.
|
||||
*/
|
||||
static const Status CODE_301;// Moved Permanently
|
||||
|
||||
/**
|
||||
* Moved Temporarily.
|
||||
*/
|
||||
static const Status CODE_302;// Moved Temporarily
|
||||
|
||||
/**
|
||||
* See Other.
|
||||
*/
|
||||
static const Status CODE_303;// See Other
|
||||
|
||||
/**
|
||||
* Not Modified.
|
||||
*/
|
||||
static const Status CODE_304;// Not Modified
|
||||
|
||||
/**
|
||||
* Use Proxy.
|
||||
*/
|
||||
static const Status CODE_305;// Use Proxy
|
||||
|
||||
/**
|
||||
* Reserved.
|
||||
*/
|
||||
static const Status CODE_306;// Reserved
|
||||
|
||||
/**
|
||||
* Temporary Redirect.
|
||||
*/
|
||||
static const Status CODE_307;// Temporary Redirect
|
||||
|
||||
|
||||
/**
|
||||
* Bad Request.
|
||||
*/
|
||||
static const Status CODE_400;// Bad Request
|
||||
|
||||
/**
|
||||
* Unauthorized.
|
||||
*/
|
||||
static const Status CODE_401;// Unauthorized
|
||||
|
||||
/**
|
||||
* Payment Required.
|
||||
*/
|
||||
static const Status CODE_402;// Payment Required
|
||||
|
||||
/**
|
||||
* Forbidden.
|
||||
*/
|
||||
static const Status CODE_403;// Forbidden
|
||||
|
||||
/**
|
||||
* Not Found.
|
||||
*/
|
||||
static const Status CODE_404;// Not Found
|
||||
|
||||
/**
|
||||
* Method Not Allowed.
|
||||
*/
|
||||
static const Status CODE_405;// Method Not Allowed
|
||||
|
||||
/**
|
||||
* Not Acceptable.
|
||||
*/
|
||||
static const Status CODE_406;// Not Acceptable
|
||||
|
||||
/**
|
||||
* Proxy Authentication Required.
|
||||
*/
|
||||
static const Status CODE_407;// Proxy Authentication Required
|
||||
|
||||
/**
|
||||
* Request Timeout.
|
||||
*/
|
||||
static const Status CODE_408;// Request Timeout
|
||||
|
||||
/**
|
||||
* Conflict.
|
||||
*/
|
||||
static const Status CODE_409;// Conflict
|
||||
|
||||
/**
|
||||
* Gone
|
||||
*/
|
||||
static const Status CODE_410;// Gone
|
||||
|
||||
/**
|
||||
* Length Required.
|
||||
*/
|
||||
static const Status CODE_411;// Length Required
|
||||
|
||||
/**
|
||||
* Precondition Failed.
|
||||
*/
|
||||
static const Status CODE_412;// Precondition Failed
|
||||
|
||||
/**
|
||||
* Request Entity Too Large.
|
||||
*/
|
||||
static const Status CODE_413;// Request Entity Too Large
|
||||
|
||||
/**
|
||||
* Request-URI Too Large.
|
||||
*/
|
||||
static const Status CODE_414;// Request-URI Too Large
|
||||
|
||||
/**
|
||||
* Unsupported Media Type.
|
||||
*/
|
||||
static const Status CODE_415;// Unsupported Media Type
|
||||
|
||||
/**
|
||||
* Requested Range Not Satisfiable.
|
||||
*/
|
||||
static const Status CODE_416;// Requested Range Not Satisfiable
|
||||
|
||||
/**
|
||||
* Expectation Failed.
|
||||
*/
|
||||
static const Status CODE_417;// Expectation Failed
|
||||
|
||||
/**
|
||||
* Unprocessable Entity.
|
||||
*/
|
||||
static const Status CODE_422;// Unprocessable Entity
|
||||
|
||||
/**
|
||||
* Locked.
|
||||
*/
|
||||
static const Status CODE_423;// Locked
|
||||
|
||||
/**
|
||||
* Failed Dependency.
|
||||
*/
|
||||
static const Status CODE_424;// Failed Dependency
|
||||
|
||||
/**
|
||||
* Unordered Collection.
|
||||
*/
|
||||
static const Status CODE_425;// Unordered Collection
|
||||
|
||||
/**
|
||||
* Upgrade Required.
|
||||
*/
|
||||
static const Status CODE_426;// Upgrade Required
|
||||
|
||||
/**
|
||||
* Precondition Required.
|
||||
*/
|
||||
static const Status CODE_428;// Precondition Required
|
||||
|
||||
/**
|
||||
* Too Many Requests.
|
||||
*/
|
||||
static const Status CODE_429;// Too Many Requests
|
||||
|
||||
/**
|
||||
* Request Header Fields Too Large.
|
||||
*/
|
||||
static const Status CODE_431;// Request Header Fields Too Large
|
||||
|
||||
/**
|
||||
* Requested host unavailable.
|
||||
*/
|
||||
static const Status CODE_434;// Requested host unavailable
|
||||
|
||||
/**
|
||||
* Close connection withot sending headers.
|
||||
*/
|
||||
static const Status CODE_444;// Close connection withot sending headers
|
||||
|
||||
/**
|
||||
* Retry With.
|
||||
*/
|
||||
static const Status CODE_449;// Retry With
|
||||
|
||||
/**
|
||||
* Unavailable For Legal Reasons.
|
||||
*/
|
||||
static const Status CODE_451;// Unavailable For Legal Reasons
|
||||
|
||||
|
||||
/**
|
||||
* Internal Server Error.
|
||||
*/
|
||||
static const Status CODE_500;// Internal Server Error
|
||||
|
||||
/**
|
||||
* Not Implemented.
|
||||
*/
|
||||
static const Status CODE_501;// Not Implemented
|
||||
|
||||
/**
|
||||
* Bad Gateway.
|
||||
*/
|
||||
static const Status CODE_502;// Bad Gateway
|
||||
|
||||
/**
|
||||
* Service Unavailable.
|
||||
*/
|
||||
static const Status CODE_503;// Service Unavailable
|
||||
|
||||
/**
|
||||
* Gateway Timeout.
|
||||
*/
|
||||
static const Status CODE_504;// Gateway Timeout
|
||||
|
||||
/**
|
||||
* HTTP Version Not Supported.
|
||||
*/
|
||||
static const Status CODE_505;// HTTP Version Not Supported
|
||||
|
||||
/**
|
||||
* Variant Also Negotiates.
|
||||
*/
|
||||
static const Status CODE_506;// Variant Also Negotiates
|
||||
|
||||
/**
|
||||
* Insufficient Storage.
|
||||
*/
|
||||
static const Status CODE_507;// Insufficient Storage
|
||||
|
||||
/**
|
||||
* Loop Detected.
|
||||
*/
|
||||
static const Status CODE_508;// Loop Detected
|
||||
|
||||
/**
|
||||
* Bandwidth Limit Exceeded.
|
||||
*/
|
||||
static const Status CODE_509;// Bandwidth Limit Exceeded
|
||||
|
||||
/**
|
||||
* Not Extended.
|
||||
*/
|
||||
static const Status CODE_510;// Not Extended
|
||||
|
||||
/**
|
||||
* Network Authentication Required.
|
||||
*/
|
||||
static const Status CODE_511;// Network Authentication Required
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
Status()
|
||||
: code(0)
|
||||
, description(nullptr)
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param pCode - status code.
|
||||
* @param pDesc - description.
|
||||
*/
|
||||
Status(v_int32 pCode, const char* pDesc)
|
||||
: code(pCode)
|
||||
, description(pDesc)
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* Status code.
|
||||
*/
|
||||
v_int32 code;
|
||||
|
||||
/**
|
||||
* Description.
|
||||
*/
|
||||
const char* description;
|
||||
|
||||
bool operator==(const Status& other) const {
|
||||
@ -131,25 +392,51 @@ public:
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* HttpError extends &id:oatpp::web::protocol::ProtocolError;<&l:Status;>.
|
||||
*/
|
||||
class HttpError : public protocol::ProtocolError<Status> {
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param info
|
||||
* @param message
|
||||
*/
|
||||
HttpError(const Info& info, const oatpp::String& message)
|
||||
: protocol::ProtocolError<Status>(info, message)
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param status
|
||||
* @param message
|
||||
*/
|
||||
HttpError(const Status& status, const oatpp::String& message)
|
||||
: protocol::ProtocolError<Status>(Info(0, status), message)
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Throw &l:HttpError; if assertion failed.
|
||||
* @param COND - boolean statement. If evaluates to false - throw error.
|
||||
* @param STATUS - &l:Status;.
|
||||
* @param MESSAGE - String message.
|
||||
*/
|
||||
#define OATPP_ASSERT_HTTP(COND, STATUS, MESSAGE) \
|
||||
if(!(COND)) { throw oatpp::web::protocol::http::HttpError(STATUS, MESSAGE); }
|
||||
|
||||
|
||||
/**
|
||||
* Collection of HTTP Header constants.
|
||||
*/
|
||||
class Header {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Possible values for headers.
|
||||
*/
|
||||
class Value {
|
||||
public:
|
||||
static const char* const CONNECTION_CLOSE;
|
||||
@ -247,43 +534,118 @@ public:
|
||||
static ContentRange parse(const oatpp::String& str);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Struct representing HTTP request starting line.
|
||||
* Example request starting line: `GET /path/to/resource/ HTTP/1.1`.
|
||||
*/
|
||||
struct RequestStartingLine {
|
||||
/**
|
||||
* Method as &id:oatpp::data::share::StringKeyLabel;.
|
||||
*/
|
||||
oatpp::data::share::StringKeyLabel method; // GET, POST ...
|
||||
|
||||
/**
|
||||
* Path as &id:oatpp::data::share::StringKeyLabel;.
|
||||
*/
|
||||
oatpp::data::share::StringKeyLabel path;
|
||||
|
||||
/**
|
||||
* Protocol as &id:oatpp::data::share::StringKeyLabel;.
|
||||
*/
|
||||
oatpp::data::share::StringKeyLabel protocol;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Struct representing HTTP response starting line.
|
||||
* Example response starting line: `HTTP/1.1 200 OK`.
|
||||
*/
|
||||
struct ResponseStartingLine {
|
||||
/**
|
||||
* Protocol as &id:oatpp::data::share::StringKeyLabel;.
|
||||
*/
|
||||
oatpp::data::share::StringKeyLabel protocol;
|
||||
|
||||
/**
|
||||
* Status code as v_int32.
|
||||
*/
|
||||
v_int32 statusCode;
|
||||
|
||||
/**
|
||||
* Description as &id:oatpp::data::share::StringKeyLabel;.
|
||||
*/
|
||||
oatpp::data::share::StringKeyLabel description;
|
||||
};
|
||||
|
||||
class Protocol {
|
||||
public:
|
||||
typedef std::unordered_map<oatpp::data::share::StringKeyLabelCI_FAST, oatpp::data::share::StringKeyLabel> Headers;
|
||||
typedef std::unordered_map<oatpp::data::share::StringKeyLabel, oatpp::data::share::StringKeyLabel> QueryParams;
|
||||
|
||||
/**
|
||||
* Typedef for headers map. Headers map key is case-insensitive.
|
||||
* `std::unordered_map` of &id:oatpp::data::share::StringKeyLabelCI_FAST; and &id:oatpp::data::share::StringKeyLabel;.
|
||||
*/
|
||||
typedef std::unordered_map<oatpp::data::share::StringKeyLabelCI_FAST, oatpp::data::share::StringKeyLabel> Headers;
|
||||
|
||||
/**
|
||||
* Typedef for query parameters map.
|
||||
* `std::unordered_map` of &id:oatpp::data::share::StringKeyLabel; and &id:oatpp::data::share::StringKeyLabel;.
|
||||
*/
|
||||
typedef std::unordered_map<oatpp::data::share::StringKeyLabel, oatpp::data::share::StringKeyLabel> QueryParams;
|
||||
|
||||
/**
|
||||
* Oatpp Http parser.
|
||||
*/
|
||||
class Parser {
|
||||
private:
|
||||
static oatpp::data::share::StringKeyLabelCI_FAST parseHeaderNameLabel(const std::shared_ptr<oatpp::base::StrBuffer>& headersText,
|
||||
oatpp::parser::Caret& caret);
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Parse &l:RequestStartingLine;.
|
||||
* @param line - &l:RequestStartingLine;. Values will be set to line's fields.
|
||||
* @param headersText - `std::shared_ptr` to &id:oatpp::base::StrBuffer; needed as a "memory handle" for
|
||||
* &l:RequestStartingLine; fields. See &id:oatpp::data::share::MemoryLabel;.
|
||||
* @param caret - &id:oatpp::parser::Caret;.
|
||||
* @param error - out parameter &l:Status;.
|
||||
*/
|
||||
static void parseRequestStartingLine(RequestStartingLine& line,
|
||||
const std::shared_ptr<oatpp::base::StrBuffer>& headersText,
|
||||
oatpp::parser::Caret& caret,
|
||||
Status& error);
|
||||
|
||||
|
||||
/**
|
||||
* Parse &l:ResponseStartingLine;.
|
||||
* @param line - &l:ResponseStartingLine;. Values will be set to line's fields.
|
||||
* @param headersText - `std::shared_ptr` to &id:oatpp::base::StrBuffer; needed as a "memory handle" for
|
||||
* &l:ResponseStartingLine; fields. See &id:oatpp::data::share::MemoryLabel;.
|
||||
* @param caret - &id:oatpp::parser::Caret;.
|
||||
* @param error - out parameter &l:Status;.
|
||||
*/
|
||||
static void parseResponseStartingLine(ResponseStartingLine& line,
|
||||
const std::shared_ptr<oatpp::base::StrBuffer>& headersText,
|
||||
oatpp::parser::Caret& caret,
|
||||
Status& error);
|
||||
|
||||
|
||||
/**
|
||||
* Parse one header line. Example of the header line:
|
||||
* `"Content-Type: application/json\r\n"`.
|
||||
* @param headers - &l:Headers; map to put parsed header to.
|
||||
* @param headersText - `std::shared_ptr` to &id:oatpp::base::StrBuffer; needed as a "memory handle" for
|
||||
* &l:Headers; values. See &id:oatpp::data::share::MemoryLabel;.
|
||||
* @param caret - &id:oatpp::parser::Caret;.
|
||||
* @param error - out parameter &l:Status;.
|
||||
*/
|
||||
static void parseOneHeader(Headers& headers,
|
||||
const std::shared_ptr<oatpp::base::StrBuffer>& headersText,
|
||||
oatpp::parser::Caret& caret,
|
||||
Status& error);
|
||||
|
||||
|
||||
/**
|
||||
* Parse HTTP headers to &l:Headers; map.
|
||||
* @param headers - &l:Headers; map to put parsed headers to.
|
||||
* @param headersText - `std::shared_ptr` to &id:oatpp::base::StrBuffer; needed as a "memory handle" for
|
||||
* &l:Headers; values. See &id:oatpp::data::share::MemoryLabel;.
|
||||
* @param caret - &id:oatpp::parser::Caret;.
|
||||
* @param error - out parameter &l:Status;.
|
||||
*/
|
||||
static void parseHeaders(Headers& headers,
|
||||
const std::shared_ptr<oatpp::base::StrBuffer>& headersText,
|
||||
oatpp::parser::Caret& caret,
|
||||
|
@ -29,7 +29,7 @@
|
||||
namespace oatpp { namespace web { namespace protocol { namespace http { namespace incoming {
|
||||
|
||||
BodyDecoder::ToStringDecoder::ToStringDecoder(const BodyDecoder* decoder,
|
||||
const Protocol::Headers& headers,
|
||||
const Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream)
|
||||
: m_decoder(decoder)
|
||||
, m_headers(headers)
|
||||
|
@ -30,20 +30,26 @@
|
||||
#include "oatpp/core/async/Coroutine.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace protocol { namespace http { namespace incoming {
|
||||
|
||||
|
||||
/**
|
||||
* Abstract BodyDecoder.
|
||||
* Body Decoder is responsible to decode body of incoming request.
|
||||
* For example if you receive chunked-encoded body, you have to decode it in order to get "plain" body.
|
||||
* You may extend this class in order to customize body-decoding process.
|
||||
*/
|
||||
class BodyDecoder {
|
||||
private:
|
||||
|
||||
|
||||
class ToStringDecoder : public oatpp::async::CoroutineWithResult<ToStringDecoder, oatpp::String> {
|
||||
private:
|
||||
const BodyDecoder* m_decoder;
|
||||
Protocol::Headers m_headers;
|
||||
Headers m_headers;
|
||||
std::shared_ptr<oatpp::data::stream::InputStream> m_bodyStream;
|
||||
std::shared_ptr<oatpp::data::stream::ChunkedBuffer> m_chunkedBuffer;
|
||||
public:
|
||||
|
||||
ToStringDecoder(const BodyDecoder* decoder,
|
||||
const Protocol::Headers& headers,
|
||||
const Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream);
|
||||
|
||||
Action act() override;
|
||||
@ -55,14 +61,14 @@ private:
|
||||
class ToDtoDecoder : public oatpp::async::CoroutineWithResult<ToDtoDecoder<Type>, typename Type::ObjectWrapper> {
|
||||
private:
|
||||
const BodyDecoder* m_decoder;
|
||||
Protocol::Headers m_headers;
|
||||
Headers m_headers;
|
||||
std::shared_ptr<oatpp::data::stream::InputStream> m_bodyStream;
|
||||
std::shared_ptr<oatpp::data::mapping::ObjectMapper> m_objectMapper;
|
||||
std::shared_ptr<oatpp::data::stream::ChunkedBuffer> m_chunkedBuffer = oatpp::data::stream::ChunkedBuffer::createShared();
|
||||
public:
|
||||
|
||||
ToDtoDecoder(const BodyDecoder* decoder,
|
||||
Protocol::Headers& headers,
|
||||
Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
|
||||
const std::shared_ptr<oatpp::data::mapping::ObjectMapper>& objectMapper)
|
||||
: m_decoder(decoder)
|
||||
@ -88,43 +94,92 @@ private:
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
virtual void decode(const Protocol::Headers& headers,
|
||||
|
||||
/**
|
||||
* Implement this method! Decode bodyStream and write decoded data to toStream.
|
||||
* @param headers - Headers map. &id:oatpp::web::protocol::http::Headers;.
|
||||
* @param bodyStream - `std::shared_ptr` to &id:oatpp::data::stream::InputStream;.
|
||||
* @param toStream - `std::shared_ptr` to &id:oatpp::data::stream::OutputStream;.
|
||||
*/
|
||||
virtual void decode(const Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
|
||||
const std::shared_ptr<oatpp::data::stream::OutputStream>& toStream) const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Implement this method! Same as &l:BodyDecoder::decode (); but Async.
|
||||
* @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*.
|
||||
* @param actionOnReturn - &id:oatpp::async::Action; to do when decoding finished.
|
||||
* @param headers - Headers map. &id:oatpp::web::protocol::http::Headers;.
|
||||
* @param bodyStream - `std::shared_ptr` to &id:oatpp::data::stream::InputStream;.
|
||||
* @param toStream - `std::shared_ptr` to &id:oatpp::data::stream::OutputStream;.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
virtual oatpp::async::Action decodeAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
|
||||
const oatpp::async::Action& actionOnReturn,
|
||||
const Protocol::Headers& headers,
|
||||
const Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
|
||||
const std::shared_ptr<oatpp::data::stream::OutputStream>& toStream) const = 0;
|
||||
|
||||
oatpp::String decodeToString(const Protocol::Headers& headers,
|
||||
|
||||
/**
|
||||
* Read body stream and decode it to string.
|
||||
* @param headers - Headers map. &id:oatpp::web::protocol::http::Headers;.
|
||||
* @param bodyStream - `std::shared_ptr` to &id:oatpp::data::stream::InputStream;.
|
||||
* @return - &oatpp::String;.
|
||||
*/
|
||||
oatpp::String decodeToString(const Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream) const {
|
||||
auto chunkedBuffer = oatpp::data::stream::ChunkedBuffer::createShared();
|
||||
decode(headers, bodyStream, chunkedBuffer);
|
||||
return chunkedBuffer->toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read body stream, decode, and deserialize it as DTO Object (see [Data Transfer Object (DTO)](https://oatpp.io/docs/components/dto/)).
|
||||
* @tparam Type - DTO object type.
|
||||
* @param headers - Headers map. &id:oatpp::web::protocol::http::Headers;.
|
||||
* @param bodyStream - `std::shared_ptr` to &id:oatpp::data::stream::InputStream;.
|
||||
* @param objectMapper - `std::shared_ptr` to &id:oatpp::data::mapping::ObjectMapper;.
|
||||
* @return - deserialized DTO object.
|
||||
*/
|
||||
template<class Type>
|
||||
typename Type::ObjectWrapper decodeToDto(const Protocol::Headers& headers,
|
||||
typename Type::ObjectWrapper decodeToDto(const Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
|
||||
const std::shared_ptr<oatpp::data::mapping::ObjectMapper>& objectMapper) const {
|
||||
return objectMapper->readFromString<Type>(decodeToString(headers, bodyStream));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Same as &l:BodyDecoder::decodeToString (); but Async.
|
||||
* @tparam ParentCoroutineType - caller coroutine type.
|
||||
* @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*.
|
||||
* @param callback - pointer to callback function.
|
||||
* @param headers - Headers map. &id:oatpp::web::protocol::http::Headers;.
|
||||
* @param bodyStream - `std::shared_ptr` to &id:oatpp::data::stream::InputStream;.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
template<typename ParentCoroutineType>
|
||||
oatpp::async::Action decodeToStringAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
|
||||
oatpp::async::Action (ParentCoroutineType::*callback)(const oatpp::String&),
|
||||
const Protocol::Headers& headers,
|
||||
const Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream) const {
|
||||
return parentCoroutine->startCoroutineForResult<ToStringDecoder>(callback, this, headers, bodyStream);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Same as &l:BodyDecoder::decodeToDto (); but Async.
|
||||
* @tparam DtoType - DTO object type.
|
||||
* @tparam ParentCoroutineType - caller coroutine type.
|
||||
* @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*.
|
||||
* @param callback - pointer to callback function.
|
||||
* @param headers - Headers map. &id:oatpp::web::protocol::http::Headers;.
|
||||
* @param bodyStream - `std::shared_ptr` to &id:oatpp::data::stream::InputStream;.
|
||||
* @param objectMapper - `std::shared_ptr` to &id:oatpp::data::mapping::ObjectMapper;.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
template<class DtoType, typename ParentCoroutineType>
|
||||
oatpp::async::Action decodeToDtoAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
|
||||
oatpp::async::Action (ParentCoroutineType::*callback)(const typename DtoType::ObjectWrapper&),
|
||||
const Protocol::Headers& headers,
|
||||
const Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
|
||||
const std::shared_ptr<oatpp::data::mapping::ObjectMapper>& objectMapper) const {
|
||||
return parentCoroutine->startCoroutineForResult<ToDtoDecoder<DtoType>>(callback, this, headers, bodyStream, objectMapper);
|
||||
|
@ -28,7 +28,7 @@ namespace oatpp { namespace web { namespace protocol { namespace http { namespac
|
||||
|
||||
Request::Request(const http::RequestStartingLine& startingLine,
|
||||
const url::mapping::Pattern::MatchMap& pathVariables,
|
||||
const http::Protocol::Headers& headers,
|
||||
const http::Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
|
||||
const std::shared_ptr<const http::incoming::BodyDecoder>& bodyDecoder)
|
||||
: m_startingLine(startingLine)
|
||||
@ -41,7 +41,7 @@ Request::Request(const http::RequestStartingLine& startingLine,
|
||||
|
||||
std::shared_ptr<Request> Request::createShared(const http::RequestStartingLine& startingLine,
|
||||
const url::mapping::Pattern::MatchMap& pathVariables,
|
||||
const http::Protocol::Headers& headers,
|
||||
const http::Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
|
||||
const std::shared_ptr<const http::incoming::BodyDecoder>& bodyDecoder) {
|
||||
return Shared_Incoming_Request_Pool::allocateShared(startingLine, pathVariables, headers, bodyStream, bodyDecoder);
|
||||
@ -55,11 +55,11 @@ const url::mapping::Pattern::MatchMap& Request::getPathVariables() const {
|
||||
return m_pathVariables;
|
||||
}
|
||||
|
||||
const http::Protocol::Headers& Request::getHeaders() const {
|
||||
const http::Headers& Request::getHeaders() const {
|
||||
return m_headers;
|
||||
}
|
||||
|
||||
const http::Protocol::QueryParams& Request::getQueryParameters() const {
|
||||
const http::QueryParams& Request::getQueryParameters() const {
|
||||
if(!m_queryParamsParsed) {
|
||||
m_queryParams = oatpp::network::Url::Parser::labelQueryParams(m_pathVariables.getTail());
|
||||
m_queryParamsParsed = true;
|
||||
|
@ -33,7 +33,7 @@
|
||||
namespace oatpp { namespace web { namespace protocol { namespace http { namespace incoming {
|
||||
|
||||
/**
|
||||
* Class http::incoming::Request AKA IncomingRequest represents client's incoming request
|
||||
* Class http::incoming::Request AKA IncomingRequest represents client's incoming request.
|
||||
*/
|
||||
class Request : public oatpp::base::Countable {
|
||||
public:
|
||||
@ -43,7 +43,7 @@ private:
|
||||
|
||||
http::RequestStartingLine m_startingLine;
|
||||
url::mapping::Pattern::MatchMap m_pathVariables;
|
||||
http::Protocol::Headers m_headers;
|
||||
http::Headers m_headers;
|
||||
std::shared_ptr<oatpp::data::stream::InputStream> m_bodyStream;
|
||||
|
||||
/*
|
||||
@ -53,20 +53,20 @@ private:
|
||||
std::shared_ptr<const http::incoming::BodyDecoder> m_bodyDecoder;
|
||||
|
||||
mutable bool m_queryParamsParsed; // used for lazy parsing of QueryParams
|
||||
mutable http::Protocol::QueryParams m_queryParams;
|
||||
mutable http::QueryParams m_queryParams;
|
||||
|
||||
public:
|
||||
|
||||
Request(const http::RequestStartingLine& startingLine,
|
||||
const url::mapping::Pattern::MatchMap& pathVariables,
|
||||
const http::Protocol::Headers& headers,
|
||||
const http::Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
|
||||
const std::shared_ptr<const http::incoming::BodyDecoder>& bodyDecoder);
|
||||
public:
|
||||
|
||||
static std::shared_ptr<Request> createShared(const http::RequestStartingLine& startingLine,
|
||||
const url::mapping::Pattern::MatchMap& pathVariables,
|
||||
const http::Protocol::Headers& headers,
|
||||
const http::Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
|
||||
const std::shared_ptr<const http::incoming::BodyDecoder>& bodyDecoder);
|
||||
|
||||
@ -76,7 +76,7 @@ public:
|
||||
* Please note: lazy parsing of query parameters is not thread-safe!
|
||||
* @return map<key, value> for "&key=value"
|
||||
*/
|
||||
const http::Protocol::QueryParams& getQueryParameters() const;
|
||||
const http::QueryParams& getQueryParameters() const;
|
||||
|
||||
/**
|
||||
* Get query parameter value by name
|
||||
@ -86,7 +86,7 @@ public:
|
||||
oatpp::String getQueryParameter(const oatpp::data::share::StringKeyLabel& name) const;
|
||||
|
||||
/**
|
||||
*
|
||||
* Get query parameter value by name with defaultValue
|
||||
* @param name
|
||||
* @param defaultValue
|
||||
* @return query parameter value or defaultValue if no such parameter found
|
||||
@ -100,8 +100,8 @@ public:
|
||||
const http::RequestStartingLine& getStartingLine() const;
|
||||
|
||||
/**
|
||||
* Get path variables according to path-pattern.
|
||||
* Ex. given request path="/sum/19/1" for path-pattern="/sum/{a}/{b}"
|
||||
* Get path variables according to path-pattern. <br>
|
||||
* Ex. given request path="/sum/19/1" for path-pattern="/sum/{a}/{b}" <br>
|
||||
* getPathVariables().getVariable("a") == 19, getPathVariables().getVariable("b") == 1.
|
||||
*
|
||||
* @return url MatchMap
|
||||
@ -112,7 +112,7 @@ public:
|
||||
* Get request's headers map
|
||||
* @return Headers map
|
||||
*/
|
||||
const http::Protocol::Headers& getHeaders() const;
|
||||
const http::Headers& getHeaders() const;
|
||||
|
||||
/**
|
||||
* Get request's body stream
|
||||
|
@ -84,9 +84,9 @@ RequestHeadersReader::Result RequestHeadersReader::readHeaders(const std::shared
|
||||
auto headersText = buffer.toString();
|
||||
oatpp::parser::Caret caret (headersText);
|
||||
http::Status status;
|
||||
http::Protocol::parseRequestStartingLine(result.startingLine, headersText.getPtr(), caret, status);
|
||||
http::Parser::parseRequestStartingLine(result.startingLine, headersText.getPtr(), caret, status);
|
||||
if(status.code == 0) {
|
||||
http::Protocol::parseHeaders(result.headers, headersText.getPtr(), caret, status);
|
||||
http::Parser::parseHeaders(result.headers, headersText.getPtr(), caret, status);
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,9 +161,9 @@ RequestHeadersReader::Action RequestHeadersReader::readHeadersAsync(oatpp::async
|
||||
auto headersText = m_bufferStream.toString();
|
||||
oatpp::parser::Caret caret (headersText);
|
||||
http::Status status;
|
||||
http::Protocol::parseRequestStartingLine(m_result.startingLine, headersText.getPtr(), caret, status);
|
||||
http::Parser::parseRequestStartingLine(m_result.startingLine, headersText.getPtr(), caret, status);
|
||||
if(status.code == 0) {
|
||||
http::Protocol::parseHeaders(m_result.headers, headersText.getPtr(), caret, status);
|
||||
http::Parser::parseHeaders(m_result.headers, headersText.getPtr(), caret, status);
|
||||
if(status.code == 0) {
|
||||
return _return(m_result);
|
||||
} else {
|
||||
|
@ -29,18 +29,42 @@
|
||||
#include "oatpp/core/async/Coroutine.hpp"
|
||||
|
||||
namespace oatpp { namespace web { namespace protocol { namespace http { namespace incoming {
|
||||
|
||||
|
||||
/**
|
||||
* Helper class to read http headers of incoming request from stream.
|
||||
*/
|
||||
class RequestHeadersReader {
|
||||
public:
|
||||
/**
|
||||
* Convenience typedef for &id:oatpp::async::Action;.
|
||||
*/
|
||||
typedef oatpp::async::Action Action;
|
||||
private:
|
||||
static constexpr v_int32 SECTION_END = ('\r' << 24) | ('\n' << 16) | ('\r' << 8) | ('\n');
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Result of headers reading and parsing.
|
||||
*/
|
||||
struct Result {
|
||||
/**
|
||||
* &id:oatpp::web::protocol::http::RequestStartingLine;.
|
||||
*/
|
||||
http::RequestStartingLine startingLine;
|
||||
http::Protocol::Headers headers;
|
||||
|
||||
/**
|
||||
* &id:oatpp::web::protocol::http::Headers;.
|
||||
*/
|
||||
http::Headers headers;
|
||||
|
||||
/**
|
||||
* This value represents starting position in buffer used to read data from stream for the last read operation.
|
||||
*/
|
||||
v_int32 bufferPosStart;
|
||||
|
||||
/**
|
||||
* This value represents end position in buffer used to read data from stream for the last read operation.
|
||||
*/
|
||||
v_int32 bufferPosEnd;
|
||||
};
|
||||
|
||||
@ -55,14 +79,34 @@ private:
|
||||
v_int32 m_bufferSize;
|
||||
v_int32 m_maxHeadersSize;
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param buffer - buffer to use to read data from stream.
|
||||
* @param bufferSize - buffer size.
|
||||
* @param maxHeadersSize - maximum allowed size in bytes of http headers section.
|
||||
*/
|
||||
RequestHeadersReader(void* buffer, v_int32 bufferSize, v_int32 maxHeadersSize)
|
||||
: m_buffer((p_char8) buffer)
|
||||
, m_bufferSize(bufferSize)
|
||||
, m_maxHeadersSize(maxHeadersSize)
|
||||
{}
|
||||
|
||||
|
||||
/**
|
||||
* Read and parse http headers from stream.
|
||||
* @param connection - `std::shared_ptr` to &id:oatpp::data::stream::IOStream;.
|
||||
* @param error - out parameter &id:oatpp::web::protocol::ProtocolError::Info;.
|
||||
* @return - &l:RequestHeadersReader::Result;.
|
||||
*/
|
||||
Result readHeaders(const std::shared_ptr<oatpp::data::stream::IOStream>& connection, http::HttpError::Info& error);
|
||||
|
||||
/**
|
||||
* Read and parse http headers from stream in asynchronous manner.
|
||||
* @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*.
|
||||
* @param callback - pointer to callback function.
|
||||
* @param connection - `std::shared_ptr` to &id:oatpp::data::stream::IOStream;.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
Action readHeadersAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
|
||||
AsyncCallback callback,
|
||||
const std::shared_ptr<oatpp::data::stream::IOStream>& connection);
|
||||
|
@ -28,7 +28,7 @@ namespace oatpp { namespace web { namespace protocol { namespace http { namespac
|
||||
|
||||
Response::Response(v_int32 statusCode,
|
||||
const oatpp::String& statusDescription,
|
||||
const http::Protocol::Headers& headers,
|
||||
const http::Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
|
||||
const std::shared_ptr<const http::incoming::BodyDecoder>& bodyDecoder)
|
||||
: m_statusCode(statusCode)
|
||||
@ -40,7 +40,7 @@ Response::Response(v_int32 statusCode,
|
||||
|
||||
std::shared_ptr<Response> Response::createShared(v_int32 statusCode,
|
||||
const oatpp::String& statusDescription,
|
||||
const http::Protocol::Headers& headers,
|
||||
const http::Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
|
||||
const std::shared_ptr<const http::incoming::BodyDecoder>& bodyDecoder) {
|
||||
return Shared_Incoming_Response_Pool::allocateShared(statusCode, statusDescription, headers, bodyStream, bodyDecoder);
|
||||
@ -54,7 +54,7 @@ oatpp::String Response::getStatusDescription() const {
|
||||
return m_statusDescription;
|
||||
}
|
||||
|
||||
const http::Protocol::Headers& Response::getHeaders() const {
|
||||
const http::Headers& Response::getHeaders() const {
|
||||
return m_headers;
|
||||
}
|
||||
|
||||
|
@ -40,10 +40,10 @@ public:
|
||||
private:
|
||||
v_int32 m_statusCode;
|
||||
oatpp::String m_statusDescription;
|
||||
http::Protocol::Headers m_headers;
|
||||
http::Headers m_headers;
|
||||
std::shared_ptr<oatpp::data::stream::InputStream> m_bodyStream;
|
||||
|
||||
/**
|
||||
/*
|
||||
* Response should be preconfigured with default BodyDecoder.
|
||||
* Entity that created response object is responsible for providing correct BodyDecoder.
|
||||
* Custom BodyDecoder can be set on demand
|
||||
@ -53,50 +53,125 @@ private:
|
||||
std::shared_ptr<oatpp::data::stream::IOStream> m_connection;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param statusCode - http status code.
|
||||
* @param statusDescription - http status description.
|
||||
* @param headers - &id:oatpp::web::protocol::http::Headers;.
|
||||
* @param bodyStream - &id:oatpp::data::stream::InputStream;.
|
||||
* @param bodyDecoder - &id:oatpp::web::protocol::http::incoming::BodyDecoder;.
|
||||
*/
|
||||
Response(v_int32 statusCode,
|
||||
const oatpp::String& statusDescription,
|
||||
const http::Protocol::Headers& headers,
|
||||
const http::Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
|
||||
const std::shared_ptr<const http::incoming::BodyDecoder>& bodyDecoder);
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Create shared Response.
|
||||
* @param statusCode - http status code.
|
||||
* @param statusDescription - http status description.
|
||||
* @param headers - &id:oatpp::web::protocol::http::Headers;.
|
||||
* @param bodyStream - &id:oatpp::data::stream::InputStream;.
|
||||
* @param bodyDecoder - &id:oatpp::web::protocol::http::incoming::BodyDecoder;.
|
||||
* @return - `std::shared_ptr` to Response.
|
||||
*/
|
||||
static std::shared_ptr<Response> createShared(v_int32 statusCode,
|
||||
const oatpp::String& statusDescription,
|
||||
const http::Protocol::Headers& headers,
|
||||
const http::Headers& headers,
|
||||
const std::shared_ptr<oatpp::data::stream::InputStream>& bodyStream,
|
||||
const std::shared_ptr<const http::incoming::BodyDecoder>& bodyDecoder);
|
||||
|
||||
|
||||
/**
|
||||
* Get http status code.
|
||||
* @return - http status code.
|
||||
*/
|
||||
v_int32 getStatusCode() const;
|
||||
|
||||
|
||||
/**
|
||||
* Get http status description.
|
||||
* @return - http status description.
|
||||
*/
|
||||
oatpp::String getStatusDescription() const;
|
||||
|
||||
const http::Protocol::Headers& getHeaders() const;
|
||||
|
||||
|
||||
/**
|
||||
* Get response http headers as &id:oatpp::web::protocol::http::Headers;.
|
||||
* @return - response http headers as &id:oatpp::web::protocol::http::Headers;.
|
||||
*/
|
||||
const http::Headers& getHeaders() const;
|
||||
|
||||
/**
|
||||
* Get raw body stream.
|
||||
* @return - raw body stream as &id:oatpp::data::stream::InputStream;.
|
||||
*/
|
||||
std::shared_ptr<oatpp::data::stream::InputStream> getBodyStream() const;
|
||||
|
||||
|
||||
/**
|
||||
* Get body decoder configured for this response.
|
||||
* @return - &id:oatpp::web::protocol::http::incoming::BodyDecoder;.
|
||||
*/
|
||||
std::shared_ptr<const http::incoming::BodyDecoder> getBodyDecoder() const;
|
||||
|
||||
/**
|
||||
* Decode and transfer body to toStream.
|
||||
* Use case example - stream huge body directly to file using relatively small buffer.
|
||||
* @param toStream - &id:oatpp::data::stream::OutputStream;.
|
||||
*/
|
||||
void streamBody(const std::shared_ptr<oatpp::data::stream::OutputStream>& toStream) const;
|
||||
|
||||
|
||||
/**
|
||||
* Decode and read body to &id:oatpp::String;.
|
||||
* @return - &id:oatpp::String;.
|
||||
*/
|
||||
oatpp::String readBodyToString() const;
|
||||
|
||||
|
||||
/**
|
||||
* Read body stream, decode, and deserialize it as DTO Object (see [Data Transfer Object (DTO)](https://oatpp.io/docs/components/dto/)).
|
||||
* @tparam Type - DTO object type.
|
||||
* @param objectMapper - `std::shared_ptr` to &id:oatpp::data::mapping::ObjectMapper;.
|
||||
* @return - deserialized DTO object.
|
||||
*/
|
||||
template<class Type>
|
||||
typename Type::ObjectWrapper readBodyToDto(const std::shared_ptr<oatpp::data::mapping::ObjectMapper>& objectMapper) const {
|
||||
return m_bodyDecoder->decodeToDto<Type>(m_headers, m_bodyStream, objectMapper);
|
||||
}
|
||||
|
||||
// Async
|
||||
|
||||
|
||||
/**
|
||||
* Same as &l:Response::readBodyToDto (); but Async.
|
||||
* @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*.
|
||||
* @param actionOnReturn - &id:oatpp::async::Action; to do when decoding finished.
|
||||
* @param toStream - `std::shared_ptr` to &id:oatpp::data::stream::OutputStream;.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
oatpp::async::Action streamBodyAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
|
||||
const oatpp::async::Action& actionOnReturn,
|
||||
const std::shared_ptr<oatpp::data::stream::OutputStream>& toStream) const;
|
||||
|
||||
|
||||
/**
|
||||
* Same as &l:Response::readBodyToString (); but Async.
|
||||
* @tparam ParentCoroutineType - caller coroutine type.
|
||||
* @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*.
|
||||
* @param callback - pointer to callback function.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
template<typename ParentCoroutineType>
|
||||
oatpp::async::Action readBodyToStringAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
|
||||
oatpp::async::Action (ParentCoroutineType::*callback)(const oatpp::String&)) const {
|
||||
return m_bodyDecoder->decodeToStringAsync(parentCoroutine, callback, m_headers, m_bodyStream);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Same as &l:Response::readBodyToDto (); but Async.
|
||||
* @tparam DtoType - DTO object type.
|
||||
* @tparam ParentCoroutineType - caller coroutine type.
|
||||
* @param parentCoroutine - caller coroutine as &id:oatpp::async::AbstractCoroutine;*.
|
||||
* @param callback - pointer to callback function.
|
||||
* @param objectMapper - `std::shared_ptr` to &id:oatpp::data::mapping::ObjectMapper;.
|
||||
* @return - &id:oatpp::async::Action;.
|
||||
*/
|
||||
template<class DtoType, typename ParentCoroutineType>
|
||||
oatpp::async::Action readBodyToDtoAsync(oatpp::async::AbstractCoroutine* parentCoroutine,
|
||||
oatpp::async::Action (ParentCoroutineType::*callback)(const typename DtoType::ObjectWrapper&),
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user