Windows Port. Tests compile, doesn't link with wepoll.

This commit is contained in:
bam 2019-07-31 11:34:52 +02:00
parent 3aa2145de6
commit 438fafd49f
14 changed files with 2789 additions and 127 deletions

View File

@ -71,6 +71,12 @@ if(OATPP_COMPAT_BUILD_NO_THREAD_LOCAL)
add_definitions(-DOATPP_COMPAT_BUILD_NO_THREAD_LOCAL)
endif()
if (MSVC)
# Add compilerswitch to allow pointer-to-members
# https://docs.microsoft.com/en-us/cpp/preprocessor/pointers-to-members?view=vs-2019
add_compile_options(/vmg /wd4996)
endif(MSVC)
message("\n############################################################################\n")
###################################################################################################

View File

@ -184,3 +184,7 @@ Grab any project from [examples](https://github.com/oatpp/oatpp-examples), and f
- [Consul](https://github.com/oatpp/example-consul) - Example project of how-to use oatpp::consul::Client. Integration with Consul.
- [PostgreSQL](https://github.com/oatpp/example-postgresql) - Example of a production grade entity service storing information in PostgreSQL. With Swagger-UI and configuration profiles.
- [WebSocket](https://github.com/oatpp/example-websocket) - Collection of oatpp WebSocket examples.
## Third Party Licenses
### wepoll
License for `wepoll Copyright 2012-2019, Bert Belder <bertbelder@gmail.com>` found in `src/oatpp/core/async/worker/wepoll/LICENSE`

View File

@ -2,11 +2,14 @@
#######################################################################################################
## oatpp
if (MSVC)
# Add compilerswitch to allow pointer-to-members
# https://docs.microsoft.com/en-us/cpp/preprocessor/pointers-to-members?view=vs-2019
add_compile_options(/vmg /wd4996)
if(MSVC)
set(ADDWINSRC
oatpp/core/async/worker/wepoll/wepoll.c
oatpp/core/async/worker/wepoll/wepoll.h
)
else(MSVC)
set(ADDWINSRC
)
endif(MSVC)
add_library(oatpp
@ -37,6 +40,7 @@ add_library(oatpp
oatpp/core/async/worker/IOEventWorker_common.cpp
oatpp/core/async/worker/IOEventWorker_kqueue.cpp
oatpp/core/async/worker/IOEventWorker_epoll.cpp
oatpp/core/async/worker/IOEventWorker_wepoll.cpp
oatpp/core/async/worker/IOEventWorker.hpp
oatpp/core/async/worker/TimerWorker.cpp
oatpp/core/async/worker/TimerWorker.hpp
@ -216,19 +220,24 @@ add_library(oatpp
oatpp/web/url/mapping/Pattern.cpp
oatpp/web/url/mapping/Pattern.hpp
oatpp/web/url/mapping/Router.hpp
${ADDWINSRC}
)
set_target_properties(oatpp PROPERTIES
CXX_STANDARD 11
CXX_EXTENSIONS OFF
CXX_STANDARD_REQUIRED ON
CXX_STANDARD_REQUIRED OFF
)
set(CMAKE_THREAD_PREFER_PTHREAD ON)
find_package(Threads REQUIRED)
target_link_libraries(oatpp PUBLIC ${CMAKE_THREAD_LIBS_INIT})
if(MSVC)
target_link_libraries(oatpp PUBLIC ${CMAKE_THREAD_LIBS_INIT} wsock32 ws2_32)
else(MSVC)
target_link_libraries(oatpp PUBLIC ${CMAKE_THREAD_LIBS_INIT})
endif(MSVC)
target_include_directories(oatpp PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>

View File

@ -46,6 +46,11 @@
#define OATPP_IO_EVENT_INTERFACE "kqueue"
#define OATPP_IO_EVENT_INTERFACE_KQUEUE
#elif defined(WIN32)
#include "oatpp/core/async/worker/wepoll/wepoll.h"
#define OATPP_IO_EVENT_INTERFACE "wepoll"
#define OATPP_IO_EVENT_INTERFACE_WEPOLL
#endif
#endif
@ -73,8 +78,13 @@ private:
oatpp::collection::FastQueue<AbstractCoroutine> m_backlog;
oatpp::concurrency::SpinLock m_backlogLock;
private:
#ifdef WIN32
HANDLE m_eventQueueHandle;
oatpp::data::v_io_handle m_wakeupTrigger[2];
#else
oatpp::data::v_io_handle m_eventQueueHandle;
oatpp::data::v_io_handle m_wakeupTrigger;
#endif
std::unique_ptr<v_char8[]> m_inEvents;
v_int32 m_inEventsCount;
v_int32 m_inEventsCapacity;

View File

@ -40,16 +40,22 @@ IOEventWorker::IOEventWorker(IOEventWorkerForeman* foreman, Action::IOEventType
, m_foreman(foreman)
, m_specialization(specialization)
, m_running(true)
#ifdef WIN32
, m_eventQueueHandle(nullptr)
#else
, m_eventQueueHandle(-1)
, m_wakeupTrigger(-1)
#endif
, m_inEvents(nullptr)
, m_inEventsCount(0)
, m_inEventsCapacity(0)
, m_outEvents(nullptr)
{
m_wakeupTrigger[0] = m_wakeupTrigger[1] = -1;
m_thread = std::thread(&IOEventWorker::run, this);
}
#ifndef WIN32
IOEventWorker::~IOEventWorker() {
if(m_eventQueueHandle >=0) {
@ -61,6 +67,7 @@ IOEventWorker::~IOEventWorker() {
}
}
#endif
void IOEventWorker::pushTasks(oatpp::collection::FastQueue<AbstractCoroutine> &tasks) {
if (tasks.first != nullptr) {

View File

@ -0,0 +1,286 @@
/***************************************************************************
*
* 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 "IOEventWorker.hpp"
#ifdef OATPP_IO_EVENT_INTERFACE_WEPOLL
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// epoll based implementation
#include "oatpp/core/async/worker/wepoll/wepoll.h"
#include "oatpp/core/async/Processor.hpp"
#include <io.h>
#include <fcntl.h>
//#include <sys/eventfd.h>
namespace oatpp { namespace async { namespace worker {
enum PIPES { READ, WRITE };
IOEventWorker::~IOEventWorker() {
if (m_eventQueueHandle != nullptr) {
wepoll_close(m_eventQueueHandle);
}
if(m_wakeupTrigger[0] >= 0) {
::close(m_wakeupTrigger[0]);
}
if(m_wakeupTrigger[1] >= 0) {
::close(m_wakeupTrigger[1]);
}
}
void IOEventWorker::initEventQueue() {
m_eventQueueHandle = epoll_create1(0);
if(m_eventQueueHandle == nullptr) {
OATPP_LOGE("[oatpp::async::worker::IOEventWorker::initEventQueue()]", "Error. Call to ::epoll_create1() failed. errno=%d", errno);
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::initEventQueue()]: Error. Call to ::epoll_create1() failed.");
}
m_outEvents = std::unique_ptr<v_char8[]>(new (std::nothrow) v_char8[MAX_EVENTS * sizeof(struct epoll_event)]);
if(!m_outEvents) {
OATPP_LOGE("[oatpp::async::worker::IOEventWorker::initEventQueue()]",
"Error. Unable to allocate %d bytes for events.", MAX_EVENTS * sizeof(struct epoll_event));
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::initEventQueue()]: Error. Unable to allocate memory for events.");
}
if(_pipe(m_wakeupTrigger, 256, O_BINARY) != 0) {
OATPP_LOGE("[oatpp::async::worker::IOEventWorker::initEventQueue()]", "Error. Call to ::eventfd() failed. errno=%d", errno);
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::initEventQueue()]: Error. Call to ::eventfd() failed.");
}
struct epoll_event event;
std::memset(&event, 0, sizeof(struct epoll_event));
event.data.ptr = this;
#ifdef EPOLLEXCLUSIVE
event.events = EPOLLIN | EPOLLET | EPOLLEXCLUSIVE;
#else
event.events = EPOLLIN;
#endif
auto res = epoll_ctl(m_eventQueueHandle, EPOLL_CTL_ADD, m_wakeupTrigger[READ], &event);
if(res == -1) {
OATPP_LOGE("[oatpp::async::worker::IOEventWorker::initEventQueue()]", "Error. Call to ::epoll_ctl failed. errno=%d", errno);
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::initEventQueue()]: Error. Call to ::epoll_ctl() failed.");
}
}
void IOEventWorker::triggerWakeup() {
static const int one = 1;
::write(m_wakeupTrigger[WRITE], &one, sizeof(int));
}
void IOEventWorker::setTriggerEvent(p_char8 eventPtr) {
// DO NOTHING
}
void IOEventWorker::setCoroutineEvent(AbstractCoroutine* coroutine, int operation, p_char8 eventPtr) {
auto& action = getCoroutineScheduledAction(coroutine);
switch(action.getType()) {
case Action::TYPE_IO_WAIT: break;
case Action::TYPE_IO_REPEAT: break;
default:
OATPP_LOGE("[oatpp::async::worker::IOEventWorker::pushCoroutineToQueue()]", "Error. Unknown Action. action.getType()==%d", action.getType());
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::pushCoroutineToQueue()]: Error. Unknown Action.");
}
struct epoll_event event;
std::memset(&event, 0, sizeof(struct epoll_event));
event.data.ptr = coroutine;
switch(action.getIOEventType()) {
case Action::IOEventType::IO_EVENT_READ:
event.events = EPOLLIN | EPOLLONESHOT;
break;
case Action::IOEventType::IO_EVENT_WRITE:
event.events = EPOLLOUT | EPOLLONESHOT;
break;
default:
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::pushCoroutineToQueue()]: Error. Unknown Action Event Type.");
}
auto res = epoll_ctl(m_eventQueueHandle, operation, action.getIOHandle(), &event);
if(res == -1) {
OATPP_LOGE("[oatpp::async::worker::IOEventWorker::setEpollEvent()]", "Error. Call to epoll_ctl failed. operation=%d, errno=%d", operation, errno);
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::setEpollEvent()]: Error. Call to epoll_ctl failed.");
}
}
void IOEventWorker::consumeBacklog() {
std::lock_guard<oatpp::concurrency::SpinLock> lock(m_backlogLock);
auto curr = m_backlog.first;
while(curr != nullptr) {
setCoroutineEvent(curr, EPOLL_CTL_ADD, nullptr);
curr = nextCoroutine(curr);
}
m_backlog.first = nullptr;
m_backlog.last = nullptr;
m_backlog.count = 0;
}
void IOEventWorker::waitEvents() {
struct epoll_event* outEvents = (struct epoll_event*)m_outEvents.get();
auto eventsCount = epoll_wait(m_eventQueueHandle, outEvents, MAX_EVENTS, -1);
if(eventsCount < 0) {
OATPP_LOGE("[oatpp::async::worker::IOEventWorker::waitEvents()]", "Error. errno=%d", errno);
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::waitEvents()]: Error. Event loop failed.");
}
oatpp::collection::FastQueue<AbstractCoroutine> popQueue;
for(v_int32 i = 0; i < eventsCount; i ++) {
void* dataPtr = outEvents[i].data.ptr;
if(dataPtr != nullptr) {
if(dataPtr == this) {
int value;
::read(m_wakeupTrigger[READ], &value, sizeof(int));
} else {
auto coroutine = (AbstractCoroutine*) dataPtr;
Action action = coroutine->iterate();
int res;
switch(action.getIOEventCode() | m_specialization) {
case Action::CODE_IO_WAIT_READ:
setCoroutineScheduledAction(coroutine, std::move(action));
setCoroutineEvent(coroutine, EPOLL_CTL_MOD, nullptr);
break;
case Action::CODE_IO_WAIT_WRITE:
setCoroutineScheduledAction(coroutine, std::move(action));
setCoroutineEvent(coroutine, EPOLL_CTL_MOD, nullptr);
break;
case Action::CODE_IO_REPEAT_READ:
setCoroutineScheduledAction(coroutine, std::move(action));
setCoroutineEvent(coroutine, EPOLL_CTL_MOD, nullptr);
break;
case Action::CODE_IO_REPEAT_WRITE:
setCoroutineScheduledAction(coroutine, std::move(action));
setCoroutineEvent(coroutine, EPOLL_CTL_MOD, nullptr);
break;
case Action::CODE_IO_WAIT_RESCHEDULE:
res = epoll_ctl(m_eventQueueHandle, EPOLL_CTL_DEL, action.getIOHandle(), nullptr);
if(res == -1) {
OATPP_LOGE(
"[oatpp::async::worker::IOEventWorker::waitEvents()]",
"Error. Call to epoll_ctl failed. operation=%d, errno=%d. action_code=%d, worker_specialization=%d",
EPOLL_CTL_DEL, errno, action.getIOEventCode(), m_specialization
);
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::waitEvents()]: Error. Call to epoll_ctl failed.");
}
setCoroutineScheduledAction(coroutine, std::move(action));
popQueue.pushBack(coroutine);
break;
case Action::CODE_IO_REPEAT_RESCHEDULE:
res = epoll_ctl(m_eventQueueHandle, EPOLL_CTL_DEL, action.getIOHandle(), nullptr);
if(res == -1) {
OATPP_LOGE(
"[oatpp::async::worker::IOEventWorker::waitEvents()]",
"Error. Call to epoll_ctl failed. operation=%d, errno=%d. action_code=%d, worker_specialization=%d",
EPOLL_CTL_DEL, errno, action.getIOEventCode(), m_specialization
);
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::waitEvents()]: Error. Call to epoll_ctl failed.");
}
setCoroutineScheduledAction(coroutine, std::move(action));
popQueue.pushBack(coroutine);
break;
default:
auto& prevAction = getCoroutineScheduledAction(coroutine);
res = epoll_ctl(m_eventQueueHandle, EPOLL_CTL_DEL, prevAction.getIOHandle(), nullptr);
if(res == -1) {
OATPP_LOGE("[oatpp::async::worker::IOEventWorker::waitEvents()]", "Error. Call to epoll_ctl failed. operation=%d, errno=%d", EPOLL_CTL_DEL, errno);
throw std::runtime_error("[oatpp::async::worker::IOEventWorker::waitEvents()]: Error. Call to epoll_ctl failed.");
}
setCoroutineScheduledAction(coroutine, std::move(action));
getCoroutineProcessor(coroutine)->pushOneTask(coroutine);
}
}
}
}
if(popQueue.count > 0) {
m_foreman->pushTasks(popQueue);
}
}
}}}
#endif // #ifdef OATPP_IO_EVENT_INTERFACE_WEPOLL

View File

@ -0,0 +1,28 @@
wepoll - epoll for Windows
https://github.com/piscisaureus/wepoll
Copyright 2012-2019, Bert Belder <bertbelder@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,113 @@
/*
* wepoll - epoll for Windows
* https://github.com/piscisaureus/wepoll
*
* Copyright 2012-2019, Bert Belder <bertbelder@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef WEPOLL_H_
#define WEPOLL_H_
#ifndef WEPOLL_EXPORT
#define WEPOLL_EXPORT
#endif
#include <stdint.h>
enum EPOLL_EVENTS {
EPOLLIN = (int) (1U << 0),
EPOLLPRI = (int) (1U << 1),
EPOLLOUT = (int) (1U << 2),
EPOLLERR = (int) (1U << 3),
EPOLLHUP = (int) (1U << 4),
EPOLLRDNORM = (int) (1U << 6),
EPOLLRDBAND = (int) (1U << 7),
EPOLLWRNORM = (int) (1U << 8),
EPOLLWRBAND = (int) (1U << 9),
EPOLLMSG = (int) (1U << 10), /* Never reported. */
EPOLLRDHUP = (int) (1U << 13),
EPOLLONESHOT = (int) (1U << 31)
};
#define EPOLLIN (1U << 0)
#define EPOLLPRI (1U << 1)
#define EPOLLOUT (1U << 2)
#define EPOLLERR (1U << 3)
#define EPOLLHUP (1U << 4)
#define EPOLLRDNORM (1U << 6)
#define EPOLLRDBAND (1U << 7)
#define EPOLLWRNORM (1U << 8)
#define EPOLLWRBAND (1U << 9)
#define EPOLLMSG (1U << 10)
#define EPOLLRDHUP (1U << 13)
#define EPOLLONESHOT (1U << 31)
#define EPOLL_CTL_ADD 1
#define EPOLL_CTL_MOD 2
#define EPOLL_CTL_DEL 3
typedef void* HANDLE;
typedef uintptr_t SOCKET;
typedef union epoll_data {
void* ptr;
int fd;
uint32_t u32;
uint64_t u64;
SOCKET sock; /* Windows specific */
HANDLE hnd; /* Windows specific */
} epoll_data_t;
struct epoll_event {
uint32_t events; /* Epoll events and flags */
epoll_data_t data; /* User data variable */
};
#ifdef __cplusplus
extern "C" {
#endif
WEPOLL_EXPORT HANDLE epoll_create(int size);
WEPOLL_EXPORT HANDLE epoll_create1(int flags);
WEPOLL_EXPORT int wepoll_close(HANDLE ephnd);
WEPOLL_EXPORT int epoll_ctl(HANDLE ephnd,
int op,
SOCKET sock,
struct epoll_event* event);
WEPOLL_EXPORT int epoll_wait(HANDLE ephnd,
struct epoll_event* events,
int maxevents,
int timeout);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* WEPOLL_H_ */

View File

@ -1,4 +1,12 @@
if (MSVC)
# The MSVC compiler doesnt comply to c99 thus the OATPP_MACRO_HAS_ARGS macro always expands to 1
# This screws up the DTO_FIELD and ENDPOINT macros. To force MSVC to c99 compliant mode we need to activate this
# experimental switch. However, we can't enable it globally since the Windows-SDK isn't prepared for this and
# throws a whole bunch of errors.
add_compile_options(/experimental:preprocessor)
endif(MSVC)
add_executable(oatppAllTests
oatpp/AllTestsMain.cpp
oatpp/core/async/LockTest.cpp

View File

@ -37,25 +37,25 @@ namespace {
class TestDto : public DTO {
DTO_INIT(TestDto, DTO)
DTO_INIT(TestDto, DTO);
DTO_FIELD(String, f_string);
DTO_FIELD(Int8, f_int8);
DTO_FIELD(Int16, f_int16);
DTO_FIELD(Int32, f_int32);
DTO_FIELD(Int64, f_int64);
DTO_FIELD(Float32, f_float32);
DTO_FIELD(Float64, f_float64);
DTO_FIELD(Boolean, f_boolean);
DTO_FIELD(String, _string);
DTO_FIELD(Int8, _int8);
DTO_FIELD(Int16, _int16);
DTO_FIELD(Int32, _int32);
DTO_FIELD(Int64, _int64);
DTO_FIELD(Float32, _float32);
DTO_FIELD(Float64, _float64);
DTO_FIELD(Boolean, _boolean);
DTO_FIELD(List<String>::ObjectWrapper, f_list_string);
DTO_FIELD(List<Int32>::ObjectWrapper, f_list_int32);
DTO_FIELD(List<Int64>::ObjectWrapper, f_list_int64);
DTO_FIELD(List<Float32>::ObjectWrapper, f_list_float32);
DTO_FIELD(List<Float64>::ObjectWrapper, f_list_float64);
DTO_FIELD(List<Boolean>::ObjectWrapper, f_list_boolean);
DTO_FIELD(List<String>::ObjectWrapper, _list_string);
DTO_FIELD(List<Int32>::ObjectWrapper, _list_int32);
DTO_FIELD(List<Int64>::ObjectWrapper, _list_int64);
DTO_FIELD(List<Float32>::ObjectWrapper, _list_float32);
DTO_FIELD(List<Float64>::ObjectWrapper, _list_float64);
DTO_FIELD(List<Boolean>::ObjectWrapper, _list_boolean);
DTO_FIELD(Fields<String>::ObjectWrapper, _map_string_string);
DTO_FIELD(Fields<String>::ObjectWrapper, f_map_string_string);
DTO_FIELD(TestDto::ObjectWrapper, obj1);
@ -69,50 +69,50 @@ void TypeTest::onRun() {
auto obj = TestDto::createShared();
OATPP_LOGV(TAG, "type: '%s'", obj->_string.valueType->name);
OATPP_ASSERT(obj->_string.valueType->name == oatpp::data::mapping::type::__class::String::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->f_string.valueType->name);
OATPP_ASSERT(obj->f_string.valueType->name == oatpp::data::mapping::type::__class::String::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->_int8.valueType->name);
OATPP_ASSERT(obj->_int8.valueType->name == oatpp::data::mapping::type::__class::Int8::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->f_int8.valueType->name);
OATPP_ASSERT(obj->f_int8.valueType->name == oatpp::data::mapping::type::__class::Int8::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->_int16.valueType->name);
OATPP_ASSERT(obj->_int16.valueType->name == oatpp::data::mapping::type::__class::Int16::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->f_int16.valueType->name);
OATPP_ASSERT(obj->f_int16.valueType->name == oatpp::data::mapping::type::__class::Int16::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->_int32.valueType->name);
OATPP_ASSERT(obj->_int32.valueType->name == oatpp::data::mapping::type::__class::Int32::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->f_int32.valueType->name);
OATPP_ASSERT(obj->f_int32.valueType->name == oatpp::data::mapping::type::__class::Int32::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->_int64.valueType->name);
OATPP_ASSERT(obj->_int64.valueType->name == oatpp::data::mapping::type::__class::Int64::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->f_int64.valueType->name);
OATPP_ASSERT(obj->f_int64.valueType->name == oatpp::data::mapping::type::__class::Int64::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->_float32.valueType->name);
OATPP_ASSERT(obj->_float32.valueType->name == oatpp::data::mapping::type::__class::Float32::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->f_float32.valueType->name);
OATPP_ASSERT(obj->f_float32.valueType->name == oatpp::data::mapping::type::__class::Float32::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->_float64.valueType->name);
OATPP_ASSERT(obj->_float64.valueType->name == oatpp::data::mapping::type::__class::Float64::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->f_float64.valueType->name);
OATPP_ASSERT(obj->f_float64.valueType->name == oatpp::data::mapping::type::__class::Float64::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->_boolean.valueType->name);
OATPP_ASSERT(obj->_boolean.valueType->name == oatpp::data::mapping::type::__class::Boolean::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->f_boolean.valueType->name);
OATPP_ASSERT(obj->f_boolean.valueType->name == oatpp::data::mapping::type::__class::Boolean::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->_list_string.valueType->name);
OATPP_ASSERT(obj->_list_string.valueType->name == oatpp::data::mapping::type::__class::AbstractList::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->f_list_string.valueType->name);
OATPP_ASSERT(obj->f_list_string.valueType->name == oatpp::data::mapping::type::__class::AbstractList::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->_list_int32.valueType->name);
OATPP_ASSERT(obj->_list_int32.valueType->name == oatpp::data::mapping::type::__class::AbstractList::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->f_list_int32.valueType->name);
OATPP_ASSERT(obj->f_list_int32.valueType->name == oatpp::data::mapping::type::__class::AbstractList::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->_list_int64.valueType->name);
OATPP_ASSERT(obj->_list_int64.valueType->name == oatpp::data::mapping::type::__class::AbstractList::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->f_list_int64.valueType->name);
OATPP_ASSERT(obj->f_list_int64.valueType->name == oatpp::data::mapping::type::__class::AbstractList::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->_list_float32.valueType->name);
OATPP_ASSERT(obj->_list_float32.valueType->name == oatpp::data::mapping::type::__class::AbstractList::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->f_list_float32.valueType->name);
OATPP_ASSERT(obj->f_list_float32.valueType->name == oatpp::data::mapping::type::__class::AbstractList::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->_list_float64.valueType->name);
OATPP_ASSERT(obj->_list_float64.valueType->name == oatpp::data::mapping::type::__class::AbstractList::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->f_list_float64.valueType->name);
OATPP_ASSERT(obj->f_list_float64.valueType->name == oatpp::data::mapping::type::__class::AbstractList::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->_list_boolean.valueType->name);
OATPP_ASSERT(obj->_list_boolean.valueType->name == oatpp::data::mapping::type::__class::AbstractList::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->f_list_boolean.valueType->name);
OATPP_ASSERT(obj->f_list_boolean.valueType->name == oatpp::data::mapping::type::__class::AbstractList::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->_map_string_string.valueType->name);
OATPP_ASSERT(obj->_map_string_string.valueType->name == oatpp::data::mapping::type::__class::AbstractListMap::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->f_map_string_string.valueType->name);
OATPP_ASSERT(obj->f_map_string_string.valueType->name == oatpp::data::mapping::type::__class::AbstractListMap::CLASS_NAME);
OATPP_LOGV(TAG, "type: '%s'", obj->obj1.valueType->name);
OATPP_ASSERT(obj->obj1.valueType->name == oatpp::data::mapping::type::__class::AbstractObject::CLASS_NAME);

View File

@ -44,18 +44,18 @@ typedef oatpp::parser::json::mapping::Deserializer Deserializer;
DTO_INIT(Test1, Object)
DTO_FIELD(String, _string);
DTO_FIELD(Int32, _int32);
DTO_FIELD(List<Int32>::ObjectWrapper, _list);
DTO_FIELD(String, f_string);
DTO_FIELD(Int32, f_int32);
DTO_FIELD(List<Int32>::ObjectWrapper, f_list);
static ObjectWrapper createTestInstance(){
auto result = Test1::createShared();
result->_string = "String Field";
result->_int32 = 5;
result->_list = List<Int32>::createShared();
result->_list->pushBack(1);
result->_list->pushBack(2);
result->_list->pushBack(3);
result->f_string = "String Field";
result->f_int32 = 5;
result->f_list = List<Int32>::createShared();
result->f_list->pushBack(1);
result->f_list->pushBack(2);
result->f_list->pushBack(3);
return result;
}

View File

@ -60,22 +60,22 @@ class Test : public DTO {
DTO_INIT(Test, DTO)
DTO_FIELD(String, _string);
DTO_FIELD(Int32, _int32);
DTO_FIELD(Int64, _int64);
DTO_FIELD(Float32, _float32);
DTO_FIELD(Float64, _float64);
DTO_FIELD(Boolean, _boolean);
DTO_FIELD(String, f_string);
DTO_FIELD(Int32, f_int32);
DTO_FIELD(Int64, f_int64);
DTO_FIELD(Float32, f_float32);
DTO_FIELD(Float64, f_float64);
DTO_FIELD(Boolean, f_boolean);
DTO_FIELD(List<String>::ObjectWrapper, _list_string) = List<String>::createShared();
DTO_FIELD(List<Int32>::ObjectWrapper, _list_int32) = List<Int32>::createShared();
DTO_FIELD(List<Int64>::ObjectWrapper, _list_int64) = List<Int64>::createShared();
DTO_FIELD(List<Float32>::ObjectWrapper, _list_float32) = List<Float32>::createShared();
DTO_FIELD(List<Float64>::ObjectWrapper, _list_float64) = List<Float64>::createShared();
DTO_FIELD(List<Boolean>::ObjectWrapper, _list_boolean) = List<Boolean>::createShared();
DTO_FIELD(List<String>::ObjectWrapper, f_list_string) = List<String>::createShared();
DTO_FIELD(List<Int32>::ObjectWrapper, f_list_int32) = List<Int32>::createShared();
DTO_FIELD(List<Int64>::ObjectWrapper, f_list_int64) = List<Int64>::createShared();
DTO_FIELD(List<Float32>::ObjectWrapper, f_list_float32) = List<Float32>::createShared();
DTO_FIELD(List<Float64>::ObjectWrapper, f_list_float64) = List<Float64>::createShared();
DTO_FIELD(List<Boolean>::ObjectWrapper, f_list_boolean) = List<Boolean>::createShared();
DTO_FIELD(List<TestChild::ObjectWrapper>::ObjectWrapper, _list_object) = List<TestChild::ObjectWrapper>::createShared();
DTO_FIELD(List<List<TestChild::ObjectWrapper>::ObjectWrapper>::ObjectWrapper, _list_list_object) = List<List<TestChild::ObjectWrapper>::ObjectWrapper>::createShared();
DTO_FIELD(List<TestChild::ObjectWrapper>::ObjectWrapper, f_list_object) = List<TestChild::ObjectWrapper>::createShared();
DTO_FIELD(List<List<TestChild::ObjectWrapper>::ObjectWrapper>::ObjectWrapper, f_list_list_object) = List<List<TestChild::ObjectWrapper>::ObjectWrapper>::createShared();
DTO_FIELD(Test::ObjectWrapper, obj1);
DTO_FIELD(TestChild::ObjectWrapper, child1);
@ -92,50 +92,50 @@ void DTOMapperTest::onRun(){
Test::ObjectWrapper test1 = Test::createShared();
test1->_string = "string value";
test1->_int32 = 32;
test1->_int64 = 64;
test1->_float32 = 0.32;
test1->_float64 = 0.64;
test1->_boolean = true;
test1->f_string = "string value";
test1->f_int32 = 32;
test1->f_int64 = 64;
test1->f_float32 = 0.32;
test1->f_float64 = 0.64;
test1->f_boolean = true;
test1->obj1 = Test::createShared();
test1->obj1->_string = "inner string";
test1->obj1->_list_string->pushBack("inner str_item_1");
test1->obj1->_list_string->pushBack("inner str_item_2");
test1->obj1->_list_string->pushBack("inner str_item_3");
test1->obj1->f_string = "inner string";
test1->obj1->f_list_string->pushBack("inner str_item_1");
test1->obj1->f_list_string->pushBack("inner str_item_2");
test1->obj1->f_list_string->pushBack("inner str_item_3");
test1->child1 = TestChild::createShared();
test1->child1->name = "child1_name";
test1->child1->secondName = "child1_second_name";
test1->_list_string->pushBack("str_item_1");
test1->_list_string->pushBack("str_item_2");
test1->_list_string->pushBack("str_item_3");
test1->f_list_string->pushBack("str_item_1");
test1->f_list_string->pushBack("str_item_2");
test1->f_list_string->pushBack("str_item_3");
test1->_list_int32->pushBack(321);
test1->_list_int32->pushBack(322);
test1->_list_int32->pushBack(323);
test1->f_list_int32->pushBack(321);
test1->f_list_int32->pushBack(322);
test1->f_list_int32->pushBack(323);
test1->_list_int64->pushBack(641);
test1->_list_int64->pushBack(642);
test1->_list_int64->pushBack(643);
test1->f_list_int64->pushBack(641);
test1->f_list_int64->pushBack(642);
test1->f_list_int64->pushBack(643);
test1->_list_float32->pushBack(0.321);
test1->_list_float32->pushBack(0.322);
test1->_list_float32->pushBack(0.323);
test1->f_list_float32->pushBack(0.321);
test1->f_list_float32->pushBack(0.322);
test1->f_list_float32->pushBack(0.323);
test1->_list_float64->pushBack(0.641);
test1->_list_float64->pushBack(0.642);
test1->_list_float64->pushBack(0.643);
test1->f_list_float64->pushBack(0.641);
test1->f_list_float64->pushBack(0.642);
test1->f_list_float64->pushBack(0.643);
test1->_list_boolean->pushBack(true);
test1->_list_boolean->pushBack(false);
test1->_list_boolean->pushBack(true);
test1->f_list_boolean->pushBack(true);
test1->f_list_boolean->pushBack(false);
test1->f_list_boolean->pushBack(true);
test1->_list_object->pushBack(TestChild::createShared("child", "1"));
test1->_list_object->pushBack(TestChild::createShared("child", "2"));
test1->_list_object->pushBack(TestChild::createShared("child", "3"));
test1->f_list_object->pushBack(TestChild::createShared("child", "1"));
test1->f_list_object->pushBack(TestChild::createShared("child", "2"));
test1->f_list_object->pushBack(TestChild::createShared("child", "3"));
auto l1 = DTO::List<TestChild::ObjectWrapper>::createShared();
auto l2 = DTO::List<TestChild::ObjectWrapper>::createShared();
@ -153,9 +153,9 @@ void DTOMapperTest::onRun(){
l3->pushBack(TestChild::createShared("list_3", "item_2"));
l3->pushBack(TestChild::createShared("list_3", "item_3"));
test1->_list_list_object->pushBack(l1);
test1->_list_list_object->pushBack(l2);
test1->_list_list_object->pushBack(l3);
test1->f_list_list_object->pushBack(l1);
test1->f_list_list_object->pushBack(l2);
test1->f_list_list_object->pushBack(l3);
auto result = mapper->writeToString(test1);
@ -168,23 +168,23 @@ void DTOMapperTest::onRun(){
oatpp::parser::Caret caret(result);
auto obj = mapper->readFromCaret<Test>(caret);
OATPP_ASSERT(obj->_string);
OATPP_ASSERT(obj->_string == test1->_string);
OATPP_ASSERT(obj->f_string);
OATPP_ASSERT(obj->f_string == test1->f_string);
OATPP_ASSERT(obj->_int32);
OATPP_ASSERT(obj->_int32->getValue() == test1->_int32->getValue());
OATPP_ASSERT(obj->f_int32);
OATPP_ASSERT(obj->f_int32->getValue() == test1->f_int32->getValue());
OATPP_ASSERT(obj->_int64);
OATPP_ASSERT(obj->_int64->getValue() == test1->_int64->getValue());
OATPP_ASSERT(obj->f_int64);
OATPP_ASSERT(obj->f_int64->getValue() == test1->f_int64->getValue());
OATPP_ASSERT(obj->_float32);
OATPP_ASSERT(obj->_float32->getValue() == test1->_float32->getValue());
OATPP_ASSERT(obj->f_float32);
OATPP_ASSERT(obj->f_float32->getValue() == test1->f_float32->getValue());
OATPP_ASSERT(obj->_float64);
OATPP_ASSERT(obj->_float64->getValue() == test1->_float64->getValue());
OATPP_ASSERT(obj->f_float64);
OATPP_ASSERT(obj->f_float64->getValue() == test1->f_float64->getValue());
OATPP_ASSERT(obj->_boolean);
OATPP_ASSERT(obj->_boolean->getValue() == test1->_boolean->getValue());
OATPP_ASSERT(obj->f_boolean);
OATPP_ASSERT(obj->f_boolean->getValue() == test1->f_boolean->getValue());
result = mapper->writeToString(obj);

View File

@ -58,18 +58,18 @@ namespace {
void parseStepByStep(const oatpp::String& text,
const oatpp::String& boundary,
const std::shared_ptr<oatpp::web::mime::multipart::StatefulParser::Listener>& listener,
v_int32 step)
const v_int32 step)
{
oatpp::web::mime::multipart::StatefulParser parser(boundary, listener, nullptr);
oatpp::data::stream::BufferInputStream stream(text.getPtr(), text->getData(), text->getSize());
v_char8 buffer[step];
v_char8 *buffer = new v_char8[step];
v_int32 size;
while((size = stream.read(buffer, step)) != 0) {
parser.parseNext(buffer, size);
}
delete[] buffer;
OATPP_ASSERT(parser.finished());
}
@ -80,7 +80,7 @@ namespace {
OATPP_ASSERT(part->getInMemoryData() == value);
v_int32 bufferSize = 16;
v_char8 buffer[bufferSize];
v_char8 *buffer = new v_char8[bufferSize];
oatpp::data::stream::ChunkedBuffer stream;
oatpp::data::stream::DefaultWriteCallback writeCallback(&stream);
@ -90,6 +90,8 @@ namespace {
OATPP_ASSERT(readData == part->getInMemoryData());
delete[] buffer;
}
}