Merge pull request #244 from oatpp/v_1.1.0

V 1.1.0
This commit is contained in:
Leonid Stryzhevskyi 2020-05-16 19:15:44 +03:00 committed by GitHub
commit e4d0776584
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
99 changed files with 7542 additions and 1648 deletions

View File

@ -50,7 +50,7 @@ For more info see [Api Controller](https://oatpp.io/docs/components/api-controll
```cpp
ENDPOINT("PUT", "/users/{userId}", putUser,
PATH(Int64, userId),
BODY_DTO(dto::UserDto::ObjectWrapper, userDto))
BODY_DTO(dto::UserDto, userDto))
{
userDto->id = userId;
return createDtoResponse(Status::CODE_200, m_database->updateUser(userDto));
@ -65,7 +65,7 @@ For more info see [Api Controller / CORS](https://oatpp.io/docs/components/api-c
ADD_CORS(putUser)
ENDPOINT("PUT", "/users/{userId}", putUser,
PATH(Int64, userId),
BODY_DTO(dto::UserDto::ObjectWrapper, userDto))
BODY_DTO(dto::UserDto, userDto))
{
userDto->id = userId;
return createDtoResponse(Status::CODE_200, m_database->updateUser(userDto));
@ -82,7 +82,7 @@ using namespace oatpp::web::server::handler;
ENDPOINT("PUT", "/users/{userId}", putUser,
AUTHORIZATION(std::shared_ptr<DefaultBasicAuthorizationObject>, authObject),
PATH(Int64, userId),
BODY_DTO(dto::UserDto::ObjectWrapper, userDto))
BODY_DTO(dto::UserDto, userDto))
{
OATPP_ASSERT_HTTP(authObject->userId == "Ivan" && authObject->password == "admin", Status::CODE_401, "Unauthorized");
userDto->id = userId;
@ -100,15 +100,15 @@ For more info see [Endpoint Annotation And API Documentation](https://oatpp.io/d
ENDPOINT_INFO(putUser) {
// general
info->summary = "Update User by userId";
info->addConsumes<dto::UserDto::ObjectWrapper>("application/json");
info->addResponse<dto::UserDto::ObjectWrapper>(Status::CODE_200, "application/json");
info->addConsumes<dto::UserDto>("application/json");
info->addResponse<dto::UserDto>(Status::CODE_200, "application/json");
info->addResponse<String>(Status::CODE_404, "text/plain");
// params specific
info->pathParams["userId"].description = "User Identifier";
}
ENDPOINT("PUT", "/users/{userId}", putUser,
PATH(Int64, userId),
BODY_DTO(dto::UserDto::ObjectWrapper, userDto))
BODY_DTO(dto::UserDto, userDto))
{
userDto->id = userId;
return createDtoResponse(Status::CODE_200, m_database->updateUser(userDto));

322
changelog/1.1.0.md Normal file
View File

@ -0,0 +1,322 @@
# Oat++ 1.1.0
Oat++ `1.1.0` is introducing breaking changes.
Please read carefully to prepare for migration.
Feel free to ask questions - [Chat on Gitter](https://gitter.im/oatpp-framework/Lobby)
Contents:
- [No more explicit ObjectWrapper](#no-more-explicit-objectwrapper)
- [Object-Mapping Simplified Primitives](#object-mapping-simplified-primitives)
- [Object-Mapping std Collections](#object-mapping-std-collections)
- [Type oatpp::Any](#type-oatppany)
- [Type oatpp::Enum](#object-mapping-enum)
- [DTO - Hashcode & Equals](#dto-hashcode-and-equals)
- [DTO - Fields Annotation](#dto-fields-annotation)
## No more explicit ObjectWrapper
Do not explicitly write `ObjectWrapper`
DTO:
```cpp
class MyDto : oatpp::Object {
DTO_INIT(MyDto, Object)
DTO_FIELD(MyDto, nested);
DTO_FIELD(List<Any>, listOfAny);
DTO_FIELD(Fields<List<String>>, mapOfLists);
}
```
ApiController:
```cpp
ENDPOINT("POST", "body-dto", postWithBody,
BODY_DTO(MyDto, body)) {
...
}
```
## Object-Mapping Simplified Primitives
No more `<primitive>->getValue()`.
```cpp
oatpp::Int32 objV = 32;
v_int32 v = objV; // You may check for nullptr before doing this
bool equals = v == objV; // <--- NO NEED to check for nullptr here
bool isNull = objV == nullptr;
bool isNull = !objV;
```
## Object-Mapping std Collections
Now `oatpp::<mapping-enabled-collections>` are based on `std::<collections>`
Example:
```cpp
oatpp::Vector<oatpp::String> vector = oatpp::Vector<oatpp::String>::createShared();
oatpp::List<oatpp::String> list = oatpp::List<oatpp::String>::createShared();
oatpp::UnorderedSet<oatpp::String> set = oatpp::UnorderedSet<oatpp::String>::createShared();
oatpp::Fields<oatpp::String> pairList= oatpp::Fields<oatpp::String>::createShared();
oatpp::UnorderedFields<oatpp::String> hashMap = oatpp::UnorderedFields<oatpp::String>::createShared();
oatpp::Vector<oatpp::String> vector = {"a", "b", "c"};
oatpp::List<oatpp::String> list = {"a", "b", "c"};
oatpp::UnorderedSet<oatpp::String> set = {"a", "b", "c"};
oatpp::Fields<oatpp::String> pairList = {{"k1", "v1"}, {"k2", "v2"}, {"k3", "v3"}};
oatpp::UnorderedFields<oatpp::String> hashMap = {{"k1", "v1"}, {"k2", "v2"}, {"k3", "v3"}};
vector[0] = "z"; // <--- Complexity = O(1);
vector->push_back("www");
list[0] = "z"; // <--- Complexity = O(n);
list->push_back("www");
bool contains = set["b"]; // <--- Complexity = O(1);
set->insert("z")
pairList["k1"] = "z"; // <--- Complexity = O(n);
pairList->push_back({"key_z", "z"});
hashMap["k1"] = "z" // <--- Complexity = O(1);
hashMap->insert({"key_z", "z"});
for(auto& item : *vector) {
...
}
for(auto& item : *list) {
...
}
for(auto& item : *set) {
...
}
for(auto& pair : *pairList) {
...
}
for(auto& pair : *hashMap) {
...
}
```
## Type oatpp::Any
The new Type Introduced - `oatpp::Any`.
Now it's possible to do like this:
```cpp
class MyDto : public oatpp::Object {
DTO_INIT(MyDto, Object)
DTO_FIELD(Any, any); // Put any oatpp::<Type> here
DTO_FIELD(List<Any>, listOfAny)
DTO_FIELD(Fields<Any>, mapOfAny);
};
```
### JSON Serializer
Will serialize Any depending on the value type it stores.
### JSON Deserializer
Will try to guess the type of the `Any`.
Currently, `Any` is deserialized as follows:
- JSON objects are deserialized to `Any` holding `oatpp::Fields<Any>`.
- JSON lists are deserialized to `Any` holding `oatpp::List<Any>`.
- JSON `null` is deserialized to `Any` holding `nullptr`.
- JSON `true`/`false` is deserialized to `Any` holding `oatpp::Boolean`.
- JSON `number` is deserialized to `Any` holding `oatpp::Float64`.
### Example
```cpp
oatpp::Fields<oatpp::Any> map = {
{"title", oatpp::String("Hello Any!")},
{"listOfAny",
oatpp::List<oatpp::Any>({
oatpp::Int32(32),
oatpp::Float32(0.32),
oatpp::Boolean(true)
})
}
};
auto json = mapper->writeToString(map);
```
**Output:**
```json
{
"title": "Hello Any!",
"listOfAny": [
32,
0.3199999928474426,
true
]
}
```
## Object-Mapping Enum
Enum is added to DTO codegen.
### Declaration
```cpp
#include OATPP_CODEGEN_BEGIN(DTO)
ENUM(Enum1, v_int32, // <-- type is mandatory
VALUE(V_1, 1), // <-- integral value is mandatory
VALUE(V_2, 2, "name-2"),
VALUE(V_3, 3, "name-3", "description_3")
)
#include OATPP_CODEGEN_END(DTO)
```
This will generate:
```cpp
enum class Enum1 : v_int32 {
V_1 = 1,
V_2 = 2,
V_3 = 3
}
... // PLUS Meta here
```
Current limitation - `ENUM` can not be declared nested in the class :(.
This may be fixed later.
### Usage
#### DTO
```cpp
ENUM(MyEnum, v_int32,
VALUE(V1, 10, "enum1-v1"),
VALUE(V2, 20, "enum1-v2"),
VALUE(V3, 30, "enum1-v3")
);
class MyDto : public oatpp::Object {
DTO_INIT(MyDto, Object)
DTO_FIELD(Enum<MyEnum>, enum1); // Default interpretation - AsString
DTO_FIELD(Enum<MyEnum>::NotNull, enum2); // NOT_NULL constraint for Ser/De
DTO_FIELD(Enum<MyEnum>::AsString, enum3); // Ser/De as string name
DTO_FIELD(Enum<MyEnum>::AsNumber, enum4); // Ser/De as a corresponding integral value
DTO_FIELD(Enum<MyEnum>::AsString::NotNull, enum5);
DTO_FIELD(Enum<MyEnum>::AsNumber::NotNull, enum6);
};
```
#### ApiController
```cpp
ENDPOINT("GET", "enum/as-string", testEnumString,
HEADER(Enum<AllowedHeaderValues>::AsString, enumValue, "X-MyEnum"))
{
return createResponse(Status::CODE_200, "OK");
}
ENDPOINT("GET", "enum/as-number", testEnumNumber,
HEADER(Enum<AllowedHeaderValues>::AsNumber, enumValue, "X-MyEnum"))
{
return createResponse(Status::CODE_200, "OK");
}
```
#### ApiClient
```cpp
API_CALL("GET", "enum/as-string", getWithEnumHeaderAsString, HEADER(Enum<AllowedHeaderValues>::AsString, enumValue, "X-MyEnum"))
API_CALL("GET", "enum/as-number", getWithEnumHeaderAsNumber, HEADER(Enum<AllowedHeaderValues>::AsNumber, enumValue, "X-MyEnum"))
```
### Meta functions
```cpp
{
auto entry = oatpp::Enum<MyEnum>::getEntryByName("<name>");
auto entry = oatpp::Enum<MyEnum>::getEntryByValue(MyEnum::VALUE);
auto entry = oatpp::Enum<MyEnum>::getEntryByUnderlyingValue(123);
auto entry = oatpp::Enum<MyEnum>::getEntryByIndex(0);
...
OATPP_LOGD("Entry", "%d, %s, %d, %d, %s", entry.index, entry.name, entry.value, entry.description);
}
{
const auto& entries = oatpp::Enum<MyEnum>::getEntries();
for(const auto& e : entries) {
...
}
}
```
## DTO Hashcode and Equals
Now DTOs can be used as a Key in `unordered_map` and `unordered_set`.
The convenience `DTO_HC_EQ` (DTO_HASHCODE_AND_EQUALS) macro has been added.
```cpp
class User : public oatpp::Object {
DTO_INIT(User, Object)
DTO_FIELD(String, firstName);
DTO_FIELD(String, lastName);
DTO_HC_EQ(firstName, lastName) // List key fields that count in std::hash and "==","!=" operators.
};
```
The `DTO_HC_EQ` macro works taking into account the `DTO_HC_EQ` declared in the parent DTO class.
If no `DTO_HC_EQ` is declared in none of the DTO's parent classes the default behavior is:
- `std::hash` - is `v_uint64` representation of object address.
- operators `==` and `!=` - is comparison of object addresses.
## DTO Fields Annotation
Now it's possible to add a description for DTO fields, which will be automatically
displayed in swagger-UI.
```cpp
class MyDto : public oatpp::Object {
DTO_INIT(MyDto, Object)
DTO_FIELD_INFO(id) {
info->description = "identifier";
}
DTO_FIELD(String, id);
};
```
*Note: The `description` is currently the only info you can add to the DTO field
(This may be extended later). In order to provide the list of possible values - use the
new Enum feature - [Type oatpp::Enum](#object-mapping-enum).*

View File

@ -11,12 +11,16 @@ add_library(oatpp
oatpp/codegen/api_controller/auth_undef.hpp
oatpp/codegen/api_controller/cors_define.hpp
oatpp/codegen/api_controller/cors_undef.hpp
oatpp/codegen/codegen_define_ApiClient_.hpp
oatpp/codegen/codegen_define_ApiController_.hpp
oatpp/codegen/codegen_define_DTO_.hpp
oatpp/codegen/codegen_undef_ApiClient_.hpp
oatpp/codegen/codegen_undef_ApiController_.hpp
oatpp/codegen/codegen_undef_DTO_.hpp
oatpp/codegen/ApiController_define.hpp
oatpp/codegen/ApiController_undef.hpp
oatpp/codegen/ApiClient_define.hpp
oatpp/codegen/ApiClient_undef.hpp
oatpp/codegen/dto/base_define.hpp
oatpp/codegen/dto/base_undef.hpp
oatpp/codegen/dto/enum_define.hpp
oatpp/codegen/dto/enum_undef.hpp
oatpp/codegen/DTO_define.hpp
oatpp/codegen/DTO_undef.hpp
oatpp/core/Types.hpp
oatpp/core/async/Coroutine.cpp
oatpp/core/async/Coroutine.hpp
@ -74,16 +78,26 @@ add_library(oatpp
oatpp/core/data/buffer/Processor.hpp
oatpp/core/data/mapping/ObjectMapper.cpp
oatpp/core/data/mapping/ObjectMapper.hpp
oatpp/core/data/mapping/type/Any.cpp
oatpp/core/data/mapping/type/Any.hpp
oatpp/core/data/mapping/type/Enum.cpp
oatpp/core/data/mapping/type/Enum.hpp
oatpp/core/data/mapping/type/List.cpp
oatpp/core/data/mapping/type/List.hpp
oatpp/core/data/mapping/type/ListMap.cpp
oatpp/core/data/mapping/type/ListMap.hpp
oatpp/core/data/mapping/type/PairList.cpp
oatpp/core/data/mapping/type/PairList.hpp
oatpp/core/data/mapping/type/Object.cpp
oatpp/core/data/mapping/type/Object.hpp
oatpp/core/data/mapping/type/Primitive.cpp
oatpp/core/data/mapping/type/Primitive.hpp
oatpp/core/data/mapping/type/Type.cpp
oatpp/core/data/mapping/type/Type.hpp
oatpp/core/data/mapping/type/UnorderedMap.cpp
oatpp/core/data/mapping/type/UnorderedMap.hpp
oatpp/core/data/mapping/type/UnorderedSet.cpp
oatpp/core/data/mapping/type/UnorderedSet.hpp
oatpp/core/data/mapping/type/Vector.cpp
oatpp/core/data/mapping/type/Vector.hpp
oatpp/core/data/share/LazyStringMap.hpp
oatpp/core/data/share/MemoryLabel.cpp
oatpp/core/data/share/MemoryLabel.hpp

View File

@ -46,7 +46,7 @@
#include "oatpp/core/macro/codegen.hpp"
#define OATPP_MACRO_API_CLIENT_PARAM_MACRO(MACRO, TYPE, PARAM_LIST) MACRO(TYPE, PARAM_LIST)
#define OATPP_MACRO_API_CLIENT_PARAM_TYPE(MACRO, TYPE, PARAM_LIST) TYPE
#define OATPP_MACRO_API_CLIENT_PARAM_TYPE(MACRO, TYPE, PARAM_LIST) const TYPE&
#define OATPP_MACRO_API_CLIENT_PARAM_NAME(MACRO, TYPE, PARAM_LIST) OATPP_MACRO_FIRSTARG PARAM_LIST
#define OATPP_MACRO_API_CLIENT_PARAM_TYPE_STR(MACRO, TYPE, PARAM_LIST) #TYPE
#define OATPP_MACRO_API_CLIENT_PARAM_NAME_STR(MACRO, TYPE, PARAM_LIST) OATPP_MACRO_FIRSTARG_STR PARAM_LIST
@ -56,14 +56,14 @@
#define PATH(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_PATH, TYPE, (__VA_ARGS__))
#define QUERY(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_QUERY, TYPE, (__VA_ARGS__))
#define BODY(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_BODY, TYPE, (__VA_ARGS__))
#define BODY_DTO(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_BODY_DTO, TYPE, (__VA_ARGS__))
#define BODY_DTO(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_BODY_DTO, TYPE::__Wrapper, (__VA_ARGS__))
#define BODY_STRING(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_BODY_STRING, TYPE, (__VA_ARGS__))
#define AUTHORIZATION(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_AUTHORIZATION, TYPE, (__VA_ARGS__))
#define AUTHORIZATION_BASIC(TYPE, ...) OATPP_MACRO_API_CLIENT_PARAM(OATPP_MACRO_API_CLIENT_AUTHORIZATION_BASIC, TYPE, (__VA_ARGS__))
//////////////////////////////////////////////////////////////////////////
#define OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(MACRO, TYPE, ...) \
#define OATPP_MACRO_API_CLIENT_MACRO_SELECTOR(MACRO, TYPE, ...) \
OATPP_MACRO_EXPAND(OATPP_MACRO_MACRO_SELECTOR(MACRO, (__VA_ARGS__)) (TYPE, __VA_ARGS__))
//////////////////////////////////////////////////////////////////////////
@ -89,35 +89,35 @@ public: \
// HEADER MACRO
#define OATPP_MACRO_API_CLIENT_HEADER_1(TYPE, NAME) \
__headers->put(#NAME, convertParameterToString(#TYPE, NAME));
__headers->put(#NAME, ApiClient::TypeInterpretation<TYPE>::toString(#TYPE, NAME));
#define OATPP_MACRO_API_CLIENT_HEADER_2(TYPE, NAME, QUALIFIER) \
__headers->put(QUALIFIER, convertParameterToString(#TYPE, NAME));
__headers->put(QUALIFIER, ApiClient::TypeInterpretation<TYPE>::toString(#TYPE, NAME));
#define OATPP_MACRO_API_CLIENT_HEADER(TYPE, PARAM_LIST) \
OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CLIENT_HEADER_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
OATPP_MACRO_API_CLIENT_MACRO_SELECTOR(OATPP_MACRO_API_CLIENT_HEADER_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
// PATH MACRO
#define OATPP_MACRO_API_CLIENT_PATH_1(TYPE, NAME) \
__pathParams->put(#NAME, convertParameterToString(#TYPE, NAME));
__pathParams->put(#NAME, ApiClient::TypeInterpretation<TYPE>::toString(#TYPE, NAME));
#define OATPP_MACRO_API_CLIENT_PATH_2(TYPE, NAME, QUALIFIER) \
__pathParams->put(QUALIFIER, convertParameterToString(#TYPE, NAME));
__pathParams->put(QUALIFIER, ApiClient::TypeInterpretation<TYPE>::toString(#TYPE, NAME));
#define OATPP_MACRO_API_CLIENT_PATH(TYPE, PARAM_LIST) \
OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CLIENT_PATH_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
OATPP_MACRO_API_CLIENT_MACRO_SELECTOR(OATPP_MACRO_API_CLIENT_PATH_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
// QUERY MACRO
#define OATPP_MACRO_API_CLIENT_QUERY_1(TYPE, NAME) \
__queryParams->put(#NAME, convertParameterToString(#TYPE, NAME));
__queryParams->put(#NAME, ApiClient::TypeInterpretation<TYPE>::toString(#TYPE, NAME));
#define OATPP_MACRO_API_CLIENT_QUERY_2(TYPE, NAME, QUALIFIER) \
__queryParams->put(QUALIFIER, convertParameterToString(#TYPE, NAME));
__queryParams->put(QUALIFIER, ApiClient::TypeInterpretation<TYPE>::toString(#TYPE, NAME));
#define OATPP_MACRO_API_CLIENT_QUERY(TYPE, PARAM_LIST) \
OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CLIENT_QUERY_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
OATPP_MACRO_API_CLIENT_MACRO_SELECTOR(OATPP_MACRO_API_CLIENT_QUERY_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
// BODY MACRO
@ -143,7 +143,7 @@ __body = oatpp::web::protocol::http::outgoing::BufferBody::createShared(OATPP_MA
__headers->put("Authorization", String(SCHEME " ") + String(TOKEN));
#define OATPP_MACRO_API_CLIENT_AUTHORIZATION(TYPE, PARAM_LIST) \
OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CLIENT_AUTHORIZATION_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
OATPP_MACRO_API_CLIENT_MACRO_SELECTOR(OATPP_MACRO_API_CLIENT_AUTHORIZATION_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
// AUTHORIZATION_BASIC MACRO
@ -151,7 +151,7 @@ OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CLIENT_AUTHORIZATION_,
__headers->put("Authorization", String("Basic ") + oatpp::encoding::Base64::encode(TOKEN));
#define OATPP_MACRO_API_CLIENT_AUTHORIZATION_BASIC(TYPE, PARAM_LIST) \
OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CLIENT_AUTHORIZATION_BASIC_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
OATPP_MACRO_API_CLIENT_MACRO_SELECTOR(OATPP_MACRO_API_CLIENT_AUTHORIZATION_BASIC_, TYPE, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
// FOR EACH

View File

@ -59,7 +59,7 @@
#undef AUTHORIZATION_BASIC
//
#undef OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR
#undef OATPP_MACRO_API_CLIENT_MACRO_SELECTOR
// INIT

View File

@ -0,0 +1,49 @@
/***************************************************************************
*
* 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.
*
***************************************************************************/
/**[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"
#include "./dto/base_define.hpp"
#include "./dto/enum_define.hpp"

View File

@ -42,10 +42,5 @@
* </ul>
*/
#undef DTO_INIT
// Fields
#undef OATPP_MACRO_DTO_FIELD_1
#undef OATPP_MACRO_DTO_FIELD_2
#undef DTO_FIELD
#include "./dto/base_undef.hpp"
#include "./dto/enum_undef.hpp"

View File

@ -24,7 +24,7 @@
#define OATPP_MACRO_API_CONTROLLER_PARAM_MACRO(MACRO, INFO, TYPE, PARAM_LIST) MACRO(TYPE, PARAM_LIST)
#define OATPP_MACRO_API_CONTROLLER_PARAM_INFO(MACRO, INFO, TYPE, PARAM_LIST) INFO(TYPE, PARAM_LIST)
#define OATPP_MACRO_API_CONTROLLER_PARAM_TYPE(MACRO, INFO, TYPE, PARAM_LIST) TYPE
#define OATPP_MACRO_API_CONTROLLER_PARAM_TYPE(MACRO, INFO, TYPE, PARAM_LIST) const TYPE&
#define OATPP_MACRO_API_CONTROLLER_PARAM_NAME(MACRO, INFO, TYPE, PARAM_LIST) OATPP_MACRO_FIRSTARG PARAM_LIST
#define OATPP_MACRO_API_CONTROLLER_PARAM_TYPE_STR(MACRO, INFO, TYPE, PARAM_LIST) #TYPE
#define OATPP_MACRO_API_CONTROLLER_PARAM_NAME_STR(MACRO, INFO, TYPE, PARAM_LIST) OATPP_MACRO_FIRSTARG_STR PARAM_LIST
@ -49,7 +49,7 @@ OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_QUERY, OATPP_MACRO_A
OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_BODY_STRING, OATPP_MACRO_API_CONTROLLER_BODY_STRING_INFO, TYPE, (__VA_ARGS__))
#define BODY_DTO(TYPE, ...) \
OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_BODY_DTO, OATPP_MACRO_API_CONTROLLER_BODY_DTO_INFO, TYPE, (__VA_ARGS__))
OATPP_MACRO_API_CONTROLLER_PARAM(OATPP_MACRO_API_CONTROLLER_BODY_DTO, OATPP_MACRO_API_CONTROLLER_BODY_DTO_INFO, TYPE::__Wrapper, (__VA_ARGS__))
//////////////////////////////////////////////////////////////////////////
@ -61,7 +61,7 @@ OATPP_MACRO_EXPAND(OATPP_MACRO_MACRO_SELECTOR(MACRO, (__VA_ARGS__)) (TYPE, __VA_
// REQUEST MACRO // ------------------------------------------------------
#define OATPP_MACRO_API_CONTROLLER_REQUEST(TYPE, PARAM_LIST) \
TYPE OATPP_MACRO_FIRSTARG PARAM_LIST = __request;
const auto& OATPP_MACRO_FIRSTARG PARAM_LIST = __request;
#define OATPP_MACRO_API_CONTROLLER_REQUEST_INFO(TYPE, PARAM_LIST)
@ -69,24 +69,24 @@ TYPE OATPP_MACRO_FIRSTARG PARAM_LIST = __request;
// HEADER MACRO // ------------------------------------------------------
#define OATPP_MACRO_API_CONTROLLER_HEADER_1(TYPE, NAME) \
auto __param_str_val_##NAME = __request->getHeader(#NAME); \
const auto& __param_str_val_##NAME = __request->getHeader(#NAME); \
if(!__param_str_val_##NAME){ \
return ApiController::handleError(Status::CODE_400, "Missing HEADER parameter '" #NAME "'"); \
} \
bool __param_validation_check_##NAME; \
TYPE NAME = parseParameterFromString<TYPE>(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
const auto& NAME = ApiController::TypeInterpretation<TYPE>::fromString(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
if(!__param_validation_check_##NAME){ \
return ApiController::handleError(Status::CODE_400, "Invalid HEADER parameter '" #NAME "'. Expected type is '" #TYPE "'"); \
}
#define OATPP_MACRO_API_CONTROLLER_HEADER_2(TYPE, NAME, QUALIFIER) \
auto __param_str_val_##NAME = __request->getHeader(QUALIFIER); \
const auto& __param_str_val_##NAME = __request->getHeader(QUALIFIER); \
if(!__param_str_val_##NAME){ \
return ApiController::handleError(Status::CODE_400, \
oatpp::String("Missing HEADER parameter '") + QUALIFIER + "'"); \
} \
bool __param_validation_check_##NAME; \
TYPE NAME = parseParameterFromString<TYPE>(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
const auto& NAME = ApiController::TypeInterpretation<TYPE>::fromString(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
if(!__param_validation_check_##NAME){ \
return ApiController::handleError(Status::CODE_400, \
oatpp::String("Invalid HEADER parameter '") + \
@ -112,24 +112,24 @@ OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_HEADER_INFO
// PATH MACRO // ------------------------------------------------------
#define OATPP_MACRO_API_CONTROLLER_PATH_1(TYPE, NAME) \
auto __param_str_val_##NAME = __request->getPathVariable(#NAME); \
const auto& __param_str_val_##NAME = __request->getPathVariable(#NAME); \
if(!__param_str_val_##NAME){ \
return ApiController::handleError(Status::CODE_400, "Missing PATH parameter '" #NAME "'"); \
} \
bool __param_validation_check_##NAME; \
TYPE NAME = parseParameterFromString<TYPE>(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
const auto& NAME = ApiController::TypeInterpretation<TYPE>::fromString(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
if(!__param_validation_check_##NAME){ \
return ApiController::handleError(Status::CODE_400, "Invalid PATH parameter '" #NAME "'. Expected type is '" #TYPE "'"); \
}
#define OATPP_MACRO_API_CONTROLLER_PATH_2(TYPE, NAME, QUALIFIER) \
auto __param_str_val_##NAME = __request->getPathVariable(QUALIFIER); \
const auto& __param_str_val_##NAME = __request->getPathVariable(QUALIFIER); \
if(!__param_str_val_##NAME){ \
return ApiController::handleError(Status::CODE_400, \
oatpp::String("Missing PATH parameter '") + QUALIFIER + "'"); \
} \
bool __param_validation_check_##NAME; \
TYPE NAME = parseParameterFromString<TYPE>(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
const auto NAME = ApiController::TypeInterpretation<TYPE>::fromString(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
if(!__param_validation_check_##NAME){ \
return ApiController::handleError(Status::CODE_400, \
oatpp::String("Invalid PATH parameter '") + \
@ -154,31 +154,31 @@ OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_PATH_INFO_,
// QUERIES MACRO // ------------------------------------------------------
#define OATPP_MACRO_API_CONTROLLER_QUERIES(TYPE, PARAM_LIST) \
TYPE OATPP_MACRO_FIRSTARG PARAM_LIST = __request->getQueryParameters();
const auto& OATPP_MACRO_FIRSTARG PARAM_LIST = __request->getQueryParameters();
#define OATPP_MACRO_API_CONTROLLER_QUERIES_INFO(TYPE, PARAM_LIST)
// QUERY MACRO // ------------------------------------------------------
#define OATPP_MACRO_API_CONTROLLER_QUERY_1(TYPE, NAME) \
auto __param_str_val_##NAME = __request->getQueryParameter(#NAME); \
const auto& __param_str_val_##NAME = __request->getQueryParameter(#NAME); \
if(!__param_str_val_##NAME){ \
return ApiController::handleError(Status::CODE_400, "Missing QUERY parameter '" #NAME "'"); \
} \
bool __param_validation_check_##NAME; \
TYPE NAME = parseParameterFromString<TYPE>(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
const auto& NAME = ApiController::TypeInterpretation<TYPE>::fromString(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
if(!__param_validation_check_##NAME){ \
return ApiController::handleError(Status::CODE_400, "Invalid QUERY parameter '" #NAME "'. Expected type is '" #TYPE "'"); \
}
#define OATPP_MACRO_API_CONTROLLER_QUERY_2(TYPE, NAME, QUALIFIER) \
auto __param_str_val_##NAME = __request->getQueryParameter(QUALIFIER); \
const auto& __param_str_val_##NAME = __request->getQueryParameter(QUALIFIER); \
if(!__param_str_val_##NAME){ \
return ApiController::handleError(Status::CODE_400, \
oatpp::String("Missing QUERY parameter '") + QUALIFIER + "'"); \
} \
bool __param_validation_check_##NAME; \
TYPE NAME = parseParameterFromString<TYPE>(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
const auto& NAME = ApiController::TypeInterpretation<TYPE>::fromString(#TYPE, __param_str_val_##NAME, __param_validation_check_##NAME); \
if(!__param_validation_check_##NAME){ \
return ApiController::handleError(Status::CODE_400, \
oatpp::String("Invalid QUERY parameter '") + \
@ -203,7 +203,7 @@ OATPP_MACRO_API_CONTROLLER_MACRO_SELECTOR(OATPP_MACRO_API_CONTROLLER_QUERY_INFO_
// BODY_STRING MACRO // ------------------------------------------------------
#define OATPP_MACRO_API_CONTROLLER_BODY_STRING(TYPE, PARAM_LIST) \
TYPE OATPP_MACRO_FIRSTARG PARAM_LIST = __request->readBodyToString();
const auto& OATPP_MACRO_FIRSTARG PARAM_LIST = __request->readBodyToString();
// __INFO
@ -214,8 +214,8 @@ info->body.type = oatpp::data::mapping::type::__class::String::getType();
// BODY_DTO MACRO // ------------------------------------------------------
#define OATPP_MACRO_API_CONTROLLER_BODY_DTO(TYPE, PARAM_LIST) \
TYPE OATPP_MACRO_FIRSTARG PARAM_LIST; \
__request->readBodyToDto(OATPP_MACRO_FIRSTARG PARAM_LIST, getDefaultObjectMapper().get()); \
const auto& OATPP_MACRO_FIRSTARG PARAM_LIST = \
__request->readBodyToDto<TYPE>(getDefaultObjectMapper().get()); \
if(!OATPP_MACRO_FIRSTARG PARAM_LIST) { \
return ApiController::handleError(Status::CODE_400, "Missing valid body parameter '" OATPP_MACRO_FIRSTARG_STR PARAM_LIST "'"); \
}

View File

@ -1,144 +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.
*
***************************************************************************/
/**[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; \
typedef TYPE_EXTEND Z__CLASS_EXTENDED; \
typedef oatpp::data::mapping::type::ObjectWrapper<Z__CLASS, oatpp::data::mapping::type::__class::Object<Z__CLASS>> ObjectWrapper; \
public: \
OBJECT_POOL(DTO_OBJECT_POOL_##TYPE_NAME, TYPE_NAME, 32) \
SHARED_OBJECT_POOL(SHARED_DTO_OBJECT_POOL_##TYPE_NAME, TYPE_NAME, 32) \
protected: \
oatpp::data::mapping::type::Type::Properties* Z__CLASS_INIT_FIELDS(oatpp::data::mapping::type::Type::Properties* properties, \
oatpp::data::mapping::type::Type::Properties* extensionProperties) { \
static oatpp::data::mapping::type::Type::Properties* ptr = Z__CLASS_EXTEND(properties, extensionProperties); \
return ptr; \
} \
public: \
TYPE_NAME() \
{ \
Z__CLASS_INIT_FIELDS(Z__CLASS::Z__CLASS_GET_FIELDS_MAP(), TYPE_EXTEND::Z__CLASS_GET_FIELDS_MAP()); \
} \
public: \
\
static ObjectWrapper createShared(){ \
return ObjectWrapper(SHARED_DTO_OBJECT_POOL_##TYPE_NAME::allocateShared()); \
} \
\
static oatpp::data::mapping::type::Type::Properties* Z__CLASS_GET_FIELDS_MAP(){ \
static oatpp::data::mapping::type::Type::Properties map = oatpp::data::mapping::type::Type::Properties(); \
return &map; \
} \
\
static oatpp::data::mapping::type::AbstractObjectWrapper Z__CLASS_OBJECT_CREATOR(){ \
return oatpp::data::mapping::type::AbstractObjectWrapper(SHARED_DTO_OBJECT_POOL_##TYPE_NAME::allocateShared(), Z__CLASS_GET_TYPE()); \
} \
\
static oatpp::data::mapping::type::Type* Z__CLASS_GET_TYPE(){ \
static oatpp::data::mapping::type::Type type(oatpp::data::mapping::type::__class::AbstractObject::CLASS_ID, \
#TYPE_NAME, \
&Z__CLASS_OBJECT_CREATOR, \
Z__CLASS_GET_FIELDS_MAP()); \
return &type; \
}
// Fields
#define OATPP_MACRO_DTO_FIELD_1(TYPE, NAME) \
\
oatpp::data::mapping::type::Type::Property* Z__CLASS_FIELD_##NAME = \
Z__CLASS_GET_FIELD_##NAME(static_cast<oatpp::base::Countable*>(this), \
(oatpp::data::mapping::type::AbstractObjectWrapper*)(&NAME)); \
\
static oatpp::data::mapping::type::Type::Property* \
Z__CLASS_GET_FIELD_##NAME(oatpp::base::Countable* _this, \
oatpp::data::mapping::type::AbstractObjectWrapper* _reg) { \
static oatpp::data::mapping::type::Type::Property* field = \
new oatpp::data::mapping::type::Type::Property(Z__CLASS_GET_FIELDS_MAP(), \
(v_int64) _reg - (v_int64) _this, \
#NAME, \
TYPE::Class::getType()); \
return field; \
} \
\
TYPE NAME
#define OATPP_MACRO_DTO_FIELD_2(TYPE, NAME, QUALIFIER) \
\
oatpp::data::mapping::type::Type::Property* Z__CLASS_FIELD_##NAME = \
Z__CLASS_GET_FIELD_##NAME(static_cast<oatpp::base::Countable*>(this), \
(oatpp::data::mapping::type::AbstractObjectWrapper*)(&NAME)); \
\
static oatpp::data::mapping::type::Type::Property* \
Z__CLASS_GET_FIELD_##NAME(oatpp::base::Countable* _this, \
oatpp::data::mapping::type::AbstractObjectWrapper* _reg) { \
static oatpp::data::mapping::type::Type::Property* field = \
new oatpp::data::mapping::type::Type::Property(Z__CLASS_GET_FIELDS_MAP(), \
(v_int64) _reg - (v_int64) _this, \
QUALIFIER, \
TYPE::Class::getType()); \
return field; \
} \
\
TYPE NAME
/**
* 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, ...) \
OATPP_MACRO_EXPAND(OATPP_MACRO_MACRO_SELECTOR(OATPP_MACRO_DTO_FIELD_, (__VA_ARGS__)) (TYPE, __VA_ARGS__))

View File

@ -0,0 +1,178 @@
/***************************************************************************
*
* Project _____ __ ____ _ _
* ( _ ) /__\ (_ _)_| |_ _| |_
* )(_)( /(__)\ )( (_ _)(_ _)
* (_____)(__)(__)(__) |_| |_|
*
*
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
* Benedikt-Alexander Mokroß <bam@icognize.de>
*
* 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.
*
***************************************************************************/
// 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) \
template<class __Z__T__PARAM> \
friend class oatpp::data::mapping::type::__class::Object; \
public: \
typedef TYPE_NAME Z__CLASS; \
typedef TYPE_EXTEND Z__CLASS_EXTENDED; \
typedef oatpp::data::mapping::type::DTOWrapper<Z__CLASS> ObjectWrapper; \
typedef ObjectWrapper __Wrapper; \
private: \
static const char* Z__CLASS_TYPE_NAME() { \
return #TYPE_NAME; \
} \
\
static oatpp::data::mapping::type::Type::Properties* Z__CLASS_GET_FIELDS_MAP(){ \
static oatpp::data::mapping::type::Type::Properties map = oatpp::data::mapping::type::Type::Properties(); \
return &map; \
} \
public: \
\
TYPE_NAME() = default; \
\
template<typename ... Args> \
static ObjectWrapper createShared(Args... args){ \
return ObjectWrapper(std::make_shared<Z__CLASS>(args...), ObjectWrapper::Class::getType()); \
}
// Fields
#define OATPP_MACRO_DTO_FIELD_1(TYPE, NAME) \
\
static v_int64 Z__PROPERTY_OFFSET_##NAME() { \
char buffer[sizeof(Z__CLASS)]; \
auto obj = static_cast<Z__CLASS*>((void*)buffer); \
auto ptr = &obj->NAME; \
return (v_int64) ptr - (v_int64) buffer; \
} \
\
static oatpp::data::mapping::type::Type::Property* Z__PROPERTY_SINGLETON_##NAME() { \
static oatpp::data::mapping::type::Type::Property* property = \
new oatpp::data::mapping::type::Type::Property(Z__PROPERTY_OFFSET_##NAME(), \
#NAME, \
TYPE::__Wrapper::Class::getType()); \
return property; \
} \
\
static bool Z__PROPERTY_INIT_##NAME(... /* default initializer for all cases */) { \
Z__CLASS_GET_FIELDS_MAP()->pushBack(Z__PROPERTY_SINGLETON_##NAME()); \
return true; \
} \
\
static TYPE::__Wrapper Z__PROPERTY_INITIALIZER_PROXY_##NAME() { \
static bool initialized = Z__PROPERTY_INIT_##NAME(1 /* init info if found */); \
return TYPE::__Wrapper(); \
} \
\
TYPE::__Wrapper NAME = Z__PROPERTY_INITIALIZER_PROXY_##NAME()
#define OATPP_MACRO_DTO_FIELD_2(TYPE, NAME, QUALIFIER) \
\
static v_int64 Z__PROPERTY_OFFSET_##NAME() { \
char buffer[sizeof(Z__CLASS)]; \
auto obj = static_cast<Z__CLASS*>((void*)buffer); \
auto ptr = &obj->NAME; \
return (v_int64) ptr - (v_int64) buffer; \
} \
\
static oatpp::data::mapping::type::Type::Property* Z__PROPERTY_SINGLETON_##NAME() { \
static oatpp::data::mapping::type::Type::Property* property = \
new oatpp::data::mapping::type::Type::Property(Z__PROPERTY_OFFSET_##NAME(), \
QUALIFIER, \
TYPE::__Wrapper::Class::getType()); \
return property; \
} \
\
static bool Z__PROPERTY_INIT_##NAME(... /* default initializer for all cases */) { \
Z__CLASS_GET_FIELDS_MAP()->pushBack(Z__PROPERTY_SINGLETON_##NAME()); \
return true; \
} \
\
static TYPE::__Wrapper Z__PROPERTY_INITIALIZER_PROXY_##NAME() { \
static bool initialized = Z__PROPERTY_INIT_##NAME(1 /* init info if found */); \
return TYPE::__Wrapper(); \
} \
\
TYPE::__Wrapper NAME = Z__PROPERTY_INITIALIZER_PROXY_##NAME()
/**
* 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, ...) \
OATPP_MACRO_EXPAND(OATPP_MACRO_MACRO_SELECTOR(OATPP_MACRO_DTO_FIELD_, (__VA_ARGS__)) (TYPE, __VA_ARGS__))
// DTO_FIELD_INFO
#define DTO_FIELD_INFO(NAME) \
\
static bool Z__PROPERTY_INIT_##NAME(int) { \
Z__PROPERTY_INIT_##NAME(); /* call first initialization */ \
Z__PROPERTY_ADD_INFO_##NAME(&Z__PROPERTY_SINGLETON_##NAME()->info); \
return true; \
} \
\
static void Z__PROPERTY_ADD_INFO_##NAME(oatpp::data::mapping::type::Type::Property::Info* info)
// FOR EACH
#define OATPP_MACRO_DTO_HC_EQ_PARAM_HC(INDEX, COUNT, X) \
result = ((result << 5) - result) + std::hash<decltype(X)>{}(X);
#define OATPP_MACRO_DTO_HC_EQ_PARAM_EQ(INDEX, COUNT, X) \
&& X == other.X
#define DTO_HASHCODE_AND_EQUALS(...) \
v_uint64 defaultHashCode() const override { \
return 1; \
} \
\
bool defaultEquals(const Object& other) const override { \
return true; \
} \
\
v_uint64 hashCode() const { \
v_uint64 result = 1; \
result = ((result << 5) - result) + static_cast<const Z__CLASS_EXTENDED&>(*this).hashCode(); \
OATPP_MACRO_FOREACH(OATPP_MACRO_DTO_HC_EQ_PARAM_HC, __VA_ARGS__) \
return result; \
} \
\
bool operator==(const Z__CLASS& other) const { \
return static_cast<const Z__CLASS_EXTENDED&>(*this) == static_cast<const Z__CLASS_EXTENDED&>(other) \
OATPP_MACRO_FOREACH(OATPP_MACRO_DTO_HC_EQ_PARAM_EQ, __VA_ARGS__) \
; \
} \
\
bool operator!=(const Z__CLASS& other) const { \
return !this->operator==(other); \
}
/**
* Hashcode and Equals macro. <br>
* List DTO-fields which should count in hashcode and equals operators.
*/
#define DTO_HC_EQ(...) DTO_HASHCODE_AND_EQUALS(__VA_ARGS__)

View File

@ -0,0 +1,44 @@
/***************************************************************************
*
* Project _____ __ ____ _ _
* ( _ ) /__\ (_ _)_| |_ _| |_
* )(_)( /(__)\ )( (_ _)(_ _)
* (_____)(__)(__)(__) |_| |_|
*
*
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
* Benedikt-Alexander Mokroß <bam@icognize.de>
*
* 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.
*
***************************************************************************/
#undef DTO_INIT
// Fields
#undef OATPP_MACRO_DTO_FIELD_1
#undef OATPP_MACRO_DTO_FIELD_2
#undef DTO_FIELD
// Fields Info
#undef DTO_FIELD_INFO
// Hashcode & Equals
#undef OATPP_MACRO_DTO_HC_EQ_PARAM_HC
#undef OATPP_MACRO_DTO_HC_EQ_PARAM_EQ
#undef DTO_HASHCODE_AND_EQUALS
#undef DTO_HC_EQ

View File

@ -0,0 +1,164 @@
/***************************************************************************
*
* Project _____ __ ____ _ _
* ( _ ) /__\ (_ _)_| |_ _| |_
* )(_)( /(__)\ )( (_ _)(_ _)
* (_____)(__)(__)(__) |_| |_|
*
*
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
* Benedikt-Alexander Mokroß <bam@icognize.de>
*
* 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.
*
***************************************************************************/
#define OATPP_MACRO_DTO_ENUM_PARAM_MACRO(MACRO, NAME, PARAM_LIST) MACRO(NAME, PARAM_LIST)
#define OATPP_MACRO_DTO_ENUM_PARAM_NAME(MACRO, NAME, PARAM_LIST) NAME
#define OATPP_MACRO_DTO_ENUM_PARAM_NAME_STR(MACRO, NAME, PARAM_LIST) #NAME
#define OATPP_MACRO_DTO_ENUM_PARAM_VALUE(MACRO, NAME, PARAM_LIST) OATPP_MACRO_FIRSTARG PARAM_LIST
#define OATPP_MACRO_DTO_ENUM_PARAM_VALUE_STR(MACRO, NAME, PARAM_LIST) OATPP_MACRO_FIRSTARG_STR PARAM_LIST
#define OATPP_MACRO_DTO_ENUM_PARAM(MACRO, NAME, PARAM_LIST) (MACRO, NAME, PARAM_LIST)
#define VALUE(NAME, ...) OATPP_MACRO_DTO_ENUM_PARAM(OATPP_MACRO_DTO_ENUM_VALUE, NAME, (__VA_ARGS__))
//////////////////////////////////////////////////////////////////////////
#define OATPP_MACRO_DTO_ENUM_MACRO_SELECTOR(MACRO, NAME, ...) \
OATPP_MACRO_EXPAND(OATPP_MACRO_MACRO_SELECTOR(MACRO, (__VA_ARGS__)) (NAME, __VA_ARGS__))
//////////////////////////////////////////////////////////////////////////
// VALUE MACRO
#define OATPP_MACRO_DTO_ENUM_VALUE_1(NAME, VAL) \
{ \
oatpp::data::mapping::type::EnumValueInfo<EnumType> entry = {EnumType::NAME, index ++, #NAME, nullptr}; \
info.byName.insert({#NAME, entry}); \
info.byValue.insert({static_cast<v_uint64>(EnumType::NAME), entry}); \
info.byIndex.push_back(entry); \
}
#define OATPP_MACRO_DTO_ENUM_VALUE_2(NAME, VAL, QUALIFIER) \
{ \
oatpp::data::mapping::type::EnumValueInfo<EnumType> entry = {EnumType::NAME, index ++, QUALIFIER, nullptr}; \
info.byName.insert({QUALIFIER, entry}); \
info.byValue.insert({static_cast<v_uint64>(EnumType::NAME), entry}); \
info.byIndex.push_back(entry); \
}
#define OATPP_MACRO_DTO_ENUM_VALUE_3(NAME, VAL, QUALIFIER, DESCRIPTION) \
{ \
oatpp::data::mapping::type::EnumValueInfo<EnumType> entry = {EnumType::NAME, index ++, QUALIFIER, DESCRIPTION}; \
info.byName.insert({QUALIFIER, entry}); \
info.byValue.insert({static_cast<v_uint64>(EnumType::NAME), entry}); \
info.byIndex.push_back(entry); \
}
#define OATPP_MACRO_DTO_ENUM_VALUE(NAME, PARAM_LIST) \
OATPP_MACRO_DTO_ENUM_MACRO_SELECTOR(OATPP_MACRO_DTO_ENUM_VALUE_, NAME, OATPP_MACRO_UNFOLD_VA_ARGS PARAM_LIST)
// FOR EACH
#define OATPP_MACRO_DTO_ENUM_PARAM_DECL_FIRST(INDEX, COUNT, X) \
OATPP_MACRO_DTO_ENUM_PARAM_NAME X = OATPP_MACRO_DTO_ENUM_PARAM_VALUE X
#define OATPP_MACRO_DTO_ENUM_PARAM_DECL_REST(INDEX, COUNT, X) \
, OATPP_MACRO_DTO_ENUM_PARAM_NAME X = OATPP_MACRO_DTO_ENUM_PARAM_VALUE X
#define OATPP_MACRO_DTO_ENUM_PARAM_PUT(INDEX, COUNT, X) \
OATPP_MACRO_DTO_ENUM_PARAM_MACRO X
// ENUM MACRO
#define OATPP_ENUM_0(NAME, ORDINAL_TYPE) \
enum class NAME : ORDINAL_TYPE {}; \
\
namespace { \
\
class Z__OATPP_ENUM_META_##NAME : public oatpp::data::mapping::type::EnumMeta<NAME> { \
private: \
\
static bool init() { \
auto& info = *EnumMeta<NAME>::getInfo(); \
v_int32 index = 0; \
info.nameQualifier = #NAME; \
return true; \
} \
\
public: \
\
static bool initializer() { \
static bool initialized = init(); \
return initialized; \
} \
\
}; \
\
bool Z__OATPP_ENUM_META_INITIALIZER_##NAME = Z__OATPP_ENUM_META_##NAME::initializer(); \
\
}
#define OATPP_ENUM_1(NAME, ORDINAL_TYPE, ...) \
enum class NAME : ORDINAL_TYPE { \
OATPP_MACRO_FOREACH_FIRST_AND_REST( \
OATPP_MACRO_DTO_ENUM_PARAM_DECL_FIRST, \
OATPP_MACRO_DTO_ENUM_PARAM_DECL_REST, \
__VA_ARGS__ \
) \
}; \
\
namespace { \
\
class Z__OATPP_ENUM_META_##NAME : public oatpp::data::mapping::type::EnumMeta<NAME> { \
private: \
\
static bool init() { \
auto& info = *EnumMeta<NAME>::getInfo(); \
v_int32 index = 0; \
info.nameQualifier = #NAME; \
OATPP_MACRO_FOREACH(OATPP_MACRO_DTO_ENUM_PARAM_PUT, __VA_ARGS__) \
return true; \
} \
\
public: \
\
static bool initializer() { \
static bool initialized = init(); \
return initialized; \
} \
\
}; \
\
bool Z__OATPP_ENUM_META_INITIALIZER_##NAME = Z__OATPP_ENUM_META_##NAME::initializer(); \
\
}
// Chooser
#define OATPP_ENUM_MACRO_0(NAME, ORDINAL_TYPE) \
OATPP_ENUM_0(NAME, ORDINAL_TYPE)
#define OATPP_ENUM_MACRO_1(NAME, ORDINAL_TYPE, ...) \
OATPP_ENUM_1(NAME, ORDINAL_TYPE, __VA_ARGS__)
/**
* 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 ENUM(NAME, ...) \
OATPP_MACRO_EXPAND(OATPP_MACRO_MACRO_BINARY_SELECTOR(OATPP_ENUM_MACRO_, (__VA_ARGS__)) (NAME, __VA_ARGS__))

View File

@ -0,0 +1,73 @@
/***************************************************************************
*
* Project _____ __ ____ _ _
* ( _ ) /__\ (_ _)_| |_ _| |_
* )(_)( /(__)\ )( (_ _)(_ _)
* (_____)(__)(__)(__) |_| |_|
*
*
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
* Benedikt-Alexander Mokroß <bam@icognize.de>
*
* 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.
*
***************************************************************************/
#undef OATPP_MACRO_DTO_ENUM_PARAM_MACRO
#undef OATPP_MACRO_DTO_ENUM_PARAM_NAME
#undef OATPP_MACRO_DTO_ENUM_PARAM_NAME_STR
#undef OATPP_MACRO_DTO_ENUM_PARAM_VALUE
#undef OATPP_MACRO_DTO_ENUM_PARAM_VALUE_STR
#undef OATPP_MACRO_DTO_ENUM_PARAM
#undef VALUE
//////////////////////////////////////////////////////////////////////////
#undef OATPP_MACRO_DTO_ENUM_MACRO_SELECTOR
//////////////////////////////////////////////////////////////////////////
// VALUE MACRO
#undef OATPP_MACRO_DTO_ENUM_VALUE_1
#undef OATPP_MACRO_DTO_ENUM_VALUE_2
#undef OATPP_MACRO_DTO_ENUM_VALUE_3
#undef OATPP_MACRO_DTO_ENUM_VALUE
// FOR EACH
#undef OATPP_MACRO_DTO_ENUM_PARAM_DECL_FIRST
#undef OATPP_MACRO_DTO_ENUM_PARAM_DECL_REST
#undef OATPP_MACRO_DTO_ENUM_PARAM_PUT
// ENUM MACRO
#undef OATPP_ENUM_0
#undef OATPP_ENUM_1
// Chooser
#undef OATPP_ENUM_MACRO_0
#undef OATPP_ENUM_MACRO_1
#undef ENUM

View File

@ -29,6 +29,17 @@
namespace oatpp {
/**
* ObjectWrapper over the void*.
*/
typedef oatpp::data::mapping::type::Void Void;
/**
* `Any` - container for mapping-enabled types.
* &id:oatpp::data::mapping::type::Any;
*/
typedef oatpp::data::mapping::type::Any Any;
/**
* Mapping-Enabled String type. &id:oatpp::data::mapping::type::String; <br>
* For `oatpp::String` methods see &id:oatpp::base::StrBuffer;
@ -95,17 +106,66 @@ namespace oatpp {
*/
typedef oatpp::data::mapping::type::Object Object;
/*
* Mapping-Enabled Enum. &id:oatpp::data::mapping::type::Enum;
*/
template <class T>
using Enum = oatpp::data::mapping::type::Enum<T>;
/*
* Mapping-Enabled List. &id:oatpp::data::mapping::type::Vector;
*/
template <class T>
using Vector = oatpp::data::mapping::type::Vector<T>;
/**
* Abstract Vector.
*/
typedef oatpp::data::mapping::type::AbstractVector AbstractVector;
/*
* Mapping-Enabled List. &id:oatpp::data::mapping::type::List;
*/
template <class T>
using List = oatpp::data::mapping::type::List<T>;
/**
* Abstract List.
*/
typedef oatpp::data::mapping::type::AbstractList AbstractList;
/*
* Mapping-Enables ListMap<String, Value>. &id:oatpp::data::mapping::type::ListMap;
* Mapping-Enabled UnorderedSet. &id:oatpp::data::mapping::type::UnorderedSet;
*/
template <class T>
using UnorderedSet = oatpp::data::mapping::type::UnorderedSet<T>;
/**
* Abstract UnorderedSet.
*/
typedef oatpp::data::mapping::type::AbstractUnorderedSet AbstractUnorderedSet;
/*
* Mapping-Enables PairList<String, Value>. &id:oatpp::data::mapping::type::PairList;
*/
template <class Value>
using Fields = oatpp::data::mapping::type::ListMap<String, Value>;
using Fields = oatpp::data::mapping::type::PairList<String, Value>;
/**
* Abstract Fields
*/
typedef data::mapping::type::PairListObjectWrapper<oatpp::String, oatpp::Void, data::mapping::type::__class::AbstractPairList> AbstractFields;
/*
* Mapping-Enables PairList<String, Value>. &id:oatpp::data::mapping::type::UnorderedFields;
*/
template <class Value>
using UnorderedFields = oatpp::data::mapping::type::UnorderedMap<String, Value>;
/**
* Abstract UnorderedFields
*/
typedef data::mapping::type::UnorderedMapObjectWrapper<oatpp::String, oatpp::Void, data::mapping::type::__class::AbstractUnorderedMap> AbstractUnorderedFields;
}

View File

@ -36,7 +36,7 @@
#include <stdexcept>
#include <stdlib.h>
#define OATPP_VERSION "1.0.0"
#define OATPP_VERSION "1.1.0"
typedef unsigned char v_char8;
typedef v_char8 *p_char8;
@ -75,9 +75,11 @@ typedef v_int64 v_counter;
* Use this type to define a size for the buffer.
*/
typedef intptr_t v_buff_size;
typedef v_buff_size* p_buff_size;
typedef uintptr_t v_buff_usize;
typedef v_buff_usize* p_buff_usize;
namespace oatpp { namespace base {
/**

View File

@ -172,6 +172,9 @@ bool StrBuffer::equals(const void* data, v_buff_size size) const {
}
bool StrBuffer::equals(const char* data) const {
if(data == nullptr) {
return m_data == nullptr;
}
if(m_size == (v_buff_size) std::strlen(data)) {
return equals(m_data, data, m_size);
}
@ -179,7 +182,7 @@ bool StrBuffer::equals(const char* data) const {
}
bool StrBuffer::equals(StrBuffer* other) const {
return equals((StrBuffer*) this, other);
return equals((StrBuffer*)this, other);
}
bool StrBuffer::startsWith(const void* data, v_buff_size size) const {
@ -190,6 +193,7 @@ bool StrBuffer::startsWith(const void* data, v_buff_size size) const {
}
bool StrBuffer::startsWith(const char* data) const {
if(data == nullptr) return false;
v_buff_size length = std::strlen(data);
if(m_size >= length) {
return equals(m_data, data, length);
@ -198,6 +202,7 @@ bool StrBuffer::startsWith(const char* data) const {
}
bool StrBuffer::startsWith(StrBuffer* data) const {
if(data == nullptr) return false;
if(m_size >= data->m_size) {
return equals(m_data, data, data->m_size);
}
@ -222,21 +227,23 @@ v_buff_size StrBuffer::compare(StrBuffer* str1, StrBuffer* str2) {
}
bool StrBuffer::equals(const void* data1, const void* data2, v_buff_size size) {
return (data1 == data2) || (std::memcmp(data1, data2, size) == 0);
if(data1 == data2) return true;
if(data1 == nullptr || data2 == nullptr) return false;
return std::memcmp(data1, data2, size) == 0;
}
bool StrBuffer::equals(const char* data1, const char* data2) {
if(data1 == data2) return true;
if(data1 == nullptr && data2 == nullptr) return false;
if(data1 == nullptr || data2 == nullptr) return false;
const auto size = std::strlen(data1);
return (size == std::strlen(data2) && std::memcmp(data1, data2, size) == 0);
}
bool StrBuffer::equals(StrBuffer* str1, StrBuffer* str2) {
return (str1 == str2) ||
(str1 != nullptr && str2 != nullptr && str1->m_size == str2->m_size &&
(str1->m_data == str2->m_data || std::memcmp(str1->m_data, str2->m_data, str1->m_size) == 0)
);
if(str1 == str2) return true;
if(str1 == nullptr || str2 == nullptr) return false;
if(str1->m_size != str2->m_size) return false;
return str1->m_data == str2->m_data || std::memcmp(str1->m_data, str2->m_data, str1->m_size) == 0;
}
bool StrBuffer::equalsCI(const void* data1, const void* data2, v_buff_size size) {
@ -254,16 +261,16 @@ bool StrBuffer::equalsCI(const void* data1, const void* data2, v_buff_size size)
bool StrBuffer::equalsCI(const char* data1, const char* data2) {
if(data1 == data2) return true;
if(data1 == nullptr && data2 == nullptr) return false;
if(data1 == nullptr || data2 == nullptr) return false;
const auto size = std::strlen(data1);
return (size == std::strlen(data2) && equalsCI(data1, data2, size) == 0);
}
bool StrBuffer::equalsCI(StrBuffer* str1, StrBuffer* str2) {
return (str1 == str2) ||
(str1 != nullptr && str2 != nullptr && str1->m_size == str2->m_size &&
(str1->m_data == str2->m_data || equalsCI(str1->m_data, str2->m_data, str1->m_size))
);
if(str1 == str2) return true;
if(str1 == nullptr || str2 == nullptr) return false;
if(str1->m_size != str2->m_size) return false;
return (str1->m_data == str2->m_data || equalsCI(str1->m_data, str2->m_data, str1->m_size));
}
bool StrBuffer::equalsCI_FAST(const void* data1, const void* data2, v_buff_size size) {
@ -277,16 +284,16 @@ bool StrBuffer::equalsCI_FAST(const void* data1, const void* data2, v_buff_size
bool StrBuffer::equalsCI_FAST(const char* data1, const char* data2) {
if(data1 == data2) return true;
if(data1 == nullptr && data2 == nullptr) return false;
if(data1 == nullptr || data2 == nullptr) return false;
const auto size = std::strlen(data1);
return (size == std::strlen(data2) && equalsCI_FAST(data1, data2, size) == 0);
}
bool StrBuffer::equalsCI_FAST(StrBuffer* str1, StrBuffer* str2) {
return (str1 == str2) ||
(str1 != nullptr && str2 != nullptr && str1->m_size == str2->m_size &&
(str1->m_data == str2->m_data || equalsCI_FAST(str1->m_data, str2->m_data, str1->m_size))
);
if(str1 == str2) return true;
if(str1 == nullptr || str2 == nullptr) return false;
if(str1->m_size != str2->m_size) return false;
return (str1->m_data == str2->m_data || equalsCI_FAST(str1->m_data, str2->m_data, str1->m_size));
}
bool StrBuffer::equalsCI_FAST(StrBuffer* str1, const char* str2) {

View File

@ -36,7 +36,7 @@ const ObjectMapper::Info& ObjectMapper::getInfo() const {
return m_info;
}
oatpp::String ObjectMapper::writeToString(const type::AbstractObjectWrapper& variant) const {
oatpp::String ObjectMapper::writeToString(const type::Void& variant) const {
stream::ChunkedBuffer stream;
write(&stream, variant);
return stream.toString();

View File

@ -25,7 +25,6 @@
#ifndef oatpp_data_mapping_ObjectMapper_hpp
#define oatpp_data_mapping_ObjectMapper_hpp
#include "type/Object.hpp"
#include "type/Object.hpp"
#include "type/Type.hpp"
@ -83,24 +82,22 @@ public:
* @param stream - &id:oatpp::data::stream::ConsistentOutputStream; to serialize object to.
* @param variant - Object to serialize.
*/
virtual void write(data::stream::ConsistentOutputStream* stream,
const type::AbstractObjectWrapper& variant) const = 0;
virtual void write(data::stream::ConsistentOutputStream* stream, const type::Void& 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;.
* @return - deserialized object wrapped in &id:oatpp::Void;.
*/
virtual mapping::type::AbstractObjectWrapper read(oatpp::parser::Caret& caret,
const mapping::type::Type* const type) const = 0;
virtual mapping::type::Void 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;
oatpp::String writeToString(const type::Void& variant) const;
/**
* Deserialize object.
@ -111,9 +108,9 @@ public:
* @throws - depends on implementation.
*/
template<class Class>
typename Class::ObjectWrapper readFromCaret(oatpp::parser::Caret& caret) const {
auto type = Class::ObjectWrapper::Class::getType();
return oatpp::data::mapping::type::static_wrapper_cast<typename Class::ObjectWrapper::ObjectType>(read(caret, type));
typename Class::__Wrapper readFromCaret(oatpp::parser::Caret& caret) const {
auto type = Class::__Wrapper::Class::getType();
return read(caret, type).template staticCast<typename Class::__Wrapper>();
}
/**
@ -125,10 +122,10 @@ public:
* @throws - depends on implementation.
*/
template<class Class>
typename Class::ObjectWrapper readFromString(const oatpp::String& str) const {
auto type = Class::ObjectWrapper::Class::getType();
typename Class::__Wrapper readFromString(const oatpp::String& str) const {
auto type = Class::__Wrapper::Class::getType();
oatpp::parser::Caret caret(str);
auto result = oatpp::data::mapping::type::static_wrapper_cast<typename Class::ObjectWrapper::ObjectType>(read(caret, type));
auto result = read(caret, type).template staticCast<typename Class::__Wrapper>();
if(!result) {
throw oatpp::parser::ParsingError(caret.getErrorMessage(), caret.getErrorCode(), caret.getPosition());
}

View File

@ -0,0 +1,95 @@
/***************************************************************************
*
* 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 "Any.hpp"
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
const ClassId Any::CLASS_ID("Any");
}
Any::Any()
: ObjectWrapper(__class::Any::getType())
{}
Any::Any(std::nullptr_t) : Any() {}
Any::Any(const std::shared_ptr<base::Countable>& ptr, const Type* const type)
: ObjectWrapper(std::make_shared<AnyHandle>(ptr, type), __class::Any::getType())
{}
Any::Any(const Any& other)
: ObjectWrapper(std::make_shared<AnyHandle>(other.m_ptr->ptr, other.m_ptr->type), __class::Any::getType())
{}
Any::Any(Any&& other)
: ObjectWrapper(std::move(other.m_ptr), __class::Any::getType())
{}
const Type* Any::getStoredType() const {
if(m_ptr) {
return m_ptr->type;
}
return nullptr;
}
Any& Any::operator=(std::nullptr_t) {
m_ptr.reset();
return *this;
}
Any& Any::operator=(const Any& other) {
if(other) {
m_ptr = std::make_shared<AnyHandle>(other.m_ptr->ptr, other.m_ptr->type);
} else {
m_ptr.reset();
}
return *this;
}
Any& Any::operator=(Any&& other) {
m_ptr = std::move(other.m_ptr);
return *this;
}
bool Any::operator == (std::nullptr_t) const {
return m_ptr == nullptr || m_ptr->ptr == nullptr;
}
bool Any::operator != (std::nullptr_t) const {
return !operator == (nullptr);
}
bool Any::operator == (const Any& other) const {
if(!m_ptr && !other.m_ptr) return true;
if(!m_ptr || !other.m_ptr) return false;
return m_ptr->ptr.get() == other.m_ptr->ptr.get();
}
bool Any::operator != (const Any& other) const {
return !operator == (other);
}
}}}}

View File

@ -0,0 +1,129 @@
/***************************************************************************
*
* 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 oatpp_data_mapping_type_Any_hpp
#define oatpp_data_mapping_type_Any_hpp
#include "./Type.hpp"
#include "oatpp/core/collection/LinkedList.hpp"
#include "oatpp/core/base/memory/ObjectPool.hpp"
#include "oatpp/core/base/Countable.hpp"
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
class Any {
public:
static const ClassId CLASS_ID;
static Type *getType() {
static Type type(CLASS_ID, nullptr);
return &type;
}
};
}
class AnyHandle : public base::Countable {
public:
AnyHandle(const std::shared_ptr<void>& objPtr, const Type* const objType)
: ptr(objPtr)
, type(objType)
{}
std::shared_ptr<void> ptr;
const Type* const type;
};
class Any : public ObjectWrapper<AnyHandle, __class::Any>{
public:
typedef Any __Wrapper;
public:
Any();
Any(std::nullptr_t);
Any(const Any& other);
Any(Any&& other);
Any(const std::shared_ptr<base::Countable>& ptr, const Type* const type);
template<class T, class C>
Any(const ObjectWrapper<T, C>& polymorph)
: ObjectWrapper(std::make_shared<AnyHandle>(polymorph.getPtr(), polymorph.valueType), __class::Any::getType())
{}
template<class T, class C>
void store(const ObjectWrapper<T, C>& polymorph) {
m_ptr = std::make_shared<AnyHandle>(polymorph.getPtr(), polymorph.valueType);
}
const Type* getStoredType() const;
template<class WrapperType>
typename WrapperType::__Wrapper retrieve() const {
if(m_ptr) {
if(m_ptr->type != WrapperType::__Wrapper::Class::getType()) {
throw std::runtime_error("[oatpp::data::mapping::type::Any::retrieve()]: Error. The value type doesn't match.");
}
return typename WrapperType::__Wrapper(std::static_pointer_cast<typename WrapperType::__Wrapper::ObjectType>(m_ptr->ptr), m_ptr->type);
}
return nullptr;
}
Any& operator=(std::nullptr_t);
Any& operator=(const Any& other);
Any& operator=(Any&& other);
template<class T, class C>
Any& operator=(const ObjectWrapper<T, C>& polymorph) {
m_ptr = std::make_shared<AnyHandle>(polymorph.getPtr(), polymorph.valueType);
return *this;
}
bool operator == (std::nullptr_t) const;
bool operator != (std::nullptr_t) const;
bool operator == (const Any& other) const;
bool operator != (const Any& other) const;
};
}}}}
#endif //oatpp_data_mapping_type_Any_hpp

View File

@ -0,0 +1,33 @@
/***************************************************************************
*
* 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 "Enum.hpp"
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
const ClassId AbstractEnum::CLASS_ID("Enum");
}
}}}}

View File

@ -0,0 +1,525 @@
/***************************************************************************
*
* 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 oatpp_data_mapping_type_Enum_hpp
#define oatpp_data_mapping_type_Enum_hpp
#include "./Primitive.hpp"
#include "oatpp/core/data/share/MemoryLabel.hpp"
#include <type_traits>
#include <unordered_map>
#include <vector>
namespace oatpp { namespace data { namespace mapping { namespace type {
/**
* Errors of enum interpretation.
*/
enum class EnumInterpreterError : v_int32 {
/**
* The interpretation was successful.
*/
OK = 0,
/**
* Wrong `Interpreter` is used to interpret the variable. <br>
* This may also occur if for example: <br>
* `oatpp::Enum<T>` is passed to interpreter of `oatpp::Enum<T>::NotNull`.
*/
TYPE_MISMATCH_ENUM = 1,
/**
* Wrong &id:oatpp::data::mapping::type::Primitive; is passed to interpreter.
*/
TYPE_MISMATCH_ENUM_VALUE = 2,
/**
* Interpreter constraint is violated. <br>
* The constraint was set to `NotNull` but interpretation to/from `nullptr` is requested.
*/
CONSTRAINT_NOT_NULL = 3,
/**
* Enum entry not found.
*/
ENTRY_NOT_FOUND = 4,
};
namespace __class {
class AbstractEnum {
public:
static const ClassId CLASS_ID;
public:
class AbstractPolymorphicDispatcher {
public:
AbstractPolymorphicDispatcher(bool pNotNull)
: notNull(pNotNull)
{}
const bool notNull;
virtual type::Void toInterpretation(const type::Void& enumValue, EnumInterpreterError& error) const = 0;
virtual type::Void fromInterpretation(const type::Void& interValue, EnumInterpreterError& error) const = 0;
virtual type::Type* getInterpretationType() const = 0;
};
};
template<class T, class Interpreter>
class Enum;
}
template<typename T>
struct EnumValueInfo {
const T value;
const v_int32 index;
const data::share::StringKeyLabel name;
const data::share::StringKeyLabel description;
};
template<typename T>
struct EnumInfo {
public:
const char* nameQualifier = nullptr;
std::unordered_map<data::share::StringKeyLabel, EnumValueInfo<T>> byName;
std::unordered_map<v_uint64, EnumValueInfo<T>> byValue;
std::vector<EnumValueInfo<T>> byIndex;
};
template<class T, class Interpreter>
class EnumObjectWrapper; // FWD
template<class T>
class EnumMeta {
template<class Type, class Interpreter>
friend class __class::Enum;
template<class Type, class Interpreter>
friend class EnumObjectWrapper;
public:
typedef T EnumType;
protected:
static EnumInfo<T>* getInfo() {
static EnumInfo<T> info;
return &info;
}
};
template<class T, bool notnull>
class EnumInterpreterAsString {
public:
typedef String UnderlyingTypeObjectWrapper;
public:
template <bool N>
using InterpreterType = EnumInterpreterAsString<T, N>;
public:
constexpr static bool notNull = notnull;
public:
static Void toInterpretation(const Void& enumValue, EnumInterpreterError& error);
static Void fromInterpretation(const Void& interValue, EnumInterpreterError& error);
static Type* getInterpretationType();
};
template<class T, bool notnull>
class EnumInterpreterAsInteger {
private:
typedef typename std::underlying_type<T>::type EnumUnderlyingType;
public:
typedef typename ObjectWrapperByUnderlyingType<EnumUnderlyingType>::ObjectWrapper UnderlyingTypeObjectWrapper;
public:
template <bool N>
using InterpreterType = EnumInterpreterAsInteger<T, N>;
public:
constexpr static bool notNull = notnull;
public:
static Void toInterpretation(const Void& enumValue, EnumInterpreterError& error);
static Void fromInterpretation(const Void& interValue, EnumInterpreterError& error);
static Type* getInterpretationType();
};
template<class T, class EnumInterpreter>
class EnumObjectWrapper : public ObjectWrapper<T, __class::Enum<T, EnumInterpreter>>{
template<class Type, class Interpreter>
friend class EnumObjectWrapper;
public:
typedef EnumObjectWrapper __Wrapper;
public:
typedef typename std::underlying_type<T>::type UnderlyingEnumType;
typedef T Z__EnumType;
typedef __class::Enum<T, EnumInterpreter> EnumObjectClass;
typedef EnumInterpreter Interpreter;
public:
typedef EnumObjectWrapper<T, EnumInterpreterAsString<T, EnumInterpreter::notNull>> AsString;
typedef EnumObjectWrapper<T, EnumInterpreterAsInteger<T, EnumInterpreter::notNull>> AsNumber;
typedef EnumObjectWrapper<T, typename EnumInterpreter::template InterpreterType<true>> NotNull;
public:
EnumObjectWrapper(const std::shared_ptr<T>& ptr, const type::Type* const valueType)
: type::ObjectWrapper<T, EnumObjectClass>(ptr, valueType)
{}
EnumObjectWrapper() {}
EnumObjectWrapper(std::nullptr_t) {}
EnumObjectWrapper(const std::shared_ptr<T>& ptr)
: type::ObjectWrapper<T, EnumObjectClass>(ptr)
{}
EnumObjectWrapper(std::shared_ptr<T>&& ptr)
: type::ObjectWrapper<T, EnumObjectClass>(std::forward<std::shared_ptr<T>>(ptr))
{}
template<class OtherInter>
EnumObjectWrapper(const EnumObjectWrapper<T, OtherInter>& other)
: type::ObjectWrapper<T, EnumObjectClass>(other.getPtr())
{}
template<class OtherInter>
EnumObjectWrapper(EnumObjectWrapper<T, OtherInter>&& other)
: type::ObjectWrapper<T, EnumObjectClass>(std::move(other.getPtr()))
{}
inline EnumObjectWrapper& operator = (std::nullptr_t) {
this->m_ptr.reset();
return *this;
}
template<class OtherInter>
inline EnumObjectWrapper& operator = (const EnumObjectWrapper<T, OtherInter>& other) {
this->m_ptr = other.m_ptr;
return *this;
}
template<class OtherInter>
inline EnumObjectWrapper& operator = (EnumObjectWrapper<T, OtherInter>&& other) {
this->m_ptr = std::forward<std::shared_ptr<T>>(other.m_ptr);
return *this;
}
public:
EnumObjectWrapper(T value)
: type::ObjectWrapper<T, EnumObjectClass>(std::make_shared<T>(value))
{}
EnumObjectWrapper& operator = (T value) {
this->m_ptr = std::make_shared<T>(value);
return *this;
}
T operator*() const {
return this->m_ptr.operator*();
}
template<typename TP,
typename enabled = typename std::enable_if<std::is_same<TP, std::nullptr_t>::value, void>::type
>
inline bool operator == (TP){
return this->m_ptr.get() == nullptr;
}
template<typename TP,
typename enabled = typename std::enable_if<std::is_same<TP, std::nullptr_t>::value, void>::type
>
inline bool operator != (TP){
return this->m_ptr.get() != nullptr;
}
template<typename TP,
typename enabled = typename std::enable_if<std::is_same<TP, T>::value, void>::type
>
inline bool operator == (TP value) const {
if(!this->m_ptr) return false;
return *this->m_ptr == value;
}
template<typename TP,
typename enabled = typename std::enable_if<std::is_same<TP, T>::value, void>::type
>
inline bool operator != (TP value) const {
if(!this->m_ptr) return true;
return *this->m_ptr != value;
}
template<typename TP,
typename enabled = typename std::enable_if<std::is_same<typename TP::Z__EnumType, Z__EnumType>::value, void>::type
>
inline bool operator == (const TP &other) const {
if(this->m_ptr.get() == other.m_ptr.get()) return true;
if(!this->m_ptr || !other.m_ptr) return false;
return *this->m_ptr == *other.m_ptr;
}
template<typename TP,
typename enabled = typename std::enable_if<std::is_same<typename TP::Z__EnumType, Z__EnumType>::value, void>::type
>
inline bool operator != (const TP &other) const {
return !operator == (other);
}
template<typename TP,
typename enabled = typename std::enable_if<std::is_same<TP, T>::value, void>::type
>
inline operator TP() const {
return *this->m_ptr;
}
public:
static const EnumValueInfo<T>& getEntryByName(const String& name) {
auto it = EnumMeta<T>::getInfo()->byName.find(name);
if(it != EnumMeta<T>::getInfo()->byName.end()) {
return it->second;
}
throw std::runtime_error("[oatpp::data::mapping::type::Enum::getEntryByName()]: Error. Entry not found.");
}
static const EnumValueInfo<T>& getEntryByValue(T value) {
auto it = EnumMeta<T>::getInfo()->byValue.find(static_cast<v_uint64>(value));
if(it != EnumMeta<T>::getInfo()->byValue.end()) {
return it->second;
}
throw std::runtime_error("[oatpp::data::mapping::type::Enum::getEntryByValue()]: Error. Entry not found.");
}
static const EnumValueInfo<T>& getEntryByUnderlyingValue(UnderlyingEnumType value) {
auto it = EnumMeta<T>::getInfo()->byValue.find(static_cast<v_uint64>(value));
if(it != EnumMeta<T>::getInfo()->byValue.end()) {
return it->second;
}
throw std::runtime_error("[oatpp::data::mapping::type::Enum::getEntryByUnderlyingValue()]: Error. Entry not found.");
}
static const EnumValueInfo<T>& getEntryByIndex(v_int32 index) {
if(index >= 0 && index < EnumMeta<T>::getInfo()->byIndex.size()) {
return EnumMeta<T>::getInfo()->byIndex[index];
}
throw std::runtime_error("[oatpp::data::mapping::type::Enum::getEntryByIndex()]: Error. Entry not found.");
}
static const std::vector<EnumValueInfo<T>>& getEntries() {
return EnumMeta<T>::getInfo()->byIndex;
}
};
template <class T>
using Enum = EnumObjectWrapper<T, EnumInterpreterAsString<T, false>>;
template<class T, bool notnull>
Void EnumInterpreterAsString<T, notnull>::toInterpretation(const Void& enumValue, EnumInterpreterError& error) {
typedef EnumObjectWrapper<T, EnumInterpreterAsString<T, notnull>> EnumOW;
if(enumValue.valueType != EnumOW::Class::getType()) {
error = EnumInterpreterError::TYPE_MISMATCH_ENUM;
return Void(nullptr, String::Class::getType());
}
if(!enumValue) {
if(notnull) {
error = EnumInterpreterError::CONSTRAINT_NOT_NULL;
return Void(nullptr, String::Class::getType());
}
return Void(nullptr, String::Class::getType());
}
const auto& ow = enumValue.staticCast<EnumOW>();
const auto& entry = EnumOW::getEntryByValue(*ow);
return entry.name.toString();
}
template<class T, bool notnull>
Void EnumInterpreterAsString<T, notnull>::fromInterpretation(const Void& interValue, EnumInterpreterError& error) {
typedef EnumObjectWrapper<T, EnumInterpreterAsString<T, notnull>> EnumOW;
if(interValue.valueType != String::Class::getType()) {
error = EnumInterpreterError::TYPE_MISMATCH_ENUM_VALUE;
return Void(nullptr, EnumOW::Class::getType());
}
if(!interValue) {
if(notnull) {
error = EnumInterpreterError::CONSTRAINT_NOT_NULL;
return Void(nullptr, EnumOW::Class::getType());
}
return Void(nullptr, EnumOW::Class::getType());
}
try {
const auto &entry = EnumObjectWrapper<T, EnumInterpreterAsString<T, notnull>>::getEntryByName(
interValue.staticCast<String>()
);
return EnumOW(entry.value);
} catch (const std::runtime_error& e) { // TODO - add a specific error for this.
error = EnumInterpreterError::ENTRY_NOT_FOUND;
}
return Void(nullptr, EnumOW::Class::getType());
}
template<class T, bool notnull>
Type* EnumInterpreterAsString<T, notnull>::getInterpretationType() {
return String::Class::getType();
}
template<class T, bool notnull>
Void EnumInterpreterAsInteger<T, notnull>::toInterpretation(const Void& enumValue, EnumInterpreterError& error) {
typedef EnumObjectWrapper<T, EnumInterpreterAsInteger<T, notnull>> EnumOW;
typedef typename std::underlying_type<T>::type EnumUT;
typedef typename ObjectWrapperByUnderlyingType<EnumUT>::ObjectWrapper UTOW;
if(enumValue.valueType != EnumOW::Class::getType()) {
error = EnumInterpreterError::TYPE_MISMATCH_ENUM;
return Void(nullptr, UTOW::Class::getType());
}
if(!enumValue) {
if(notnull) {
error = EnumInterpreterError::CONSTRAINT_NOT_NULL;
return Void(nullptr, UTOW::Class::getType());
}
return Void(nullptr, UTOW::Class::getType());
}
const auto& ow = enumValue.staticCast<EnumOW>();
return UTOW(static_cast<EnumUT>(*ow));
}
template<class T, bool notnull>
Void EnumInterpreterAsInteger<T, notnull>::fromInterpretation(const Void& interValue, EnumInterpreterError& error) {
typedef EnumObjectWrapper<T, EnumInterpreterAsInteger<T, notnull>> EnumOW;
typedef typename std::underlying_type<T>::type EnumUT;
typedef typename ObjectWrapperByUnderlyingType<EnumUT>::ObjectWrapper OW;
if(interValue.valueType != OW::Class::getType()) {
error = EnumInterpreterError::TYPE_MISMATCH_ENUM_VALUE;
return Void(nullptr, EnumOW::Class::getType());
}
if(!interValue) {
if(notnull) {
error = EnumInterpreterError::CONSTRAINT_NOT_NULL;
return Void(nullptr, EnumOW::Class::getType());
}
return Void(nullptr, EnumOW::Class::getType());
}
try{
const auto& entry = EnumOW::getEntryByUnderlyingValue(
interValue.staticCast<OW>()
);
return EnumOW(entry.value);
} catch (const std::runtime_error& e) { // TODO - add a specific error for this.
error = EnumInterpreterError::ENTRY_NOT_FOUND;
}
return Void(nullptr, EnumOW::Class::getType());
}
template<class T, bool notnull>
Type* EnumInterpreterAsInteger<T, notnull>::getInterpretationType() {
typedef typename std::underlying_type<T>::type EnumUT;
return ObjectWrapperByUnderlyingType<EnumUT>::ObjectWrapper::Class::getType();
}
namespace __class {
template<class T, class Interpreter>
class Enum : public AbstractEnum {
private:
class PolymorphicDispatcher : public AbstractPolymorphicDispatcher {
public:
PolymorphicDispatcher()
: AbstractPolymorphicDispatcher(Interpreter::notNull)
{}
type::Void toInterpretation(const type::Void& enumValue, EnumInterpreterError& error) const override {
return Interpreter::toInterpretation(enumValue, error);
}
type::Void fromInterpretation(const type::Void& interValue, EnumInterpreterError& error) const override {
return Interpreter::fromInterpretation(interValue, error);
}
type::Type* getInterpretationType() const override {
return Interpreter::getInterpretationType();
}
};
private:
static type::Void creator() {
return type::Void(std::make_shared<T>(), getType());
}
static Type createType() {
Type type(__class::AbstractEnum::CLASS_ID, type::EnumMeta<T>::getInfo()->nameQualifier, &creator, nullptr, new PolymorphicDispatcher());
return type;
}
public:
static Type* getType() {
static Type type = createType();
return &type;
}
};
}
}}}}
namespace std {
template<class T, class I>
struct hash <oatpp::data::mapping::type::EnumObjectWrapper<T, I>> {
typedef oatpp::data::mapping::type::EnumObjectWrapper<T, I> argument_type;
typedef v_uint64 result_type;
result_type operator()(argument_type const &e) const noexcept {
if (e.get() == nullptr) return 0;
return static_cast<v_uint64>(*e);
}
};
}
#endif // oatpp_data_mapping_type_Enum_hpp

View File

@ -27,81 +27,109 @@
#include "./Type.hpp"
#include "oatpp/core/collection/LinkedList.hpp"
#include "oatpp/core/base/memory/ObjectPool.hpp"
#include "oatpp/core/base/Countable.hpp"
#include <list>
#include <initializer_list>
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
class AbstractList {
public:
static const ClassId CLASS_ID;
public:
class AbstractPolymorphicDispatcher {
public:
virtual void addPolymorphicItem(const type::Void& object, const type::Void& item) const = 0;
};
};
template<class T>
class List; // FWD
class List;
}
template<class T, class Class>
class ListTypeTemplate : public oatpp::collection::LinkedList<T> {
friend Class;
template<class T, class C>
class ListObjectWrapper : public type::ObjectWrapper<std::list<T>, C> {
public:
typedef oatpp::data::mapping::type::ObjectWrapper<ListTypeTemplate, Class> ObjectWrapper;
typedef std::list<T> TemplateObjectType;
typedef C TemplateObjectClass;
public:
OBJECT_POOL(DTO_LIST_POOL, ListTypeTemplate, 32)
SHARED_OBJECT_POOL(SHARED_DTO_LIST_POOL, ListTypeTemplate, 32)
protected:
static AbstractObjectWrapper Z__CLASS_OBJECT_CREATOR(){
return AbstractObjectWrapper(SHARED_DTO_LIST_POOL::allocateShared(), Z__CLASS_GET_TYPE());
}
static Type* Z__CLASS_GET_TYPE(){
static Type type(Class::CLASS_ID, nullptr, &Z__CLASS_OBJECT_CREATOR);
if(type.params.empty()){
type.params.push_back(T::Class::getType());
}
return &type;
}
public:
ListTypeTemplate()
OATPP_DEFINE_OBJECT_WRAPPER_DEFAULTS(ListObjectWrapper, TemplateObjectType, TemplateObjectClass)
ListObjectWrapper(std::initializer_list<T> ilist)
: type::ObjectWrapper<TemplateObjectType, TemplateObjectClass>(std::make_shared<TemplateObjectType>(ilist))
{}
public:
static ObjectWrapper createShared(){
return ObjectWrapper(SHARED_DTO_LIST_POOL::allocateShared());
static ListObjectWrapper createShared() {
return std::make_shared<TemplateObjectType>();
}
virtual void addPolymorphicItem(const AbstractObjectWrapper& item){
auto ptr = std::static_pointer_cast<typename T::ObjectType>(item.getPtr());
this->pushBack(T(ptr, item.valueType));
ListObjectWrapper& operator = (std::initializer_list<T> ilist) {
this->m_ptr = std::make_shared<TemplateObjectType>(ilist);
return *this;
}
T& operator[] (v_buff_usize index) const {
auto it = this->m_ptr->begin();
std::advance(it, index);
return *it;
}
TemplateObjectType& operator*() const {
return this->m_ptr.operator*();
}
};
template<class T>
using List = ListTypeTemplate<T, __class::List<T>>;
using List = ListObjectWrapper<typename T::__Wrapper, __class::List<typename T::__Wrapper>>;
typedef ListObjectWrapper<type::Void, __class::AbstractList> AbstractList;
namespace __class {
template<class T>
class List : public AbstractList {
public:
static Type* getType(){
static Type* type = static_cast<Type*>(oatpp::data::mapping::type::List<T>::Z__CLASS_GET_TYPE());
private:
class PolymorphicDispatcher : public AbstractPolymorphicDispatcher {
public:
void addPolymorphicItem(const type::Void& object, const type::Void& item) const override {
const auto& list = object.staticCast<type::List<T>>();
const auto& listItem = item.staticCast<T>();
list->push_back(listItem);
}
};
private:
static type::Void creator() {
return type::Void(std::make_shared<std::list<T>>(), getType());
}
static Type createType() {
Type type(__class::AbstractList::CLASS_ID, nullptr, &creator, nullptr, new PolymorphicDispatcher());
type.params.push_back(T::Class::getType());
return type;
}
public:
static Type* getType() {
static Type type = createType();
return &type;
}
};
}
}}}}
#endif /* oatpp_data_mapping_type_List_hpp */
#endif // oatpp_data_mapping_type_List_hpp

View File

@ -1,102 +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 oatpp_data_mapping_type_ListMap_hpp
#define oatpp_data_mapping_type_ListMap_hpp
#include "./Type.hpp"
#include "oatpp/core/collection/ListMap.hpp"
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
class AbstractListMap {
public:
static const ClassId CLASS_ID;
};
template<class Key, class Value>
class ListMap; // FWD
}
template<class Key, class Value>
class ListMap : public oatpp::collection::ListMap<Key, Value> {
friend __class::ListMap<Key, Value>;
public:
typedef oatpp::data::mapping::type::ObjectWrapper<ListMap, __class::ListMap<Key, Value>> ObjectWrapper;
public:
OBJECT_POOL(DTO_LISTMAP_POOL, ListMap, 32)
SHARED_OBJECT_POOL(SHARED_DTO_LISTMAP_POOL, ListMap, 32)
protected:
static AbstractObjectWrapper Z__CLASS_OBJECT_CREATOR(){
return AbstractObjectWrapper(SHARED_DTO_LISTMAP_POOL::allocateShared(), Z__CLASS_GET_TYPE());
}
static Type* Z__CLASS_GET_TYPE(){
static Type type(__class::AbstractListMap::CLASS_ID, nullptr, &Z__CLASS_OBJECT_CREATOR);
if(type.params.empty()){
type.params.push_back(Key::Class::getType());
type.params.push_back(Value::Class::getType());
}
return &type;
}
public:
ListMap()
{}
public:
static ObjectWrapper createShared(){
return ObjectWrapper(SHARED_DTO_LISTMAP_POOL::allocateShared());
}
virtual void putPolymorphicItem(const AbstractObjectWrapper& key, const AbstractObjectWrapper& value){
auto keyPtr = std::static_pointer_cast<typename Key::ObjectType>(key.getPtr());
auto valuePtr = std::static_pointer_cast<typename Value::ObjectType>(value.getPtr());
this->put(Key(keyPtr, key.valueType), Value(valuePtr, value.valueType));
}
};
namespace __class {
template<class Key, class Value>
class ListMap : public AbstractListMap{
public:
static Type* getType(){
static Type* type = static_cast<Type*>(oatpp::data::mapping::type::ListMap<Key, Value>::Z__CLASS_GET_TYPE());
return type;
}
};
}
}}}}
#endif /* oatpp_data_mapping_type_ListMap_hpp */

View File

@ -27,13 +27,20 @@
#include "./Type.hpp"
#include "./Any.hpp"
#include "./Primitive.hpp"
#include "./ListMap.hpp"
#include "./Enum.hpp"
#include "./UnorderedMap.hpp"
#include "./PairList.hpp"
#include "./List.hpp"
#include "./Vector.hpp"
#include "./UnorderedSet.hpp"
#include "oatpp/core/base/memory/ObjectPool.hpp"
#include "oatpp/core/base/Countable.hpp"
#include <type_traits>
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
@ -52,14 +59,31 @@ namespace __class {
*/
template<class T>
class Object : public AbstractObject {
private:
static type::Void creator() {
return type::Void(std::make_shared<T>(), getType());
}
static type::Type::Properties* initProperties() {
T obj; // initializer;
T::Z__CLASS_EXTEND(T::Z__CLASS::Z__CLASS_GET_FIELDS_MAP(), T::Z__CLASS_EXTENDED::Z__CLASS_GET_FIELDS_MAP());
return T::Z__CLASS::Z__CLASS_GET_FIELDS_MAP();
}
static const Type::Properties* propertiesGetter() {
static type::Type::Properties* properties = initProperties();
return properties;
}
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());
static Type* getType() {
static Type* type = new Type(CLASS_ID, T::Z__CLASS_TYPE_NAME(), creator, propertiesGetter);
return type;
}
@ -72,7 +96,11 @@ namespace __class {
* 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 {
template<class T>
friend class __class::Object;
public:
typedef oatpp::data::mapping::type::Void Void;
typedef oatpp::data::mapping::type::Any Any;
typedef oatpp::data::mapping::type::String String;
typedef oatpp::data::mapping::type::Int8 Int8;
typedef oatpp::data::mapping::type::UInt8 UInt8;
@ -85,26 +113,118 @@ public:
typedef oatpp::data::mapping::type::Float32 Float32;
typedef oatpp::data::mapping::type::Float64 Float64;
typedef oatpp::data::mapping::type::Boolean Boolean;
template <class T>
using Vector = oatpp::data::mapping::type::Vector<T>;
template <class T>
using UnorderedSet = oatpp::data::mapping::type::UnorderedSet<T>;
template <class T>
using List = oatpp::data::mapping::type::List<T>;
template <class Value>
using Fields = oatpp::data::mapping::type::ListMap<String, Value>;
protected:
using Fields = oatpp::data::mapping::type::PairList<String, Value>;
template <class Value>
using UnorderedFields = oatpp::data::mapping::type::UnorderedMap<String, Value>;
private:
static Type::Properties* Z__CLASS_EXTEND(Type::Properties* properties, Type::Properties* extensionProperties) {
properties->pushFrontAll(extensionProperties);
return properties;
}
public:
static oatpp::data::mapping::type::Type::Properties* Z__CLASS_GET_FIELDS_MAP(){
static oatpp::data::mapping::type::Type::Properties map;
return &map;
}
public:
virtual v_uint64 defaultHashCode() const {
return (v_uint64) reinterpret_cast<v_buff_usize>(this);
}
virtual bool defaultEquals(const Object& other) const {
return this == &other;
}
v_uint64 hashCode() const {
return defaultHashCode();
}
bool operator==(const Object& other) const {
return defaultEquals(other);
}
};
template<class ObjT>
class DTOWrapper : public ObjectWrapper<ObjT, __class::Object<ObjT>> {
public:
typedef ObjT TemplateObjectType;
typedef __class::Object<ObjT> TemplateObjectClass;
public:
OATPP_DEFINE_OBJECT_WRAPPER_DEFAULTS(DTOWrapper, TemplateObjectType, TemplateObjectClass)
static DTOWrapper createShared() {
return std::make_shared<TemplateObjectType>();
}
template<typename T,
typename enabled = typename std::enable_if<std::is_same<T, std::nullptr_t>::value, void>::type
>
inline bool operator == (T){
return this->m_ptr.get() == nullptr;
}
template<typename T,
typename enabled = typename std::enable_if<std::is_same<T, std::nullptr_t>::value, void>::type
>
inline bool operator != (T){
return this->m_ptr.get() != nullptr;
}
template<typename T,
typename enabled = typename std::enable_if<std::is_same<T, DTOWrapper>::value, void>::type
>
inline bool operator == (const T &other) const {
if(this->m_ptr.get() == other.m_ptr.get()) return true;
if(!this->m_ptr || !other.m_ptr) return false;
return *this->m_ptr == *other.m_ptr;
}
template<typename T,
typename enabled = typename std::enable_if<std::is_same<T, DTOWrapper>::value, void>::type
>
inline bool operator != (const T &other) const {
return !operator == (other);
}
};
}}}}
namespace std {
template<class T>
struct hash<oatpp::data::mapping::type::DTOWrapper<T>> {
typedef oatpp::data::mapping::type::DTOWrapper<T> argument_type;
typedef v_uint64 result_type;
result_type operator()(argument_type const &ow) const noexcept {
if(ow) {
return ow->hashCode();
}
return 0;
}
};
}
#endif /* oatpp_data_type_Object_hpp */

View File

@ -22,12 +22,12 @@
*
***************************************************************************/
#include "ListMap.hpp"
#include "PairList.hpp"
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
const ClassId AbstractListMap::CLASS_ID("ListMap");
const ClassId AbstractPairList::CLASS_ID("PairList");
}
}}}}

View File

@ -0,0 +1,156 @@
/***************************************************************************
*
* 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 oatpp_data_mapping_type_PairList_hpp
#define oatpp_data_mapping_type_PairList_hpp
#include "./Type.hpp"
#include <list>
#include <initializer_list>
#include <utility>
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
class AbstractPairList {
public:
static const ClassId CLASS_ID;
public:
class AbstractPolymorphicDispatcher {
public:
virtual void addPolymorphicItem(const type::Void& object, const type::Void& key, const type::Void& value) const = 0;
};
};
template<class Key, class Value>
class PairList;
}
template<class Key, class Value, class C>
class PairListObjectWrapper : public type::ObjectWrapper<std::list<std::pair<Key, Value>>, C> {
public:
typedef std::list<std::pair<Key, Value>> TemplateObjectType;
typedef C TemplateObjectClass;
public:
OATPP_DEFINE_OBJECT_WRAPPER_DEFAULTS(PairListObjectWrapper, TemplateObjectType, TemplateObjectClass)
PairListObjectWrapper(std::initializer_list<std::pair<Key, Value>> ilist)
: type::ObjectWrapper<TemplateObjectType, TemplateObjectClass>(std::make_shared<TemplateObjectType>(ilist))
{}
static PairListObjectWrapper createShared() {
return std::make_shared<TemplateObjectType>();
}
PairListObjectWrapper& operator = (std::initializer_list<std::pair<Key, Value>> ilist) {
this->m_ptr = std::make_shared<TemplateObjectType>(ilist);
return *this;
}
std::pair<Key, Value>& operator[] (v_buff_usize index) const {
auto it = this->m_ptr->begin();
std::advance(it, index);
return *it;
}
Value& operator[] (const Key& key) const {
auto& list = *(this->m_ptr.get());
auto it = list.begin();
while(it != list.end()) {
if(it->first == key) {
return it->second;
}
it ++;
}
list.push_back({key, nullptr});
return list.back().second;
}
TemplateObjectType& operator*() const {
return this->m_ptr.operator*();
}
};
template<class Key, class Value>
using PairList = PairListObjectWrapper<
typename Key::__Wrapper,
typename Value::__Wrapper,
__class::PairList<
typename Key::__Wrapper,
typename Value::__Wrapper
>
>;
namespace __class {
template<class Key, class Value>
class PairList : public AbstractPairList {
private:
class PolymorphicDispatcher : public AbstractPolymorphicDispatcher {
public:
void addPolymorphicItem(const type::Void& object, const type::Void& key, const type::Void& value) const override {
const auto& map = object.staticCast<type::PairList<Key, Value>>();
const auto& k = key.staticCast<Key>();
const auto& v = value.staticCast<Value>();
map->push_back({k, v});
}
};
private:
static type::Void creator() {
return type::Void(std::make_shared<std::list<std::pair<Key, Value>>>(), getType());
}
static Type createType() {
Type type(__class::AbstractPairList::CLASS_ID, nullptr, &creator, nullptr, new PolymorphicDispatcher());
type.params.push_back(Key::Class::getType());
type.params.push_back(Value::Class::getType());
return type;
}
public:
static Type* getType() {
static Type type = createType();
return &type;
}
};
}
}}}}
#endif // oatpp_data_mapping_type_PairList_hpp

View File

@ -59,71 +59,97 @@ namespace __class {
/**
* Mapping-enables String is &id:type::ObjectWrapper; over &id:oatpp::base::StrBuffer;
*/
class String : public type::ObjectWrapper<oatpp::base::StrBuffer, __class::String> {
class String : public type::ObjectWrapper<base::StrBuffer, __class::String> {
public:
String(const std::shared_ptr<oatpp::base::StrBuffer>& ptr, const type::Type* const valueType);
typedef String __Wrapper;
public:
String(const std::shared_ptr<base::StrBuffer>& ptr, const type::Type* const valueType);
public:
String() {}
String(std::nullptr_t) {}
String(v_buff_size size)
: type::ObjectWrapper<oatpp::base::StrBuffer, __class::String>(oatpp::base::StrBuffer::createShared(size))
explicit String(v_buff_size size)
: type::ObjectWrapper<base::StrBuffer, __class::String>(base::StrBuffer::createShared(size))
{}
String(const char* data, v_buff_size size, bool copyAsOwnData = true)
: type::ObjectWrapper<oatpp::base::StrBuffer, __class::String>(oatpp::base::StrBuffer::createShared(data, size, copyAsOwnData))
: type::ObjectWrapper<base::StrBuffer, __class::String>(base::StrBuffer::createShared(data, size, copyAsOwnData))
{}
String(const char* data1, v_buff_size size1, const char* data2, v_buff_size size2)
: type::ObjectWrapper<oatpp::base::StrBuffer, __class::String>(oatpp::base::StrBuffer::createSharedConcatenated(data1, size1, data2, size2))
: type::ObjectWrapper<base::StrBuffer, __class::String>(base::StrBuffer::createSharedConcatenated(data1, size1, data2, size2))
{}
String(const char* data, bool copyAsOwnData = true)
: type::ObjectWrapper<oatpp::base::StrBuffer, __class::String>(oatpp::base::StrBuffer::createFromCString(data, copyAsOwnData))
: type::ObjectWrapper<base::StrBuffer, __class::String>(base::StrBuffer::createFromCString(data, copyAsOwnData))
{}
String(const std::shared_ptr<oatpp::base::StrBuffer>& ptr)
: type::ObjectWrapper<oatpp::base::StrBuffer, __class::String>(ptr)
String(const std::shared_ptr<base::StrBuffer>& ptr)
: type::ObjectWrapper<base::StrBuffer, __class::String>(ptr)
{}
String(std::shared_ptr<oatpp::base::StrBuffer>&& ptr)
: type::ObjectWrapper<oatpp::base::StrBuffer, __class::String>(std::forward<std::shared_ptr<oatpp::base::StrBuffer>>(ptr))
String(std::shared_ptr<base::StrBuffer>&& ptr)
: type::ObjectWrapper<base::StrBuffer, __class::String>(std::forward<std::shared_ptr<base::StrBuffer>>(ptr))
{}
String(const String& other)
: type::ObjectWrapper<oatpp::base::StrBuffer, __class::String>(other)
: type::ObjectWrapper<base::StrBuffer, __class::String>(other)
{}
String(String&& other)
: type::ObjectWrapper<oatpp::base::StrBuffer, __class::String>(std::forward<String>(other))
: type::ObjectWrapper<base::StrBuffer, __class::String>(std::forward<String>(other))
{}
String& operator = (const char* str) {
m_ptr = oatpp::base::StrBuffer::createFromCString(str);
inline String& operator = (std::nullptr_t) {
m_ptr.reset();
return *this;
}
String& operator = (const String& other){
inline String& operator = (const char* str) {
m_ptr = base::StrBuffer::createFromCString(str);
return *this;
}
inline String& operator = (const String& other){
m_ptr = other.m_ptr;
return *this;
}
String& operator = (String&& other){
m_ptr = std::forward<std::shared_ptr<oatpp::base::StrBuffer>>(other.m_ptr);
inline String& operator = (String&& other){
m_ptr = std::forward<std::shared_ptr<base::StrBuffer>>(other.m_ptr);
return *this;
}
bool operator==(const String &other) const {
return m_ptr->equals(other.get());
inline bool operator == (std::nullptr_t) const {
return m_ptr.get() == nullptr;
}
bool operator!=(const String &other) const {
return !m_ptr->equals(other.get());
inline bool operator != (std::nullptr_t) const {
return m_ptr.get() != nullptr;
}
explicit operator bool() const {
inline bool operator == (const char* str) const {
if(!m_ptr) return str == nullptr;
if(str == nullptr) return false;
if(m_ptr->getSize() != std::strlen(str)) return false;
return base::StrBuffer::equals(m_ptr->getData(), str, m_ptr->getSize());
}
inline bool operator != (const char* str) const {
return !operator == (str);
}
inline bool operator == (const String &other) const {
return base::StrBuffer::equals(m_ptr.get(), other.m_ptr.get());
}
inline bool operator != (const String &other) const {
return !operator == (other);
}
inline explicit operator bool() const {
return m_ptr.operator bool();
}
@ -139,188 +165,245 @@ String operator + (const String& a, const String& b);
* @tparam Clazz - Class holding static class information.
*/
template<typename TValueType, class Clazz>
class Primitive : public oatpp::base::Countable {
class Primitive : public type::ObjectWrapper<TValueType, Clazz> {
public:
typedef TValueType ValueType;
public:
OBJECT_POOL(Primitive_Type_Pool, Primitive, 32)
SHARED_OBJECT_POOL(Shared_Primitive_Type_Pool, Primitive, 32)
typedef TValueType UnderlyingType;
public:
/**
* ObjectWrapper template for &l:Primitive;.
*/
class ObjectWrapper : public type::ObjectWrapper<Primitive, Clazz> {
public:
ObjectWrapper(const std::shared_ptr<Primitive>& ptr, const type::Type* const valueType)
: type::ObjectWrapper<Primitive, Clazz>(ptr)
{
if(Clazz::getType() != valueType){
throw std::runtime_error("Value type does not match");
}
}
public:
ObjectWrapper()
: type::ObjectWrapper<Primitive, Clazz>()
{}
OATPP_DEFINE_OBJECT_WRAPPER_DEFAULTS(Primitive, TValueType, Clazz)
ObjectWrapper(std::nullptr_t)
: type::ObjectWrapper<Primitive, Clazz>()
{}
ObjectWrapper(const std::shared_ptr<Primitive>& ptr)
: type::ObjectWrapper<Primitive, Clazz>(ptr)
{}
ObjectWrapper(std::shared_ptr<Primitive>&& ptr)
: type::ObjectWrapper<Primitive, Clazz>(std::move(ptr))
{}
ObjectWrapper(const ObjectWrapper& other)
: type::ObjectWrapper<Primitive, Clazz>(other)
{}
ObjectWrapper(ObjectWrapper&& other)
: type::ObjectWrapper<Primitive, Clazz>(std::move(other))
{}
ObjectWrapper(const ValueType& value)
: type::ObjectWrapper<Primitive, Clazz>(Primitive::createShared(value))
{}
ObjectWrapper& operator = (const ValueType& value){
if(!this->m_ptr){
this->m_ptr = Primitive::createShared(value);
} else {
this->m_ptr.get()->setValue(value);
}
return *this;
}
ObjectWrapper& operator = (const ObjectWrapper &other){
this->m_ptr = other.m_ptr;
return *this;
}
bool operator==(const ObjectWrapper &other) const {
return this->m_ptr->getValue() == other->getValue();
}
bool operator!=(const ObjectWrapper &other) const {
return this->m_ptr->getValue() != other->getValue();
}
inline operator ValueType() const {
return this->get()->getValue();
}
};
private:
ValueType m_value;
public:
/**
* Constructor.
* @param value - initial value.
*/
Primitive(const ValueType& value)
: m_value(value)
Primitive(TValueType value)
: type::ObjectWrapper<TValueType, Clazz>(std::make_shared<TValueType>(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);
Primitive& operator = (TValueType value) {
this->m_ptr = std::make_shared<TValueType>(value);
return *this;
}
/**
* 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));
TValueType operator*() const {
return this->m_ptr.operator*();
}
/**
* Set value.
* @param value.
*/
void setValue(const ValueType& value) {
m_value = value;
template<typename T,
typename enabled = typename std::enable_if<std::is_same<T, std::nullptr_t>::value, void>::type
>
inline bool operator == (T){
return this->m_ptr.get() == nullptr;
}
/**
* Get value.
* @return - value.
*/
ValueType getValue() {
return m_value;
template<typename T,
typename enabled = typename std::enable_if<std::is_same<T, std::nullptr_t>::value, void>::type
>
inline bool operator != (T){
return this->m_ptr.get() != nullptr;
}
template<typename T,
typename enabled = typename std::enable_if<std::is_same<T, TValueType>::value, void>::type
>
inline bool operator == (T value) const {
if(!this->m_ptr) return false;
return *this->m_ptr == value;
}
template<typename T,
typename enabled = typename std::enable_if<std::is_same<T, TValueType>::value, void>::type
>
inline bool operator != (T value) const {
if(!this->m_ptr) return true;
return *this->m_ptr != value;
}
template<typename T,
typename enabled = typename std::enable_if<std::is_same<T, Primitive>::value, void>::type
>
inline bool operator == (const T &other) const {
if(this->m_ptr.get() == other.m_ptr.get()) return true;
if(!this->m_ptr || !other.m_ptr) return false;
return *this->m_ptr == *other.m_ptr;
}
template<typename T,
typename enabled = typename std::enable_if<std::is_same<T, Primitive>::value, void>::type
>
inline bool operator != (const T &other) const {
return !operator == (other);
}
inline operator TValueType() const {
return *this->m_ptr;
}
};
/**
* Int8 is an ObjectWrapper over &l:Primitive; and __class::Int8.
* ObjectWrapper for Boolean.
*/
typedef Primitive<v_int8, __class::Int8>::ObjectWrapper Int8;
class Boolean : public type::ObjectWrapper<bool, __class::Boolean> {
public:
typedef bool UnderlyingType;
public:
OATPP_DEFINE_OBJECT_WRAPPER_DEFAULTS(Boolean, bool, __class::Boolean)
Boolean(bool value)
: type::ObjectWrapper<bool, __class::Boolean>(std::make_shared<bool>(value))
{}
Boolean& operator = (bool value) {
this->m_ptr = std::make_shared<bool>(value);
return *this;
}
inline bool operator*() const {
return this->m_ptr.operator*();
}
template<typename T,
typename enabled = typename std::enable_if<std::is_same<T, std::nullptr_t>::value, void>::type
>
inline bool operator == (T){
return m_ptr.get() == nullptr;
}
template<typename T,
typename enabled = typename std::enable_if<std::is_same<T, std::nullptr_t>::value, void>::type
>
inline bool operator != (T){
return m_ptr.get() != nullptr;
}
template<typename T,
typename enabled = typename std::enable_if<std::is_same<T, bool>::value, void>::type
>
inline bool operator == (T value) const {
if(!this->m_ptr) return false;
return *this->m_ptr == value;
}
template<typename T,
typename enabled = typename std::enable_if<std::is_same<T, bool>::value, void>::type
>
inline bool operator != (T value) const {
if(!this->m_ptr) return true;
return *this->m_ptr != value;
}
inline bool operator == (const Boolean &other) const {
if(this->m_ptr.get() == other.m_ptr.get()) return true;
if(!this->m_ptr || !other.m_ptr) return false;
return *this->m_ptr == *other.m_ptr;
}
inline bool operator != (const Boolean &other) const {
return !operator == (other);
}
inline operator bool() const {
if(this->m_ptr) {
return *(this->m_ptr);
}
return false;
}
};
/**
* UInt8 is an ObjectWrapper over &l:Primitive; and __class::UInt8.
* Int8 is an ObjectWrapper over `v_int8` and __class::Int8.
*/
typedef Primitive<v_uint8, __class::UInt8>::ObjectWrapper UInt8;
typedef Primitive<v_int8, __class::Int8> Int8;
/**
* Int16 is an ObjectWrapper over &l:Primitive; and __class::Int16.
* UInt8 is an ObjectWrapper over `v_uint8` and __class::UInt8.
*/
typedef Primitive<v_int16, __class::Int16>::ObjectWrapper Int16;
typedef Primitive<v_uint8, __class::UInt8> UInt8;
/**
* UInt16 is an ObjectWrapper over &l:Primitive; and __class::UInt16.
* Int16 is an ObjectWrapper over `v_int16` and __class::Int16.
*/
typedef Primitive<v_uint16, __class::UInt16>::ObjectWrapper UInt16;
typedef Primitive<v_int16, __class::Int16> Int16;
/**
* Int32 is an ObjectWrapper over &l:Primitive; and __class::Int32.
* UInt16 is an ObjectWrapper over `v_uint16` and __class::UInt16.
*/
typedef Primitive<v_int32, __class::Int32>::ObjectWrapper Int32;
typedef Primitive<v_uint16, __class::UInt16> UInt16;
/**
* UInt32 is an ObjectWrapper over &l:Primitive; and __class::UInt32.
* Int32 is an ObjectWrapper over `v_int32` and __class::Int32.
*/
typedef Primitive<v_uint32, __class::UInt32>::ObjectWrapper UInt32;
typedef Primitive<v_int32, __class::Int32> Int32;
/**
* Int64 is an ObjectWrapper over &l:Primitive; and __class::Int64.
* UInt32 is an ObjectWrapper over `v_uint32` and __class::UInt32.
*/
typedef Primitive<v_int64, __class::Int64>::ObjectWrapper Int64;
typedef Primitive<v_uint32, __class::UInt32> UInt32;
/**
* UInt64 is an ObjectWrapper over &l:Primitive; and __class::UInt64.
* Int64 is an ObjectWrapper over `v_int64` and __class::Int64.
*/
typedef Primitive<v_uint64, __class::UInt64>::ObjectWrapper UInt64;
typedef Primitive<v_int64, __class::Int64> Int64;
/**
* Float32 is an ObjectWrapper over &l:Primitive; and __class::Float32.
* UInt64 is an ObjectWrapper over `v_uint64` and __class::UInt64.
*/
typedef Primitive<v_float32, __class::Float32>::ObjectWrapper Float32;
typedef Primitive<v_uint64, __class::UInt64> UInt64;
/**
* Float64 is an ObjectWrapper over &l:Primitive; and __class::Float64.
* Float32 is an ObjectWrapper over `v_float32` and __class::Float32.
*/
typedef Primitive<v_float64, __class::Float64>::ObjectWrapper Float64;
typedef Primitive<v_float32, __class::Float32> Float32;
/**
* Boolean is an ObjectWrapper over &l:Primitive; and __class::Boolean.
* Float64 is an ObjectWrapper over `v_float64` and __class::Float64.
*/
typedef Primitive<bool, __class::Boolean>::ObjectWrapper Boolean;
typedef Primitive<v_float64, __class::Float64> Float64;
template<>
struct ObjectWrapperByUnderlyingType <v_int8> {
typedef Int8 ObjectWrapper;
};
template<>
struct ObjectWrapperByUnderlyingType <v_uint8> {
typedef UInt8 ObjectWrapper;
};
template<>
struct ObjectWrapperByUnderlyingType <v_int16> {
typedef Int16 ObjectWrapper;
};
template<>
struct ObjectWrapperByUnderlyingType <v_uint16> {
typedef UInt16 ObjectWrapper;
};
template<>
struct ObjectWrapperByUnderlyingType <v_int32> {
typedef Int32 ObjectWrapper;
};
template<>
struct ObjectWrapperByUnderlyingType <v_uint32> {
typedef UInt32 ObjectWrapper;
};
template<>
struct ObjectWrapperByUnderlyingType <v_int64> {
typedef Int64 ObjectWrapper;
};
template<>
struct ObjectWrapperByUnderlyingType <v_uint64> {
typedef UInt64 ObjectWrapper;
};
template<>
struct ObjectWrapperByUnderlyingType <bool> {
typedef Boolean ObjectWrapper;
};
namespace __class {
@ -466,9 +549,10 @@ namespace std {
struct hash<oatpp::data::mapping::type::String> {
typedef oatpp::data::mapping::type::String argument_type;
typedef v_uint32 result_type;
typedef v_uint64 result_type;
result_type operator()(argument_type const& s) const noexcept {
if(s.get() == nullptr) return 0;
p_char8 data = s->getData();
result_type result = 0;
@ -482,6 +566,150 @@ namespace std {
}
};
template<>
struct hash<oatpp::data::mapping::type::Boolean> {
typedef oatpp::data::mapping::type::Boolean argument_type;
typedef v_uint64 result_type;
result_type operator()(argument_type const& v) const noexcept {
if(v.get() == nullptr) return 2;
return result_type(*v);
}
};
template<>
struct hash<oatpp::data::mapping::type::Int8> {
typedef oatpp::data::mapping::type::Int8 argument_type;
typedef v_uint64 result_type;
result_type operator()(argument_type const& v) const noexcept {
if(v.get() == nullptr) return 0;
return (result_type) *v;
}
};
template<>
struct hash<oatpp::data::mapping::type::UInt8> {
typedef oatpp::data::mapping::type::UInt8 argument_type;
typedef v_uint64 result_type;
result_type operator()(argument_type const& v) const noexcept {
if(v.get() == nullptr) return 0;
return (result_type) *v;
}
};
template<>
struct hash<oatpp::data::mapping::type::Int16> {
typedef oatpp::data::mapping::type::Int16 argument_type;
typedef v_uint64 result_type;
result_type operator()(argument_type const& v) const noexcept {
if(v.get() == nullptr) return 0;
return (result_type) *v;
}
};
template<>
struct hash<oatpp::data::mapping::type::UInt16> {
typedef oatpp::data::mapping::type::UInt16 argument_type;
typedef v_uint64 result_type;
result_type operator()(argument_type const& v) const noexcept {
if(v.get() == nullptr) return 0;
return (result_type) *v;
}
};
template<>
struct hash<oatpp::data::mapping::type::Int32> {
typedef oatpp::data::mapping::type::Int32 argument_type;
typedef v_uint64 result_type;
result_type operator()(argument_type const& v) const noexcept {
if(v.get() == nullptr) return 0;
return (result_type) *v;
}
};
template<>
struct hash<oatpp::data::mapping::type::UInt32> {
typedef oatpp::data::mapping::type::UInt32 argument_type;
typedef v_uint64 result_type;
result_type operator()(argument_type const& v) const noexcept {
if(v.get() == nullptr) return 0;
return (result_type) *v;
}
};
template<>
struct hash<oatpp::data::mapping::type::Int64> {
typedef oatpp::data::mapping::type::Int64 argument_type;
typedef v_uint64 result_type;
result_type operator()(argument_type const& v) const noexcept {
if(v.get() == nullptr) return 0;
return (result_type) *v;
}
};
template<>
struct hash<oatpp::data::mapping::type::UInt64> {
typedef oatpp::data::mapping::type::UInt64 argument_type;
typedef v_uint64 result_type;
result_type operator()(argument_type const& v) const noexcept {
if(v.get() == nullptr) return 0;
return (result_type) *v;
}
};
template<>
struct hash<oatpp::data::mapping::type::Float32> {
typedef oatpp::data::mapping::type::Float32 argument_type;
typedef v_uint64 result_type;
result_type operator()(argument_type const& v) const noexcept {
if(v.get() == nullptr) return 0;
return *((v_uint32*) v.get());
}
};
template<>
struct hash<oatpp::data::mapping::type::Float64> {
typedef oatpp::data::mapping::type::Float64 argument_type;
typedef v_uint64 result_type;
result_type operator()(argument_type const& v) const noexcept {
if(v.get() == nullptr) return 0;
return *((result_type*) v.get());
}
};
}
#endif /* oatpp_base_Countable_PrimitiveDataTypes_hpp */

View File

@ -56,9 +56,10 @@ int ClassId::getClassCount() {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Type::Properties
void Type::Properties::pushBack(Property* property) {
Type::Property* Type::Properties::pushBack(Property* property) {
m_map.insert({property->name, property});
m_list.push_back(property);
return property;
}
void Type::Properties::pushFrontAll(Properties* properties) {
@ -69,51 +70,40 @@ void Type::Properties::pushFrontAll(Properties* properties) {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Type::Property
Type::Property::Property(Properties* properties, v_int64 pOffset, const char* pName, Type* pType)
Type::Property::Property(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);
void Type::Property::set(void* object, const Void& value) {
Void* property = (Void*)(((v_int64) object) + offset);
*property = value;
}
AbstractObjectWrapper Type::Property::get(void* object) {
AbstractObjectWrapper* property = (AbstractObjectWrapper*)(((v_int64) object) + offset);
Void Type::Property::get(void* object) {
Void* property = (Void*)(((v_int64) object) + offset);
return *property;
}
AbstractObjectWrapper& Type::Property::getAsRef(void* object) {
AbstractObjectWrapper* property = (AbstractObjectWrapper*)(((v_int64) object) + offset);
Void& Type::Property::getAsRef(void* object) {
Void* property = (Void*)(((v_int64) object) + offset);
return *property;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Type
Type::Type(const ClassId& pClassId, const char* pNameQualifier)
: classId(pClassId)
, nameQualifier(pNameQualifier)
, creator(nullptr)
, properties(nullptr)
{}
Type::Type(const ClassId& pClassId, const char* pNameQualifier, Creator pCreator)
Type::Type(const ClassId& pClassId,
const char* pNameQualifier,
Creator pCreator,
PropertiesGetter pPropertiesGetter,
void* pPolymorphicDispatcher)
: classId(pClassId)
, nameQualifier(pNameQualifier)
, creator(pCreator)
, properties(nullptr)
{}
Type::Type(const ClassId& pClassId, const char* pNameQualifier, Creator pCreator, Properties* pProperties)
: classId(pClassId)
, nameQualifier(pNameQualifier)
, creator(pCreator)
, properties(pProperties)
, propertiesGetter(pPropertiesGetter)
, polymorphicDispatcher(pPolymorphicDispatcher)
{}
}}}}

View File

@ -26,6 +26,7 @@
#define oatpp_data_type_Type_hpp
#include "oatpp/core/base/Countable.hpp"
#include "oatpp/core/base/Environment.hpp"
#include <list>
#include <unordered_map>
@ -88,80 +89,91 @@ namespace __class {
}
/**
* PolymorphicWrapper holds std::shared_ptr to object, object static type, plus object dynamic type information.
* @tparam T - Object Type
* ObjectWrapper holds std::shared_ptr to object, object static type, plus object dynamic type information.
* @tparam T - Object Type.
* @tparam Clazz - Static type info.
*/
template <class T>
class PolymorphicWrapper {
template <class T, class Clazz = __class::Void>
class ObjectWrapper {
protected:
std::shared_ptr<T> m_ptr;
public:
/**
* Convenience self-typedef.
*/
typedef ObjectWrapper __Wrapper;
/**
* 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;.
* Static object class information.
*/
typedef __class::Void Class;
typedef Clazz Class;
public:
PolymorphicWrapper(const std::shared_ptr<T>& ptr)
ObjectWrapper(const std::shared_ptr<T>& ptr)
: m_ptr(ptr)
, valueType(Class::getType())
{}
PolymorphicWrapper(const std::shared_ptr<T>& ptr, const Type* const type)
ObjectWrapper(const std::shared_ptr<T>& ptr, const Type* const type)
: m_ptr(ptr)
, valueType(type)
{}
PolymorphicWrapper(std::shared_ptr<T>&& ptr, const Type* const type)
ObjectWrapper(std::shared_ptr<T>&& ptr, const Type* const type)
: m_ptr(std::move(ptr))
, valueType(type)
{}
public:
PolymorphicWrapper()
ObjectWrapper()
: valueType(Class::getType())
{}
PolymorphicWrapper(std::nullptr_t)
ObjectWrapper(std::nullptr_t)
: valueType(Class::getType())
{}
PolymorphicWrapper(const Type* const type)
ObjectWrapper(const Type* const type)
: valueType(type)
{}
PolymorphicWrapper(const PolymorphicWrapper& other)
ObjectWrapper(const ObjectWrapper& other)
: m_ptr(other.m_ptr)
, valueType(other.valueType)
{}
PolymorphicWrapper(PolymorphicWrapper&& other)
ObjectWrapper(ObjectWrapper&& other)
: m_ptr(std::move(other.m_ptr))
, valueType(other.valueType)
{}
PolymorphicWrapper& operator=(const PolymorphicWrapper<T>& other){
inline ObjectWrapper& operator=(const ObjectWrapper& other){
m_ptr = other.m_ptr;
return *this;
}
PolymorphicWrapper& operator=(const PolymorphicWrapper<T>&& other){
inline ObjectWrapper& operator=(ObjectWrapper&& other){
m_ptr = std::move(other.m_ptr);
return *this;
}
inline operator PolymorphicWrapper<oatpp::base::Countable>() const {
return PolymorphicWrapper<oatpp::base::Countable>(this->m_ptr, valueType);
inline operator ObjectWrapper<void>() const {
return ObjectWrapper<void>(this->m_ptr, valueType);
}
T* operator->() const {
template<class Wrapper>
Wrapper staticCast() const {
return Wrapper(std::static_pointer_cast<typename Wrapper::ObjectType>(m_ptr), valueType);
}
inline T* operator->() const {
return m_ptr.operator->();
}
@ -176,16 +188,24 @@ public:
std::shared_ptr<T> getPtr() const {
return m_ptr;
}
inline bool operator == (std::nullptr_t){
return m_ptr.get() == nullptr;
}
inline bool operator != (std::nullptr_t){
return m_ptr.get() != nullptr;
}
inline bool operator == (const PolymorphicWrapper& other){
inline bool operator == (const ObjectWrapper& other){
return m_ptr.get() == other.m_ptr.get();
}
inline bool operator != (const PolymorphicWrapper& other){
inline bool operator != (const ObjectWrapper& other){
return m_ptr.get() != other.m_ptr.get();
}
explicit operator bool() const {
explicit inline operator bool() const {
return m_ptr.operator bool();
}
@ -196,90 +216,16 @@ public:
const Type* const valueType;
};
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)
: PolymorphicWrapper<T>(ptr, Class::getType())
{
if(Class::getType() != valueType){
throw std::runtime_error("Value type does not match");
}
}
public:
ObjectWrapper()
: PolymorphicWrapper<T>(Class::getType())
{}
ObjectWrapper(std::nullptr_t)
: PolymorphicWrapper<T>(Class::getType())
{}
ObjectWrapper(const std::shared_ptr<T>& ptr)
: PolymorphicWrapper<T>(ptr, Class::getType())
{}
ObjectWrapper(const PolymorphicWrapper<T>& other)
: PolymorphicWrapper<T>(other.getPtr(), Class::getType())
{}
ObjectWrapper(PolymorphicWrapper<T>&& other)
: PolymorphicWrapper<T>(std::move(other.getPtr()), Class::getType())
{}
ObjectWrapper& operator=(const PolymorphicWrapper<T>& other){
if(this->valueType != other.valueType){
OATPP_LOGE("ObjectWrapper", "Invalid class cast");
throw std::runtime_error("[oatpp::data::mapping::type::ObjectWrapper]: Invalid class cast");
}
PolymorphicWrapper<T>::operator = (other);
return *this;
}
ObjectWrapper& operator=(const PolymorphicWrapper<T>&& other){
if(this->valueType != other.valueType){
OATPP_LOGE("ObjectWrapper", "Invalid class cast");
throw std::runtime_error("[oatpp::data::mapping::type::ObjectWrapper]: Invalid class cast");
}
PolymorphicWrapper<T>::operator = (std::forward<PolymorphicWrapper<T>>(other));
return *this;
}
};
typedef ObjectWrapper<void, __class::Void> Void;
/**
* PolymorphicWrapper over &id:oatpp::base::Countable; object.
*/
typedef PolymorphicWrapper<oatpp::base::Countable> AbstractObjectWrapper;
template <typename T>
struct ObjectWrapperByUnderlyingType {};
/**
* Object type data.
*/
class Type {
public:
typedef AbstractObjectWrapper (*Creator)();
public:
class Property; // FWD
public:
@ -297,7 +243,7 @@ public:
* Add property to the end of the list.
* @param property
*/
void pushBack(Property* property);
Property* pushBack(Property* property);
/**
* Add all properties to the beginning of the list.
@ -329,18 +275,29 @@ public:
* Class to map object properties.
*/
class Property {
public:
/**
* Editional Info about Property.
*/
struct Info {
/**
* Description.
*/
std::string description = "";
};
private:
const v_int64 offset;
public:
/**
* 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(v_int64 pOffset, const char* pName, Type* pType);
/**
* Property name.
@ -352,54 +309,52 @@ public:
*/
const Type* const type;
/**
* Property additional info.
*/
Info info;
/**
* 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);
void set(void* object, const Void& value);
/**
* Get value of object field mapped by this property.
* @param object - object address.
* @return - value of the field.
*/
AbstractObjectWrapper get(void* object);
Void 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);
Void& getAsRef(void* object);
};
public:
typedef Void (*Creator)();
typedef const Properties* (*PropertiesGetter)();
public:
/**
* Constructor.
* @param pClassId - type class id.
* @param pNameQualifier - type name qualifier.
*/
Type(const ClassId& pClassId, const char* pNameQualifier);
/**
* Constructor.
* @param pClassId - type class id.
* @param pNameQualifier - type name qualifier.
* @param pCreator - function pointer of Creator - function to create instance of this type.
* @param pPropertiesGetter - function to get properties of the type.
* @param pPolymorphicDispatcher - dispatcher to correctly address methods of the type.
*/
Type(const ClassId& pClassId, const char* pNameQualifier, Creator pCreator);
/**
* Constructor.
* @param pClassId - type class id.
* @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 ClassId& pClassId, const char* pNameQualifier, Creator pCreator, Properties* pProperties);
Type(const ClassId& pClassId,
const char* pNameQualifier,
Creator pCreator = nullptr,
PropertiesGetter pPropertiesGetter = nullptr,
void* pPolymorphicDispatcher = nullptr);
/**
* type class id.
@ -422,12 +377,78 @@ public:
const Creator creator;
/**
* Pointer to type properties.
* PropertiesGetter - function to get properties of the type.
*/
const Properties* const properties;
const PropertiesGetter propertiesGetter;
/**
* PolymorphicDispatcher - is an object to forward polymorphic calls to a correct object of type `Type`.
*/
const void* const polymorphicDispatcher;
};
#define OATPP_DEFINE_OBJECT_WRAPPER_DEFAULTS(WRAPPER_NAME, OBJECT_TYPE, OBJECT_CLASS) \
public:\
typedef WRAPPER_NAME __Wrapper; \
public: \
WRAPPER_NAME(const std::shared_ptr<OBJECT_TYPE>& ptr, const type::Type* const valueType) \
: type::ObjectWrapper<OBJECT_TYPE, OBJECT_CLASS>(ptr, valueType) \
{} \
public: \
\
WRAPPER_NAME() {} \
\
WRAPPER_NAME(std::nullptr_t) {} \
\
WRAPPER_NAME(const std::shared_ptr<OBJECT_TYPE>& ptr) \
: type::ObjectWrapper<OBJECT_TYPE, OBJECT_CLASS>(ptr) \
{} \
\
WRAPPER_NAME(std::shared_ptr<OBJECT_TYPE>&& ptr) \
: type::ObjectWrapper<OBJECT_TYPE, OBJECT_CLASS>(std::forward<std::shared_ptr<OBJECT_TYPE>>(ptr)) \
{} \
\
WRAPPER_NAME(const WRAPPER_NAME& other) \
: type::ObjectWrapper<OBJECT_TYPE, OBJECT_CLASS>(other) \
{} \
\
WRAPPER_NAME(WRAPPER_NAME&& other) \
: type::ObjectWrapper<OBJECT_TYPE, OBJECT_CLASS>(std::forward<WRAPPER_NAME>(other)) \
{} \
\
inline WRAPPER_NAME& operator = (std::nullptr_t) { \
this->m_ptr.reset(); \
return *this; \
} \
\
inline WRAPPER_NAME& operator = (const WRAPPER_NAME& other) { \
this->m_ptr = other.m_ptr; \
return *this; \
} \
\
inline WRAPPER_NAME& operator = (WRAPPER_NAME&& other) { \
this->m_ptr = std::forward<std::shared_ptr<OBJECT_TYPE>>(other.m_ptr); \
return *this; \
} \
}}}}
namespace std {
template<>
struct hash<oatpp::data::mapping::type::Void> {
typedef oatpp::data::mapping::type::Void argument_type;
typedef v_uint64 result_type;
result_type operator()(argument_type const& v) const noexcept {
return (result_type) v.get();
}
};
}
#endif /* oatpp_data_type_Type_hpp */

View File

@ -0,0 +1,33 @@
/***************************************************************************
*
* 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 "UnorderedMap.hpp"
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
const ClassId AbstractUnorderedMap::CLASS_ID("UnorderedMap");
}
}}}}

View File

@ -0,0 +1,141 @@
/***************************************************************************
*
* 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 oatpp_data_mapping_type_UnorderedMap_hpp
#define oatpp_data_mapping_type_UnorderedMap_hpp
#include "./Type.hpp"
#include <unordered_map>
#include <initializer_list>
#include <utility>
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
class AbstractUnorderedMap {
public:
static const ClassId CLASS_ID;
public:
class AbstractPolymorphicDispatcher {
public:
virtual void addPolymorphicItem(const type::Void& object, const type::Void& key, const type::Void& value) const = 0;
};
};
template<class Key, class Value>
class UnorderedMap;
}
template<class Key, class Value, class C>
class UnorderedMapObjectWrapper : public type::ObjectWrapper<std::unordered_map<Key, Value>, C> {
public:
typedef std::unordered_map<Key, Value> TemplateObjectType;
typedef C TemplateObjectClass;
public:
OATPP_DEFINE_OBJECT_WRAPPER_DEFAULTS(UnorderedMapObjectWrapper, TemplateObjectType, TemplateObjectClass)
UnorderedMapObjectWrapper(std::initializer_list<std::pair<const Key, Value>> ilist)
: type::ObjectWrapper<TemplateObjectType, TemplateObjectClass>(std::make_shared<TemplateObjectType>(ilist))
{}
static UnorderedMapObjectWrapper createShared() {
return std::make_shared<TemplateObjectType>();
}
UnorderedMapObjectWrapper& operator = (std::initializer_list<std::pair<const Key, Value>> ilist) {
this->m_ptr = std::make_shared<TemplateObjectType>(ilist);
return *this;
}
Value& operator[] (const Key& key) const {
return this->m_ptr->operator [] (key);
}
TemplateObjectType& operator*() const {
return this->m_ptr.operator*();
}
};
template<class Key, class Value>
using UnorderedMap = UnorderedMapObjectWrapper<
typename Key::__Wrapper,
typename Value::__Wrapper,
__class::UnorderedMap<
typename Key::__Wrapper,
typename Value::__Wrapper
>
>;
namespace __class {
template<class Key, class Value>
class UnorderedMap : public AbstractUnorderedMap {
private:
class PolymorphicDispatcher : public AbstractPolymorphicDispatcher {
public:
void addPolymorphicItem(const type::Void& object, const type::Void& key, const type::Void& value) const override {
const auto& map = object.staticCast<type::UnorderedMap<Key, Value>>();
const auto& k = key.staticCast<Key>();
const auto& v = value.staticCast<Value>();
map[k] = v;
}
};
private:
static type::Void creator() {
return type::Void(std::make_shared<std::unordered_map<Key, Value>>(), getType());
}
static Type createType() {
Type type(__class::AbstractUnorderedMap::CLASS_ID, nullptr, &creator, nullptr, new PolymorphicDispatcher());
type.params.push_back(Key::Class::getType());
type.params.push_back(Value::Class::getType());
return type;
}
public:
static Type* getType() {
static Type type = createType();
return &type;
}
};
}
}}}}
#endif // oatpp_data_mapping_type_UnorderedMap_hpp

View File

@ -0,0 +1,33 @@
/***************************************************************************
*
* 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 "UnorderedSet.hpp"
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
const ClassId AbstractUnorderedSet::CLASS_ID("UnorderedSet");
}
}}}}

View File

@ -0,0 +1,137 @@
/***************************************************************************
*
* 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 oatpp_data_mapping_type_UnorderedSet_hpp
#define oatpp_data_mapping_type_UnorderedSet_hpp
#include "./Type.hpp"
#include <unordered_set>
#include <initializer_list>
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
class AbstractUnorderedSet {
public:
static const ClassId CLASS_ID;
public:
class AbstractPolymorphicDispatcher {
public:
virtual void addPolymorphicItem(const type::Void& object, const type::Void& item) const = 0;
};
};
template<class T>
class UnorderedSet;
}
template<class T, class C>
class UnorderedSetObjectWrapper : public type::ObjectWrapper<std::unordered_set<T>, C> {
public:
typedef std::unordered_set<T> TemplateObjectType;
typedef C TemplateObjectClass;
public:
OATPP_DEFINE_OBJECT_WRAPPER_DEFAULTS(UnorderedSetObjectWrapper, TemplateObjectType, TemplateObjectClass)
UnorderedSetObjectWrapper(std::initializer_list<T> ilist)
: type::ObjectWrapper<TemplateObjectType, TemplateObjectClass>(std::make_shared<TemplateObjectType>(ilist))
{}
static UnorderedSetObjectWrapper createShared() {
return std::make_shared<TemplateObjectType>();
}
UnorderedSetObjectWrapper& operator = (std::initializer_list<T> ilist) {
this->m_ptr = std::make_shared<TemplateObjectType>(ilist);
return *this;
}
bool operator[] (const T& key) const {
if(this->m_ptr) {
auto it = this->m_ptr->find(key);
return it != this->m_ptr->end();
}
return false;
}
TemplateObjectType& operator*() const {
return this->m_ptr.operator*();
}
};
template<class T>
using UnorderedSet = UnorderedSetObjectWrapper<typename T::__Wrapper, __class::UnorderedSet<typename T::__Wrapper>>;
typedef UnorderedSetObjectWrapper<type::Void, __class::AbstractUnorderedSet> AbstractUnorderedSet;
namespace __class {
template<class T>
class UnorderedSet : public AbstractUnorderedSet {
private:
class PolymorphicDispatcher : public AbstractPolymorphicDispatcher {
public:
void addPolymorphicItem(const type::Void& object, const type::Void& item) const override {
const auto& set = object.staticCast<type::UnorderedSet<T>>();
const auto& setItem = item.staticCast<T>();
set->insert(setItem);
}
};
private:
static type::Void creator() {
return type::Void(std::make_shared<std::unordered_set<T>>(), getType());
}
static Type createType() {
Type type(__class::AbstractUnorderedSet::CLASS_ID, nullptr, &creator, nullptr, new PolymorphicDispatcher());
type.params.push_back(T::Class::getType());
return type;
}
public:
static Type* getType() {
static Type type = createType();
return &type;
}
};
}
}}}}
#endif // oatpp_data_mapping_type_UnorderedSet_hpp

View File

@ -0,0 +1,33 @@
/***************************************************************************
*
* 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 "Vector.hpp"
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
const ClassId AbstractVector::CLASS_ID("Vector");
}
}}}}

View File

@ -0,0 +1,133 @@
/***************************************************************************
*
* 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 oatpp_data_mapping_type_Vector_hpp
#define oatpp_data_mapping_type_Vector_hpp
#include "./Type.hpp"
#include <vector>
#include <initializer_list>
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
class AbstractVector {
public:
static const ClassId CLASS_ID;
public:
class AbstractPolymorphicDispatcher {
public:
virtual void addPolymorphicItem(const type::Void& object, const type::Void& item) const = 0;
};
};
template<class T>
class Vector;
}
template<class T, class C>
class VectorObjectWrapper : public type::ObjectWrapper<std::vector<T>, C> {
public:
typedef std::vector<T> TemplateObjectType;
typedef C TemplateObjectClass;
public:
OATPP_DEFINE_OBJECT_WRAPPER_DEFAULTS(VectorObjectWrapper, TemplateObjectType, TemplateObjectClass)
VectorObjectWrapper(std::initializer_list<T> ilist)
: type::ObjectWrapper<TemplateObjectType, TemplateObjectClass>(std::make_shared<TemplateObjectType>(ilist))
{}
static VectorObjectWrapper createShared() {
return std::make_shared<TemplateObjectType>();
}
VectorObjectWrapper& operator = (std::initializer_list<T> ilist) {
this->m_ptr = std::make_shared<TemplateObjectType>(ilist);
return *this;
}
T& operator[] (v_buff_usize index) const {
return this->m_ptr->operator [] (index);
}
TemplateObjectType& operator*() const {
return this->m_ptr.operator*();
}
};
template<class T>
using Vector = VectorObjectWrapper<typename T::__Wrapper, __class::Vector<typename T::__Wrapper>>;
typedef VectorObjectWrapper<type::Void, __class::AbstractVector> AbstractVector;
namespace __class {
template<class T>
class Vector : public AbstractVector {
private:
class PolymorphicDispatcher : public AbstractPolymorphicDispatcher {
public:
void addPolymorphicItem(const type::Void& object, const type::Void& item) const override {
const auto& vector = object.staticCast<type::Vector<T>>();
const auto& vectorItem = item.staticCast<T>();
vector->push_back(vectorItem);
}
};
private:
static type::Void creator() {
return type::Void(std::make_shared<std::vector<T>>(), getType());
}
static Type createType() {
Type type(__class::AbstractVector::CLASS_ID, nullptr, &creator, nullptr, new PolymorphicDispatcher());
type.params.push_back(T::Class::getType());
return type;
}
public:
static Type* getType() {
static Type type = createType();
return &type;
}
};
}
}}}}
#endif // oatpp_data_mapping_type_Vector_hpp

View File

@ -39,6 +39,8 @@ namespace oatpp { namespace data { namespace share {
*/
template<class Key>
class LazyStringMap {
public:
typedef oatpp::data::mapping::type::String String;
private:
mutable concurrency::SpinLock m_lock;
mutable bool m_fullyInitialized;
@ -181,7 +183,7 @@ public:
* @param key
* @return
*/
oatpp::String get(const Key& key) const {
String get(const Key& key) const {
std::lock_guard<concurrency::SpinLock> lock(m_lock);

View File

@ -42,7 +42,7 @@ StringKeyLabel::StringKeyLabel(const char* constText)
: oatpp::data::share::MemoryLabel(nullptr, (p_char8)constText, std::strlen(constText))
{}
StringKeyLabel::StringKeyLabel(const oatpp::String& str)
StringKeyLabel::StringKeyLabel(const String& str)
: oatpp::data::share::MemoryLabel(str.getPtr(), str->getData(), str->getSize())
{}
@ -54,7 +54,7 @@ StringKeyLabelCI::StringKeyLabelCI(const char* constText)
: oatpp::data::share::MemoryLabel(nullptr, (p_char8)constText, std::strlen(constText))
{}
StringKeyLabelCI::StringKeyLabelCI(const oatpp::String& str)
StringKeyLabelCI::StringKeyLabelCI(const String& str)
: oatpp::data::share::MemoryLabel(str.getPtr(), str->getData(), str->getSize())
{}
@ -66,7 +66,7 @@ StringKeyLabelCI_FAST::StringKeyLabelCI_FAST(const char* constText)
: oatpp::data::share::MemoryLabel(nullptr, (p_char8)constText, std::strlen(constText))
{}
StringKeyLabelCI_FAST::StringKeyLabelCI_FAST(const oatpp::String& str)
StringKeyLabelCI_FAST::StringKeyLabelCI_FAST(const String& str)
: oatpp::data::share::MemoryLabel(str.getPtr(), str->getData(), str->getSize())
{}

View File

@ -26,7 +26,7 @@
#define oatpp_data_share_MemoryLabel_hpp
#include "oatpp/core/base/StrBuffer.hpp"
#include "oatpp/core/Types.hpp"
#include "oatpp/core/data/mapping/type/Primitive.hpp"
namespace oatpp { namespace data { namespace share {
@ -36,6 +36,8 @@ namespace oatpp { namespace data { namespace share {
* You may allocate separate buffer for data copy later once you need it.
*/
class MemoryLabel {
public:
typedef oatpp::data::mapping::type::String String;
protected:
mutable std::shared_ptr<base::StrBuffer> m_memoryHandle;
mutable p_char8 m_data;
@ -134,8 +136,8 @@ public:
* Create oatpp::String from memory label
* @return oatpp::String(data, size)
*/
oatpp::String toString() const {
return oatpp::String((const char*) m_data, m_size, true);
String toString() const {
return String((const char*) m_data, m_size, true);
}
/**
@ -146,7 +148,15 @@ public:
return std::string((const char*) m_data, m_size);
}
explicit operator bool() const {
inline bool operator==(std::nullptr_t) const {
return m_data == nullptr;
}
inline bool operator!=(std::nullptr_t) const {
return m_data != nullptr;
}
inline explicit operator bool() const {
return m_data != nullptr;
}
@ -164,13 +174,43 @@ public:
StringKeyLabel(const std::shared_ptr<base::StrBuffer>& memHandle, p_char8 data, v_buff_size size);
StringKeyLabel(const char* constText);
StringKeyLabel(const oatpp::String& str);
bool operator==(const StringKeyLabel &other) const {
StringKeyLabel(const String& str);
inline bool operator==(std::nullptr_t) const {
return m_data == nullptr;
}
inline bool operator!=(std::nullptr_t) const {
return m_data != nullptr;
}
inline bool operator==(const char* str) const {
if(m_data == nullptr) return str == nullptr;
if(str == nullptr) return false;
if(m_size != std::strlen(str)) return false;
return base::StrBuffer::equals(m_data, str, m_size);
}
inline bool operator!=(const char* str) const {
return !operator==(str);
}
inline bool operator==(const String& str) const {
if(m_data == nullptr) return str == nullptr;
if(str == nullptr) return false;
if(m_size != str->getSize()) return false;
return base::StrBuffer::equals(m_data, str->getData(), m_size);
}
inline bool operator!=(const String& str) const {
return !operator==(str);
}
inline bool operator==(const StringKeyLabel &other) const {
return m_size == other.m_size && base::StrBuffer::equals(m_data, other.m_data, m_size);
}
bool operator!=(const StringKeyLabel &other) const {
inline bool operator!=(const StringKeyLabel &other) const {
return !(m_size == other.m_size && base::StrBuffer::equals(m_data, other.m_data, m_size));
}
@ -188,16 +228,46 @@ public:
StringKeyLabelCI(const std::shared_ptr<base::StrBuffer>& memHandle, p_char8 data, v_buff_size size);
StringKeyLabelCI(const char* constText);
StringKeyLabelCI(const oatpp::String& str);
bool operator==(const StringKeyLabelCI &other) const {
StringKeyLabelCI(const String& str);
inline bool operator==(std::nullptr_t) const {
return m_data == nullptr;
}
inline bool operator!=(std::nullptr_t) const {
return m_data != nullptr;
}
inline bool operator==(const char* str) const {
if(m_data == nullptr) return str == nullptr;
if(str == nullptr) return false;
if(m_size != std::strlen(str)) return false;
return base::StrBuffer::equalsCI(m_data, str, m_size);
}
inline bool operator!=(const char* str) const {
return !operator==(str);
}
inline bool operator==(const String& str) const {
if(m_data == nullptr) return str == nullptr;
if(str == nullptr) return false;
if(m_size != str->getSize()) return false;
return base::StrBuffer::equalsCI(m_data, str->getData(), m_size);
}
inline bool operator!=(const String& str) const {
return !operator==(str);
}
inline bool operator==(const StringKeyLabelCI &other) const {
return m_size == other.m_size && base::StrBuffer::equalsCI(m_data, other.m_data, m_size);
}
bool operator!=(const StringKeyLabelCI &other) const {
inline bool operator!=(const StringKeyLabelCI &other) const {
return !(m_size == other.m_size && base::StrBuffer::equalsCI(m_data, other.m_data, m_size));
}
};
/**
@ -208,17 +278,49 @@ public:
class StringKeyLabelCI_FAST : public MemoryLabel {
public:
StringKeyLabelCI_FAST() : MemoryLabel() {};
StringKeyLabelCI_FAST(std::nullptr_t) : MemoryLabel() {}
StringKeyLabelCI_FAST(const std::shared_ptr<base::StrBuffer>& memHandle, p_char8 data, v_buff_size size);
StringKeyLabelCI_FAST(const char* constText);
StringKeyLabelCI_FAST(const oatpp::String& str);
bool operator==(const StringKeyLabelCI_FAST &other) const {
StringKeyLabelCI_FAST(const String& str);
inline bool operator==(std::nullptr_t) const {
return m_data == nullptr;
}
inline bool operator!=(std::nullptr_t) const {
return m_data != nullptr;
}
inline bool operator==(const char* str) const {
if(m_data == nullptr) return str == nullptr;
if(str == nullptr) return false;
if(m_size != std::strlen(str)) return false;
return base::StrBuffer::equalsCI_FAST(m_data, str, m_size);
}
inline bool operator!=(const char* str) const {
return !operator==(str);
}
inline bool operator==(const String& str) const {
if(m_data == nullptr) return str == nullptr;
if(str == nullptr) return false;
if(m_size != str->getSize()) return false;
return base::StrBuffer::equalsCI_FAST(m_data, str->getData(), m_size);
}
inline bool operator!=(const String& str) const {
return !operator==(str);
}
inline bool operator==(const StringKeyLabelCI_FAST &other) const {
return m_size == other.m_size && base::StrBuffer::equalsCI_FAST(m_data, other.m_data, m_size);
}
bool operator!=(const StringKeyLabelCI_FAST &other) const {
inline bool operator!=(const StringKeyLabelCI_FAST &other) const {
return !(m_size == other.m_size && base::StrBuffer::equalsCI_FAST(m_data, other.m_data, m_size));
}
@ -232,7 +334,7 @@ namespace std {
struct hash<oatpp::data::share::StringKeyLabel> {
typedef oatpp::data::share::StringKeyLabel argument_type;
typedef v_uint32 result_type;
typedef v_uint64 result_type;
result_type operator()(oatpp::data::share::StringKeyLabel const& s) const noexcept {
@ -252,7 +354,7 @@ namespace std {
struct hash<oatpp::data::share::StringKeyLabelCI> {
typedef oatpp::data::share::StringKeyLabelCI argument_type;
typedef v_uint32 result_type;
typedef v_uint64 result_type;
result_type operator()(oatpp::data::share::StringKeyLabelCI const& s) const noexcept {
@ -272,7 +374,7 @@ namespace std {
struct hash<oatpp::data::share::StringKeyLabelCI_FAST> {
typedef oatpp::data::share::StringKeyLabelCI_FAST argument_type;
typedef v_uint32 result_type;
typedef v_uint64 result_type;
result_type operator()(oatpp::data::share::StringKeyLabelCI_FAST const& s) const noexcept {

View File

@ -438,7 +438,7 @@ ConsistentOutputStream& operator << (ConsistentOutputStream& s, const oatpp::Str
ConsistentOutputStream& operator << (ConsistentOutputStream& s, const Int8& value) {
if(value.getPtr()) {
return operator << (s, value->getValue());
return operator << (s, *value);
}
s.writeSimple("[<Int8(null)>]");
return s;
@ -446,7 +446,7 @@ ConsistentOutputStream& operator << (ConsistentOutputStream& s, const Int8& valu
ConsistentOutputStream& operator << (ConsistentOutputStream& s, const UInt8& value) {
if(value.getPtr()) {
return operator << (s, value->getValue());
return operator << (s, *value);
}
s.writeSimple("[<UInt8(null)>]");
return s;
@ -454,7 +454,7 @@ ConsistentOutputStream& operator << (ConsistentOutputStream& s, const UInt8& val
ConsistentOutputStream& operator << (ConsistentOutputStream& s, const Int16& value) {
if(value.getPtr()) {
return operator << (s, value->getValue());
return operator << (s, *value);
}
s.writeSimple("[<Int16(null)>]");
return s;
@ -462,7 +462,7 @@ ConsistentOutputStream& operator << (ConsistentOutputStream& s, const Int16& val
ConsistentOutputStream& operator << (ConsistentOutputStream& s, const UInt16& value) {
if(value.getPtr()) {
return operator << (s, value->getValue());
return operator << (s, *value);
}
s.writeSimple("[<UInt16(null)>]");
return s;
@ -470,7 +470,7 @@ ConsistentOutputStream& operator << (ConsistentOutputStream& s, const UInt16& va
ConsistentOutputStream& operator << (ConsistentOutputStream& s, const Int32& value) {
if(value.getPtr()) {
return operator << (s, value->getValue());
return operator << (s, *value);
}
s.writeSimple("[<Int32(null)>]");
return s;
@ -478,7 +478,7 @@ ConsistentOutputStream& operator << (ConsistentOutputStream& s, const Int32& val
ConsistentOutputStream& operator << (ConsistentOutputStream& s, const UInt32& value) {
if(value.getPtr()) {
return operator << (s, value->getValue());
return operator << (s, *value);
}
s.writeSimple("[<UInt32(null)>]");
return s;
@ -486,7 +486,7 @@ ConsistentOutputStream& operator << (ConsistentOutputStream& s, const UInt32& va
ConsistentOutputStream& operator << (ConsistentOutputStream& s, const Int64& value) {
if(value.getPtr()) {
return operator << (s, value->getValue());
return operator << (s, *value);
}
s.writeSimple("[<Int64(null)>]");
return s;
@ -494,7 +494,7 @@ ConsistentOutputStream& operator << (ConsistentOutputStream& s, const Int64& val
ConsistentOutputStream& operator << (ConsistentOutputStream& s, const UInt64& value) {
if(value.getPtr()) {
return operator << (s, value->getValue());
return operator << (s, *value);
}
s.writeSimple("[<UInt64(null)>]");
return s;
@ -502,7 +502,7 @@ ConsistentOutputStream& operator << (ConsistentOutputStream& s, const UInt64& va
ConsistentOutputStream& operator << (ConsistentOutputStream& s, const Float32& value) {
if(value.getPtr()) {
return operator << (s, value->getValue());
return operator << (s, *value);
}
s.writeSimple("[<Float32(null)>]");
return s;
@ -510,7 +510,7 @@ ConsistentOutputStream& operator << (ConsistentOutputStream& s, const Float32& v
ConsistentOutputStream& operator << (ConsistentOutputStream& s, const Float64& value) {
if(value.getPtr()) {
return operator << (s, value->getValue());
return operator << (s, *value);
}
s.writeSimple("[<Float64(null)>]");
return s;
@ -518,7 +518,7 @@ ConsistentOutputStream& operator << (ConsistentOutputStream& s, const Float64& v
ConsistentOutputStream& operator << (ConsistentOutputStream& s, const Boolean& value) {
if(value.getPtr()) { // use getPtr() here to avoid false to nullptr conversion
return operator << (s, value->getValue());
return operator << (s, *value);
}
s.writeSimple("[<Boolean(null)>]");
return s;

View File

@ -26,8 +26,8 @@
* This file contains source code for basic helper macros used for code-generator.
*/
#ifndef oatpp_macro_ForEach_hpp
#define oatpp_macro_ForEach_hpp
#ifndef oatpp_macro_basic_hpp
#define oatpp_macro_basic_hpp
#define OATPP_MACRO_FOREACH_EXAMPLE_FUNC(INDEX, COUNT, X) \
ENV::log("macro", "param: %d/%d: '%s'", INDEX, COUNT, #X);
@ -498,4 +498,4 @@ OATPP_MACRO_EXPAND(OATPP_MACRO_FOREACH_CALL(N - 99, N, M, OATPP_MACRO_FIRSTARG_E
OATPP_MACRO_FOREACH_98(N, M, OATPP_MACRO_RESTARGS(__VA_ARGS__))
#endif /* oatpp_macro_ForEach_hpp */
#endif /* oatpp_macro_basic_hpp */

View File

@ -35,14 +35,21 @@
*
*/
#ifndef codegen_hpp
#define codegen_hpp
#ifndef oatpp_macro_codegen_hpp
#define oatpp_macro_codegen_hpp
#include "./basic.hpp"
#define OATPP_MACRO_CODEGEN_EXPAND(X) OATPP_MACRO_STR(X)
#define OATPP_CODEGEN_DEFINE_ApiController "oatpp/codegen/ApiController_define.hpp"
#define OATPP_CODEGEN_UNDEF_ApiController "oatpp/codegen/ApiController_undef.hpp"
#define OATPP_CODEGEN_BEGIN(NAME) OATPP_MACRO_CODEGEN_EXPAND(OATPP_MACRO_CONCAT2(oatpp/codegen/codegen_define_, NAME##_.hpp))
#define OATPP_CODEGEN_END(NAME) OATPP_MACRO_CODEGEN_EXPAND(OATPP_MACRO_CONCAT2(oatpp/codegen/codegen_undef_, NAME##_.hpp))
#define OATPP_CODEGEN_DEFINE_ApiClient "oatpp/codegen/ApiClient_define.hpp"
#define OATPP_CODEGEN_UNDEF_ApiClient "oatpp/codegen/ApiClient_undef.hpp"
#endif /* codegen_hpp */
#define OATPP_CODEGEN_DEFINE_DTO "oatpp/codegen/DTO_define.hpp"
#define OATPP_CODEGEN_UNDEF_DTO "oatpp/codegen/DTO_undef.hpp"
#define OATPP_CODEGEN_BEGIN(NAME) OATPP_MACRO_EXPAND(OATPP_CODEGEN_DEFINE_ ## NAME)
#define OATPP_CODEGEN_END(NAME) OATPP_MACRO_EXPAND(OATPP_CODEGEN_UNDEF_ ## NAME)
#endif /* oatpp_macro_codegen_hpp */

View File

@ -61,13 +61,17 @@ v_io_size Beautifier::write(const void *data, v_buff_size count, async::Action&
continue;
}
switch(c) {
case '\\': {
if(m_isInString) {
if(c == '\\') {
m_isCharEscaped = true;
buffer.writeCharSimple('\\');
break;
} else if(c == '"') {
m_isInString = false;
}
buffer.writeCharSimple(c);
continue;
}
switch(c) {
case '{': {
if(m_wantIndent) {
@ -121,20 +125,20 @@ v_io_size Beautifier::write(const void *data, v_buff_size count, async::Action&
}
buffer.writeCharSimple('"');
m_wantIndent = false;
m_isInString = !m_isInString;
m_isInString = true;
break;
}
case ':': {
if(!m_isInString) {
buffer.writeSimple(": ", 2);
} else {
buffer.writeCharSimple(':');
}
buffer.writeSimple(": ", 2);
break;
}
default:
if(m_wantIndent) {
writeIndent(&buffer);
m_wantIndent = false;
}
buffer.writeCharSimple(c);
}

View File

@ -24,7 +24,6 @@
#include "Deserializer.hpp"
#include "oatpp/parser/json/Utils.hpp"
#include "oatpp/core/utils/ConversionUtils.hpp"
namespace oatpp { namespace parser { namespace json { namespace mapping {
@ -35,27 +34,34 @@ Deserializer::Deserializer(const std::shared_ptr<Config>& config)
m_methods.resize(data::mapping::type::ClassId::getClassCount(), nullptr);
setDeserializerMethod(oatpp::data::mapping::type::__class::String::CLASS_ID, &Deserializer::deserializeString);
setDeserializerMethod(data::mapping::type::__class::String::CLASS_ID, &Deserializer::deserializeString);
setDeserializerMethod(data::mapping::type::__class::Any::CLASS_ID, &Deserializer::deserializeAny);
setDeserializerMethod(oatpp::data::mapping::type::__class::Int8::CLASS_ID, &Deserializer::deserializeInt<oatpp::Int8>);
setDeserializerMethod(oatpp::data::mapping::type::__class::UInt8::CLASS_ID, &Deserializer::deserializeUInt<oatpp::UInt8>);
setDeserializerMethod(data::mapping::type::__class::Int8::CLASS_ID, &Deserializer::deserializeInt<oatpp::Int8>);
setDeserializerMethod(data::mapping::type::__class::UInt8::CLASS_ID, &Deserializer::deserializeUInt<oatpp::UInt8>);
setDeserializerMethod(oatpp::data::mapping::type::__class::Int16::CLASS_ID, &Deserializer::deserializeInt<oatpp::Int16>);
setDeserializerMethod(oatpp::data::mapping::type::__class::UInt16::CLASS_ID, &Deserializer::deserializeUInt<oatpp::UInt16>);
setDeserializerMethod(data::mapping::type::__class::Int16::CLASS_ID, &Deserializer::deserializeInt<oatpp::Int16>);
setDeserializerMethod(data::mapping::type::__class::UInt16::CLASS_ID, &Deserializer::deserializeUInt<oatpp::UInt16>);
setDeserializerMethod(oatpp::data::mapping::type::__class::Int32::CLASS_ID, &Deserializer::deserializeInt<oatpp::Int32>);
setDeserializerMethod(oatpp::data::mapping::type::__class::UInt32::CLASS_ID, &Deserializer::deserializeUInt<oatpp::UInt32>);
setDeserializerMethod(data::mapping::type::__class::Int32::CLASS_ID, &Deserializer::deserializeInt<oatpp::Int32>);
setDeserializerMethod(data::mapping::type::__class::UInt32::CLASS_ID, &Deserializer::deserializeUInt<oatpp::UInt32>);
setDeserializerMethod(oatpp::data::mapping::type::__class::Int64::CLASS_ID, &Deserializer::deserializeInt<oatpp::Int64>);
setDeserializerMethod(oatpp::data::mapping::type::__class::UInt64::CLASS_ID, &Deserializer::deserializeUInt<oatpp::UInt64>);
setDeserializerMethod(data::mapping::type::__class::Int64::CLASS_ID, &Deserializer::deserializeInt<oatpp::Int64>);
setDeserializerMethod(data::mapping::type::__class::UInt64::CLASS_ID, &Deserializer::deserializeUInt<oatpp::UInt64>);
setDeserializerMethod(oatpp::data::mapping::type::__class::Float32::CLASS_ID, &Deserializer::deserializeFloat32);
setDeserializerMethod(oatpp::data::mapping::type::__class::Float64::CLASS_ID, &Deserializer::deserializeFloat64);
setDeserializerMethod(oatpp::data::mapping::type::__class::Boolean::CLASS_ID, &Deserializer::deserializeBoolean);
setDeserializerMethod(data::mapping::type::__class::Float32::CLASS_ID, &Deserializer::deserializeFloat32);
setDeserializerMethod(data::mapping::type::__class::Float64::CLASS_ID, &Deserializer::deserializeFloat64);
setDeserializerMethod(data::mapping::type::__class::Boolean::CLASS_ID, &Deserializer::deserializeBoolean);
setDeserializerMethod(oatpp::data::mapping::type::__class::AbstractList::CLASS_ID, &Deserializer::deserializeList);
setDeserializerMethod(oatpp::data::mapping::type::__class::AbstractListMap::CLASS_ID, &Deserializer::deserializeFieldsMap);
setDeserializerMethod(oatpp::data::mapping::type::__class::AbstractObject::CLASS_ID, &Deserializer::deserializeObject);
setDeserializerMethod(data::mapping::type::__class::AbstractObject::CLASS_ID, &Deserializer::deserializeObject);
setDeserializerMethod(data::mapping::type::__class::AbstractEnum::CLASS_ID, &Deserializer::deserializeEnum);
setDeserializerMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, &Deserializer::deserializeList<oatpp::AbstractVector>);
setDeserializerMethod(data::mapping::type::__class::AbstractList::CLASS_ID, &Deserializer::deserializeList<oatpp::AbstractList>);
setDeserializerMethod(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &Deserializer::deserializeList<oatpp::AbstractUnorderedSet>);
setDeserializerMethod(data::mapping::type::__class::AbstractPairList::CLASS_ID, &Deserializer::deserializeKeyValue<oatpp::AbstractFields>);
setDeserializerMethod(data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID, &Deserializer::deserializeKeyValue<oatpp::AbstractUnorderedFields>);
}
@ -149,201 +155,148 @@ void Deserializer::skipValue(oatpp::parser::Caret& caret){
}
}
data::mapping::type::AbstractObjectWrapper Deserializer::deserializeFloat32(Deserializer* deserializer,
parser::Caret& caret,
const Type* const type)
{
oatpp::Void Deserializer::deserializeFloat32(Deserializer* deserializer, parser::Caret& caret, const Type* const type) {
(void) deserializer;
(void) type;
if(caret.isAtText("null", true)){
return AbstractObjectWrapper(Float32::ObjectWrapper::Class::getType());
return oatpp::Void(Float32::ObjectWrapper::Class::getType());
} else {
return AbstractObjectWrapper(Float32::ObjectType::createAbstract(caret.parseFloat32()), Float32::ObjectWrapper::Class::getType());
return Float32(caret.parseFloat32());
}
}
data::mapping::type::AbstractObjectWrapper Deserializer::deserializeFloat64(Deserializer* deserializer,
parser::Caret& caret,
const Type* const type)
{
oatpp::Void Deserializer::deserializeFloat64(Deserializer* deserializer, parser::Caret& caret, const Type* const type) {
(void) deserializer;
(void) type;
if(caret.isAtText("null", true)){
return AbstractObjectWrapper(Float64::ObjectWrapper::Class::getType());
return oatpp::Void(Float64::ObjectWrapper::Class::getType());
} else {
return AbstractObjectWrapper(Float64::ObjectType::createAbstract(caret.parseFloat64()), Float64::ObjectWrapper::Class::getType());
return Float64(caret.parseFloat64());
}
}
data::mapping::type::AbstractObjectWrapper Deserializer::deserializeBoolean(Deserializer* deserializer,
parser::Caret& caret,
const Type* const type)
{
oatpp::Void Deserializer::deserializeBoolean(Deserializer* deserializer, parser::Caret& caret, const Type* const type) {
(void) deserializer;
(void) type;
if(caret.isAtText("null", true)){
return AbstractObjectWrapper(Boolean::ObjectWrapper::Class::getType());
return oatpp::Void(Boolean::ObjectWrapper::Class::getType());
} else {
if(caret.isAtText("true", true)) {
return AbstractObjectWrapper(Boolean::ObjectType::createAbstract(true), Boolean::ObjectWrapper::Class::getType());
return Boolean(true);
} else if(caret.isAtText("false", true)) {
return AbstractObjectWrapper(Boolean::ObjectType::createAbstract(false), Boolean::ObjectWrapper::Class::getType());
return Boolean(false);
} else {
caret.setError("[oatpp::parser::json::mapping::Deserializer::readBooleanValue()]: Error. 'true' or 'false' - expected.", ERROR_CODE_VALUE_BOOLEAN);
return AbstractObjectWrapper(Boolean::ObjectWrapper::Class::getType());
return oatpp::Void(Boolean::ObjectWrapper::Class::getType());
}
}
}
data::mapping::type::AbstractObjectWrapper Deserializer::deserializeString(Deserializer* deserializer,
parser::Caret& caret,
const Type* const type)
{
oatpp::Void Deserializer::deserializeString(Deserializer* deserializer, parser::Caret& caret, const Type* const type) {
(void) deserializer;
(void) type;
if(caret.isAtText("null", true)){
return AbstractObjectWrapper(String::Class::getType());
return oatpp::Void(String::Class::getType());
} else {
return AbstractObjectWrapper(oatpp::parser::json::Utils::parseString(caret).getPtr(), String::Class::getType());
return oatpp::Void(oatpp::parser::json::Utils::parseString(caret).getPtr(), String::Class::getType());
}
}
data::mapping::type::AbstractObjectWrapper Deserializer::deserializeList(Deserializer* deserializer,
parser::Caret& caret,
const Type* const type)
{
if(caret.isAtText("null", true)){
return AbstractObjectWrapper(type);
}
if(caret.canContinueAtChar('[', 1)) {
auto listWrapper = type->creator();
oatpp::data::mapping::type::PolymorphicWrapper<AbstractList>
list(std::static_pointer_cast<AbstractList>(listWrapper.getPtr()), listWrapper.valueType);
Type* itemType = *type->params.begin();
caret.skipBlankChars();
while(!caret.isAtChar(']') && caret.canContinue()){
caret.skipBlankChars();
auto item = deserializer->deserialize(caret, itemType);
if(caret.hasError()){
return nullptr;
}
list->addPolymorphicItem(item);
caret.skipBlankChars();
caret.canContinueAtChar(',', 1);
const data::mapping::type::Type* Deserializer::guessNumberType(oatpp::parser::Caret& caret) {
return Float64::Class::getType();
}
const data::mapping::type::Type* Deserializer::guessType(oatpp::parser::Caret& caret) {
{
parser::Caret::StateSaveGuard stateGuard(caret);
v_char8 c = *caret.getCurrData();
switch (c) {
case '"':
return String::Class::getType();
case '{':
return oatpp::Fields<Any>::ObjectWrapper::Class::getType();
case '[':
return oatpp::List<Any>::ObjectWrapper::Class::getType();
case 't':
if(caret.isAtText("true")) return Boolean::Class::getType();
break;
case 'f':
if(caret.isAtText("false")) return Boolean::Class::getType();
break;
default:
if (c == '-' || caret.isAtDigitChar()) {
return guessNumberType(caret);
}
}
}
caret.setError("[oatpp::parser::json::mapping::Deserializer::guessType()]: Error. Can't guess type for oatpp::Any.");
return nullptr;
}
if(!caret.canContinueAtChar(']', 1)){
if(!caret.hasError()){
caret.setError("[oatpp::parser::json::mapping::Deserializer::readList()]: Error. ']' - expected", ERROR_CODE_ARRAY_SCOPE_CLOSE);
}
return nullptr;
};
return AbstractObjectWrapper(list.getPtr(), list.valueType);
oatpp::Void Deserializer::deserializeAny(Deserializer* deserializer, parser::Caret& caret, const Type* const type) {
(void) type;
if(caret.isAtText("null", true)){
return oatpp::Void(Any::Class::getType());
} else {
caret.setError("[oatpp::parser::json::mapping::Deserializer::readList()]: Error. '[' - expected", ERROR_CODE_ARRAY_SCOPE_OPEN);
const Type* const fieldType = guessType(caret);
if(fieldType != nullptr) {
auto fieldValue = deserializer->deserialize(caret, fieldType);
auto anyHandle = std::make_shared<data::mapping::type::AnyHandle>(fieldValue.getPtr(), fieldValue.valueType);
return oatpp::Void(anyHandle, Any::Class::getType());
}
}
return oatpp::Void(Any::Class::getType());
}
oatpp::Void Deserializer::deserializeEnum(Deserializer* deserializer, parser::Caret& caret, const Type* const type) {
auto polymorphicDispatcher = static_cast<const data::mapping::type::__class::AbstractEnum::AbstractPolymorphicDispatcher*>(
type->polymorphicDispatcher
);
data::mapping::type::EnumInterpreterError e = data::mapping::type::EnumInterpreterError::OK;
const auto& value = deserializer->deserialize(caret, polymorphicDispatcher->getInterpretationType());
if(caret.hasError()) {
return nullptr;
}
const auto& result = polymorphicDispatcher->fromInterpretation(value, e);
}
data::mapping::type::AbstractObjectWrapper Deserializer::deserializeFieldsMap(Deserializer* deserializer,
parser::Caret& caret,
const Type* const type)
{
if(caret.isAtText("null", true)){
return AbstractObjectWrapper(type);
if(e == data::mapping::type::EnumInterpreterError::OK) {
return result;
}
if(caret.canContinueAtChar('{', 1)) {
auto mapWrapper = type->creator();
oatpp::data::mapping::type::PolymorphicWrapper<AbstractFieldsMap>
map(std::static_pointer_cast<AbstractFieldsMap>(mapWrapper.getPtr()), mapWrapper.valueType);
auto it = type->params.begin();
Type* keyType = *it ++;
if(keyType->classId.id != oatpp::data::mapping::type::__class::String::CLASS_ID.id){
throw std::runtime_error("[oatpp::parser::json::mapping::Deserializer::readListMap()]: Invalid json map key. Key should be String");
}
Type* valueType = *it;
caret.skipBlankChars();
while (!caret.isAtChar('}') && caret.canContinue()) {
caret.skipBlankChars();
auto key = Utils::parseString(caret);
if(caret.hasError()){
return nullptr;
}
caret.skipBlankChars();
if(!caret.canContinueAtChar(':', 1)){
caret.setError("[oatpp::parser::json::mapping::Deserializer::readListMap()]: Error. ':' - expected", ERROR_CODE_OBJECT_SCOPE_COLON_MISSING);
return nullptr;
}
caret.skipBlankChars();
map->putPolymorphicItem(key, deserializer->deserialize(caret, valueType));
caret.skipBlankChars();
caret.canContinueAtChar(',', 1);
}
if(!caret.canContinueAtChar('}', 1)){
if(!caret.hasError()){
caret.setError("[oatpp::parser::json::mapping::Deserializer::readListMap()]: Error. '}' - expected", ERROR_CODE_OBJECT_SCOPE_CLOSE);
}
return nullptr;
}
return AbstractObjectWrapper(map.getPtr(), map.valueType);
} else {
caret.setError("[oatpp::parser::json::mapping::Deserializer::readListMap()]: Error. '{' - expected", ERROR_CODE_OBJECT_SCOPE_OPEN);
switch(e) {
case data::mapping::type::EnumInterpreterError::CONSTRAINT_NOT_NULL:
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeEnum()]: Error. Enum constraint violated - 'NotNull'.");
break;
default:
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeEnum()]: Error. Can't deserialize Enum.");
}
return nullptr;
}
data::mapping::type::AbstractObjectWrapper Deserializer::deserializeObject(Deserializer* deserializer,
parser::Caret& caret,
const Type* const type)
{
oatpp::Void Deserializer::deserializeObject(Deserializer* deserializer, parser::Caret& caret, const Type* const type) {
if(caret.isAtText("null", true)){
return AbstractObjectWrapper(type);
return oatpp::Void(type);
}
if(caret.canContinueAtChar('{', 1)) {
auto object = type->creator();
const auto& fieldsMap = type->properties->getMap();
const auto& fieldsMap = type->propertiesGetter()->getMap();
caret.skipBlankChars();
@ -404,7 +357,7 @@ data::mapping::type::AbstractObjectWrapper Deserializer::deserializeObject(Deser
}
data::mapping::type::AbstractObjectWrapper Deserializer::deserialize(parser::Caret& caret, const Type* const type) {
oatpp::Void Deserializer::deserialize(parser::Caret& caret, const Type* const type) {
auto id = type->classId.id;
auto& method = m_methods[id];
if(method) {

View File

@ -25,15 +25,8 @@
#ifndef oatpp_parser_json_mapping_Deserializer_hpp
#define oatpp_parser_json_mapping_Deserializer_hpp
#include "oatpp/core/data/mapping/type/ListMap.hpp"
#include "oatpp/core/data/mapping/type/List.hpp"
#include "oatpp/core/data/mapping/type/Object.hpp"
#include "oatpp/core/data/mapping/type/Primitive.hpp"
#include "oatpp/core/data/mapping/type/Type.hpp"
#include "oatpp/parser/json/Utils.hpp"
#include "oatpp/core/parser/Caret.hpp"
#include "oatpp/core/collection/LinkedList.hpp"
#include "oatpp/core/Types.hpp"
#include <vector>
@ -53,12 +46,6 @@ public:
typedef oatpp::data::mapping::type::Object Object;
typedef oatpp::String String;
template<class T>
using PolymorphicWrapper = data::mapping::type::PolymorphicWrapper<T>;
typedef oatpp::data::mapping::type::AbstractObjectWrapper AbstractObjectWrapper;
typedef oatpp::data::mapping::type::List<AbstractObjectWrapper> AbstractList;
typedef oatpp::data::mapping::type::ListMap<String, AbstractObjectWrapper> AbstractFieldsMap;
public:
/**
@ -127,52 +114,165 @@ public:
};
public:
typedef AbstractObjectWrapper (*DeserializerMethod)(Deserializer*, parser::Caret&, const Type* const);
typedef oatpp::Void (*DeserializerMethod)(Deserializer*, parser::Caret&, const Type* const);
private:
static void skipScope(oatpp::parser::Caret& caret, v_char8 charOpen, v_char8 charClose);
static void skipString(oatpp::parser::Caret& caret);
static void skipToken(oatpp::parser::Caret& caret);
static void skipValue(oatpp::parser::Caret& caret);
private:
static const Type* guessNumberType(oatpp::parser::Caret& caret);
static const Type* guessType(oatpp::parser::Caret& caret);
private:
template<class T>
static AbstractObjectWrapper deserializeInt(Deserializer* deserializer, parser::Caret& caret, const Type* const type){
static oatpp::Void deserializeInt(Deserializer* deserializer, parser::Caret& caret, const Type* const type){
(void) deserializer;
(void) type;
if(caret.isAtText("null", true)){
return AbstractObjectWrapper(T::Class::getType());
return oatpp::Void(T::Class::getType());
} else {
return AbstractObjectWrapper(T::ObjectType::createAbstract((typename T::ObjectType::ValueType) caret.parseInt()), T::ObjectWrapper::Class::getType());
return T(caret.parseInt());
}
}
template<class T>
static AbstractObjectWrapper deserializeUInt(Deserializer* deserializer, parser::Caret& caret, const Type* const type){
static oatpp::Void deserializeUInt(Deserializer* deserializer, parser::Caret& caret, const Type* const type){
(void) deserializer;
(void) type;
if(caret.isAtText("null", true)){
return AbstractObjectWrapper(T::Class::getType());
return oatpp::Void(T::Class::getType());
} else {
return AbstractObjectWrapper(T::ObjectType::createAbstract((typename T::ObjectType::ValueType) caret.parseUnsignedInt()), T::ObjectWrapper::Class::getType());
return T(caret.parseUnsignedInt());
}
}
static AbstractObjectWrapper deserializeFloat32(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
static AbstractObjectWrapper deserializeFloat64(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
template<class Collection>
static oatpp::Void deserializeList(Deserializer* deserializer, parser::Caret& caret, const Type* const type) {
static AbstractObjectWrapper deserializeBoolean(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
if(caret.isAtText("null", true)){
return oatpp::Void(type);
}
static AbstractObjectWrapper deserializeString(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
if(caret.canContinueAtChar('[', 1)) {
static AbstractObjectWrapper deserializeList(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
static AbstractObjectWrapper deserializeFieldsMap(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
static AbstractObjectWrapper deserializeObject(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
auto listWrapper = type->creator();
auto polymorphicDispatcher = static_cast<const typename Collection::Class::AbstractPolymorphicDispatcher*>(type->polymorphicDispatcher);
const auto& list = listWrapper.template staticCast<Collection>();
Type* itemType = *type->params.begin();
caret.skipBlankChars();
while(!caret.isAtChar(']') && caret.canContinue()){
caret.skipBlankChars();
auto item = deserializer->deserialize(caret, itemType);
if(caret.hasError()){
return nullptr;
}
polymorphicDispatcher->addPolymorphicItem(listWrapper, item);
caret.skipBlankChars();
caret.canContinueAtChar(',', 1);
}
if(!caret.canContinueAtChar(']', 1)){
if(!caret.hasError()){
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeList()]: Error. ']' - expected", ERROR_CODE_ARRAY_SCOPE_CLOSE);
}
return nullptr;
};
return oatpp::Void(list.getPtr(), list.valueType);
} else {
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeList()]: Error. '[' - expected", ERROR_CODE_ARRAY_SCOPE_OPEN);
return nullptr;
}
}
template<class Collection>
static oatpp::Void deserializeKeyValue(Deserializer* deserializer, parser::Caret& caret, const Type* const type) {
if(caret.isAtText("null", true)){
return oatpp::Void(type);
}
if(caret.canContinueAtChar('{', 1)) {
auto mapWrapper = type->creator();
auto polymorphicDispatcher = static_cast<const typename Collection::Class::AbstractPolymorphicDispatcher*>(type->polymorphicDispatcher);
const auto& map = mapWrapper.template staticCast<Collection>();
auto it = type->params.begin();
Type* keyType = *it ++;
if(keyType->classId.id != oatpp::data::mapping::type::__class::String::CLASS_ID.id){
throw std::runtime_error("[oatpp::parser::json::mapping::Deserializer::deserializeKeyValue()]: Invalid json map key. Key should be String");
}
Type* valueType = *it;
caret.skipBlankChars();
while (!caret.isAtChar('}') && caret.canContinue()) {
caret.skipBlankChars();
auto key = Utils::parseString(caret);
if(caret.hasError()){
return nullptr;
}
caret.skipBlankChars();
if(!caret.canContinueAtChar(':', 1)){
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeKeyValue()]: Error. ':' - expected", ERROR_CODE_OBJECT_SCOPE_COLON_MISSING);
return nullptr;
}
caret.skipBlankChars();
auto item = deserializer->deserialize(caret, valueType);
if(caret.hasError()){
return nullptr;
}
polymorphicDispatcher->addPolymorphicItem(mapWrapper, key, item);
caret.skipBlankChars();
caret.canContinueAtChar(',', 1);
}
if(!caret.canContinueAtChar('}', 1)){
if(!caret.hasError()){
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeKeyValue()]: Error. '}' - expected", ERROR_CODE_OBJECT_SCOPE_CLOSE);
}
return nullptr;
}
return oatpp::Void(map.getPtr(), map.valueType);
} else {
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeKeyValue()]: Error. '{' - expected", ERROR_CODE_OBJECT_SCOPE_OPEN);
}
return nullptr;
}
static oatpp::Void deserializeFloat32(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
static oatpp::Void deserializeFloat64(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
static oatpp::Void deserializeBoolean(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
static oatpp::Void deserializeString(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
static oatpp::Void deserializeAny(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
static oatpp::Void deserializeEnum(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
static oatpp::Void deserializeObject(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
private:
std::shared_ptr<Config> m_config;
@ -188,7 +288,7 @@ public:
/**
* Set deserializer method for type.
* @param classId - &id:oatpp::data::mapping::type::ClassId;.
* @param method - `typedef AbstractObjectWrapper (*DeserializerMethod)(Deserializer*, parser::Caret&, const Type* const)`.
* @param method - `typedef oatpp::Void (*DeserializerMethod)(Deserializer*, parser::Caret&, const Type* const)`.
*/
void setDeserializerMethod(const data::mapping::type::ClassId& classId, DeserializerMethod method);
@ -196,9 +296,9 @@ public:
* Deserialize text.
* @param caret - &id:oatpp::parser::Caret;.
* @param type - &id:oatpp::data::mapping::type::Type;
* @return - `AbstractObjectWrapper` over deserialized object.
* @return - `oatpp::Void` over deserialized object.
*/
AbstractObjectWrapper deserialize(parser::Caret& caret, const Type* const type);
oatpp::Void deserialize(parser::Caret& caret, const Type* const type);
/**
* Get deserializer config.

View File

@ -51,11 +51,11 @@ std::shared_ptr<ObjectMapper> ObjectMapper::createShared(const std::shared_ptr<S
}
void ObjectMapper::write(data::stream::ConsistentOutputStream* stream,
const oatpp::data::mapping::type::AbstractObjectWrapper& variant) const {
const oatpp::Void& variant) const {
m_serializer->serializeToStream(stream, variant);
}
oatpp::data::mapping::type::AbstractObjectWrapper ObjectMapper::read(oatpp::parser::Caret& caret,
oatpp::Void ObjectMapper::read(oatpp::parser::Caret& caret,
const oatpp::data::mapping::type::Type* const type) const {
return m_deserializer->deserialize(caret, type);
}

View File

@ -87,19 +87,17 @@ public:
/**
* Implementation of &id:oatpp::data::mapping::ObjectMapper::write;.
* @param stream - stream to write serializerd data to &id:oatpp::data::stream::ConsistentOutputStream;.
* @param variant - object to serialize &id:oatpp::data::mapping::type::AbstractObjectWrapper;.
* @param variant - object to serialize &id:oatpp::Void;.
*/
void write(data::stream::ConsistentOutputStream* stream,
const oatpp::data::mapping::type::AbstractObjectWrapper& variant) const override;
void write(data::stream::ConsistentOutputStream* stream, const oatpp::Void& 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.
* @return - &id:oatpp::Void; holding resultant object.
*/
oatpp::data::mapping::type::AbstractObjectWrapper read(oatpp::parser::Caret& caret,
const oatpp::data::mapping::type::Type* const type) const override;
oatpp::Void read(oatpp::parser::Caret& caret, const oatpp::data::mapping::type::Type* const type) const override;
/**

View File

@ -25,6 +25,7 @@
#include "Serializer.hpp"
#include "oatpp/parser/json/Utils.hpp"
#include "oatpp/core/data/mapping/type/Any.hpp"
namespace oatpp { namespace parser { namespace json { namespace mapping {
@ -34,27 +35,34 @@ Serializer::Serializer(const std::shared_ptr<Config>& config)
m_methods.resize(data::mapping::type::ClassId::getClassCount(), nullptr);
setSerializerMethod(oatpp::data::mapping::type::__class::String::CLASS_ID, &Serializer::serializeString);
setSerializerMethod(data::mapping::type::__class::String::CLASS_ID, &Serializer::serializeString);
setSerializerMethod(data::mapping::type::__class::Any::CLASS_ID, &Serializer::serializeAny);
setSerializerMethod(oatpp::data::mapping::type::__class::Int8::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int8>);
setSerializerMethod(oatpp::data::mapping::type::__class::UInt8::CLASS_ID, &Serializer::serializePrimitive<oatpp::UInt8>);
setSerializerMethod(data::mapping::type::__class::Int8::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int8>);
setSerializerMethod(data::mapping::type::__class::UInt8::CLASS_ID, &Serializer::serializePrimitive<oatpp::UInt8>);
setSerializerMethod(oatpp::data::mapping::type::__class::Int16::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int16>);
setSerializerMethod(oatpp::data::mapping::type::__class::UInt16::CLASS_ID, &Serializer::serializePrimitive<oatpp::UInt16>);
setSerializerMethod(data::mapping::type::__class::Int16::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int16>);
setSerializerMethod(data::mapping::type::__class::UInt16::CLASS_ID, &Serializer::serializePrimitive<oatpp::UInt16>);
setSerializerMethod(oatpp::data::mapping::type::__class::Int32::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int32>);
setSerializerMethod(oatpp::data::mapping::type::__class::UInt32::CLASS_ID, &Serializer::serializePrimitive<oatpp::UInt32>);
setSerializerMethod(data::mapping::type::__class::Int32::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int32>);
setSerializerMethod(data::mapping::type::__class::UInt32::CLASS_ID, &Serializer::serializePrimitive<oatpp::UInt32>);
setSerializerMethod(oatpp::data::mapping::type::__class::Int64::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int64>);
setSerializerMethod(oatpp::data::mapping::type::__class::UInt64::CLASS_ID, &Serializer::serializePrimitive<oatpp::UInt64>);
setSerializerMethod(data::mapping::type::__class::Int64::CLASS_ID, &Serializer::serializePrimitive<oatpp::Int64>);
setSerializerMethod(data::mapping::type::__class::UInt64::CLASS_ID, &Serializer::serializePrimitive<oatpp::UInt64>);
setSerializerMethod(oatpp::data::mapping::type::__class::Float32::CLASS_ID, &Serializer::serializePrimitive<oatpp::Float32>);
setSerializerMethod(oatpp::data::mapping::type::__class::Float64::CLASS_ID, &Serializer::serializePrimitive<oatpp::Float64>);
setSerializerMethod(oatpp::data::mapping::type::__class::Boolean::CLASS_ID, &Serializer::serializePrimitive<oatpp::Boolean>);
setSerializerMethod(data::mapping::type::__class::Float32::CLASS_ID, &Serializer::serializePrimitive<oatpp::Float32>);
setSerializerMethod(data::mapping::type::__class::Float64::CLASS_ID, &Serializer::serializePrimitive<oatpp::Float64>);
setSerializerMethod(data::mapping::type::__class::Boolean::CLASS_ID, &Serializer::serializePrimitive<oatpp::Boolean>);
setSerializerMethod(oatpp::data::mapping::type::__class::AbstractObject::CLASS_ID, &Serializer::serializeObject);
setSerializerMethod(oatpp::data::mapping::type::__class::AbstractList::CLASS_ID, &Serializer::serializeList);
setSerializerMethod(oatpp::data::mapping::type::__class::AbstractListMap::CLASS_ID, &Serializer::serializeFieldsMap);
setSerializerMethod(data::mapping::type::__class::AbstractObject::CLASS_ID, &Serializer::serializeObject);
setSerializerMethod(data::mapping::type::__class::AbstractEnum::CLASS_ID, &Serializer::serializeEnum);
setSerializerMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, &Serializer::serializeList<oatpp::AbstractVector>);
setSerializerMethod(data::mapping::type::__class::AbstractList::CLASS_ID, &Serializer::serializeList<oatpp::AbstractList>);
setSerializerMethod(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &Serializer::serializeList<oatpp::AbstractUnorderedSet>);
setSerializerMethod(data::mapping::type::__class::AbstractPairList::CLASS_ID, &Serializer::serializeKeyValue<oatpp::AbstractFields>);
setSerializerMethod(data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID, &Serializer::serializeKeyValue<oatpp::AbstractUnorderedFields>);
}
@ -67,7 +75,7 @@ void Serializer::setSerializerMethod(const data::mapping::type::ClassId& classId
}
}
void Serializer::serializeString(oatpp::data::stream::ConsistentOutputStream* stream, p_char8 data, v_buff_size size) {
void Serializer::serializeString(data::stream::ConsistentOutputStream* stream, p_char8 data, v_buff_size size) {
auto encodedValue = Utils::escapeString(data, size, false);
stream->writeCharSimple('\"');
stream->writeSimple(encodedValue);
@ -76,7 +84,7 @@ void Serializer::serializeString(oatpp::data::stream::ConsistentOutputStream* st
void Serializer::serializeString(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const data::mapping::type::AbstractObjectWrapper& polymorph)
const oatpp::Void& polymorph)
{
(void) serializer;
@ -92,9 +100,9 @@ void Serializer::serializeString(Serializer* serializer,
}
void Serializer::serializeList(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const data::mapping::type::AbstractObjectWrapper& polymorph)
void Serializer::serializeAny(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph)
{
if(!polymorph) {
@ -102,60 +110,38 @@ void Serializer::serializeList(Serializer* serializer,
return;
}
auto* list = static_cast<AbstractList*>(polymorph.get());
stream->writeCharSimple('[');
bool first = true;
auto curr = list->getFirstNode();
while(curr != nullptr){
auto value = curr->getData();
if(value || serializer->getConfig()->includeNullFields) {
(first) ? first = false : stream->writeSimple(",", 1);
serializer->serialize(stream, curr->getData());
}
curr = curr->getNext();
}
stream->writeCharSimple(']');
auto anyHandle = static_cast<data::mapping::type::AnyHandle*>(polymorph.get());
serializer->serialize(stream, oatpp::Void(anyHandle->ptr, anyHandle->type));
}
void Serializer::serializeFieldsMap(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const data::mapping::type::AbstractObjectWrapper& polymorph)
void Serializer::serializeEnum(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph)
{
auto polymorphicDispatcher = static_cast<const data::mapping::type::__class::AbstractEnum::AbstractPolymorphicDispatcher*>(
polymorph.valueType->polymorphicDispatcher
);
if(!polymorph) {
stream->writeSimple("null", 4);
data::mapping::type::EnumInterpreterError e = data::mapping::type::EnumInterpreterError::OK;
serializer->serialize(stream, polymorphicDispatcher->toInterpretation(polymorph, e));
if(e == data::mapping::type::EnumInterpreterError::OK) {
return;
}
auto map = static_cast<AbstractFieldsMap*>(polymorph.get());
stream->writeCharSimple('{');
bool first = true;
auto curr = map->getFirstEntry();
while(curr != nullptr){
auto value = curr->getValue();
if(value || serializer->getConfig()->includeNullFields) {
(first) ? first = false : stream->writeSimple(",", 1);
auto key = curr->getKey();
serializeString(stream, key->getData(), key->getSize());
stream->writeSimple(":", 1);
serializer->serialize(stream, curr->getValue());
}
curr = curr->getNext();
switch(e) {
case data::mapping::type::EnumInterpreterError::CONSTRAINT_NOT_NULL:
throw std::runtime_error("[oatpp::parser::json::mapping::Serializer::serializeEnum()]: Error. Enum constraint violated - 'NotNull'.");
default:
throw std::runtime_error("[oatpp::parser::json::mapping::Serializer::serializeEnum()]: Error. Can't serialize Enum.");
}
stream->writeCharSimple('}');
}
void Serializer::serializeObject(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const data::mapping::type::AbstractObjectWrapper& polymorph)
const oatpp::Void& polymorph)
{
if(!polymorph) {
@ -166,7 +152,7 @@ void Serializer::serializeObject(Serializer* serializer,
stream->writeCharSimple('{');
bool first = true;
auto fields = polymorph.valueType->properties->getList();
auto fields = polymorph.valueType->propertiesGetter()->getList();
Object* object = static_cast<Object*>(polymorph.get());
for (auto const& field : fields) {
@ -186,7 +172,7 @@ void Serializer::serializeObject(Serializer* serializer,
}
void Serializer::serialize(data::stream::ConsistentOutputStream* stream,
const data::mapping::type::AbstractObjectWrapper& polymorph)
const oatpp::Void& polymorph)
{
auto id = polymorph.valueType->classId.id;
auto& method = m_methods[id];
@ -199,7 +185,7 @@ void Serializer::serialize(data::stream::ConsistentOutputStream* stream,
}
void Serializer::serializeToStream(data::stream::ConsistentOutputStream* stream,
const data::mapping::type::AbstractObjectWrapper& polymorph)
const oatpp::Void& polymorph)
{
if(m_config->useBeautifier) {
json::Beautifier beautifier(stream, " ", "\n");

View File

@ -26,16 +26,7 @@
#define oatpp_parser_json_mapping_Serializer_hpp
#include "oatpp/parser/json/Beautifier.hpp"
#include "oatpp/core/data/mapping/type/ListMap.hpp"
#include "oatpp/core/data/mapping/type/List.hpp"
#include "oatpp/core/data/mapping/type/Object.hpp"
#include "oatpp/core/data/mapping/type/Primitive.hpp"
#include "oatpp/core/data/mapping/type/Type.hpp"
#include "oatpp/core/collection/LinkedList.hpp"
#include "oatpp/core/Types.hpp"
#include <vector>
namespace oatpp { namespace parser { namespace json { namespace mapping {
@ -52,14 +43,6 @@ public:
typedef oatpp::data::mapping::type::Object Object;
typedef oatpp::String String;
template<class T>
using PolymorphicWrapper = data::mapping::type::PolymorphicWrapper<T>;
typedef oatpp::data::mapping::type::AbstractObjectWrapper AbstractObjectWrapper;
typedef oatpp::data::mapping::type::List<AbstractObjectWrapper> AbstractList;
typedef oatpp::data::mapping::type::ListMap<String, AbstractObjectWrapper> AbstractFieldsMap;
public:
/**
* Serializer config.
@ -113,40 +96,92 @@ public:
public:
typedef void (*SerializerMethod)(Serializer*,
data::stream::ConsistentOutputStream*,
const data::mapping::type::AbstractObjectWrapper&);
const oatpp::Void&);
private:
template<class T>
static void serializePrimitive(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const data::mapping::type::AbstractObjectWrapper& polymorph){
const oatpp::Void& polymorph){
(void) serializer;
if(polymorph){
stream->writeAsString(static_cast<typename T::ObjectType*>(polymorph.get())->getValue());
stream->writeAsString(* static_cast<typename T::ObjectType*>(polymorph.get()));
} else {
stream->writeSimple("null", 4);
}
}
template<class Collection>
static void serializeList(Serializer* serializer, data::stream::ConsistentOutputStream* stream, const oatpp::Void& polymorph) {
if(!polymorph) {
stream->writeSimple("null", 4);
return;
}
const auto& list = polymorph.staticCast<Collection>();
stream->writeCharSimple('[');
bool first = true;
for(auto& value : *list) {
if(value || serializer->getConfig()->includeNullFields) {
(first) ? first = false : stream->writeSimple(",", 1);
serializer->serialize(stream, value);
}
}
stream->writeCharSimple(']');
}
template<class Collection>
static void serializeKeyValue(Serializer* serializer, data::stream::ConsistentOutputStream* stream, const oatpp::Void& polymorph) {
if(!polymorph) {
stream->writeSimple("null", 4);
return;
}
const auto& map = polymorph.staticCast<Collection>();
stream->writeCharSimple('{');
bool first = true;
for(auto& pair : *map) {
const auto& value = pair.second;
if(value || serializer->getConfig()->includeNullFields) {
(first) ? first = false : stream->writeSimple(",", 1);
const auto& key = pair.first;
serializeString(stream, key->getData(), key->getSize());
stream->writeSimple(":", 1);
serializer->serialize(stream, value);
}
}
stream->writeCharSimple('}');
}
static void serializeString(oatpp::data::stream::ConsistentOutputStream* stream, p_char8 data, v_buff_size size);
static void serializeString(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const data::mapping::type::AbstractObjectWrapper& polymorph);
const oatpp::Void& polymorph);
static void serializeList(Serializer* serializer,
static void serializeAny(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph);
static void serializeEnum(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const data::mapping::type::AbstractObjectWrapper& polymorph);
static void serializeFieldsMap(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const data::mapping::type::AbstractObjectWrapper& polymorph);
const oatpp::Void& polymorph);
static void serializeObject(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const data::mapping::type::AbstractObjectWrapper& polymorph);
const oatpp::Void& polymorph);
void serialize(data::stream::ConsistentOutputStream* stream, const data::mapping::type::AbstractObjectWrapper& polymorph);
void serialize(data::stream::ConsistentOutputStream* stream, const oatpp::Void& polymorph);
private:
std::shared_ptr<Config> m_config;
@ -162,16 +197,16 @@ public:
/**
* Set serializer method for type.
* @param classId - &id:oatpp::data::mapping::type::ClassId;.
* @param method - `typedef void (*SerializerMethod)(Serializer*, data::stream::ConsistentOutputStream*, const data::mapping::type::AbstractObjectWrapper&)`.
* @param method - `typedef void (*SerializerMethod)(Serializer*, data::stream::ConsistentOutputStream*, const oatpp::Void&)`.
*/
void setSerializerMethod(const data::mapping::type::ClassId& classId, SerializerMethod method);
/**
* Serialize object to stream.
* @param stream - &id:oatpp::data::stream::ConsistentOutputStream;.
* @param polymorph - DTO as &id:oatpp::data::mapping::type::AbstractObjectWrapper;.
* @param polymorph - DTO as &id:oatpp::Void;.
*/
void serializeToStream(data::stream::ConsistentOutputStream* stream, const data::mapping::type::AbstractObjectWrapper& polymorph);
void serializeToStream(data::stream::ConsistentOutputStream* stream, const oatpp::Void& polymorph);
/**
* Get serializer config.

View File

@ -84,7 +84,7 @@ void ApiClient::formatPath(oatpp::data::stream::ConsistentOutputStream* stream,
auto& param = params->get(key, nullptr);
if(!param){
OATPP_LOGD(TAG, "Path parameter '%s' not provided in the api call", seg.text.c_str());
throw std::runtime_error("[oatpp::web::client::ApiClient]: Path parameter missing");
throw std::runtime_error("[oatpp::web::client::ApiClient::formatPath()]: Path parameter missing");
}
stream->data::stream::OutputStream::writeSimple(param);
}
@ -132,7 +132,12 @@ web::protocol::http::Headers ApiClient::mapToHeaders(const std::shared_ptr<Strin
auto curr = params->getFirstEntry();
while (curr != nullptr) {
result.put_LockFree(curr->getKey(), curr->getValue());
if(curr->getValue()) {
result.put_LockFree(curr->getKey(), curr->getValue());
} else {
OATPP_LOGE(TAG, "Header parameter '%s' not provided in the api call", curr->getKey()->c_str());
throw std::runtime_error("[oatpp::web::client::ApiClient::mapToHeaders()]: Header parameter missing");
}
curr = curr->getNext();
}
}

View File

@ -73,35 +73,69 @@ public:
*/
typedef oatpp::web::protocol::http::Header Header;
public:
/**
* Convenience typedef for &id:oatpp::data::mapping::type::String;.
*/
typedef oatpp::data::mapping::type::String String;
typedef oatpp::String String;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::Int8;.
*/
typedef oatpp::Int8 Int8;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::UInt8;.
*/
typedef oatpp::UInt8 UInt8;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::Int16;.
*/
typedef oatpp::Int16 Int16;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::UInt16;.
*/
typedef oatpp::UInt16 UInt16;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::Int32;.
*/
typedef oatpp::data::mapping::type::Int32 Int32;
typedef oatpp::Int32 Int32;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::UInt32;.
*/
typedef oatpp::UInt32 UInt32;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::Int64;.
*/
typedef oatpp::data::mapping::type::Int64 Int64;
typedef oatpp::Int64 Int64;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::UInt64;.
*/
typedef oatpp::UInt64 UInt64;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::Float32;.
*/
typedef oatpp::data::mapping::type::Float32 Float32;
typedef oatpp::Float32 Float32;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::Float64;.
* Convenience typedef for &id:atpp::data::mapping::type::Float64;.
*/
typedef oatpp::data::mapping::type::Float64 Float64;
typedef oatpp::Float64 Float64;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::Boolean;.
*/
typedef oatpp::data::mapping::type::Boolean Boolean;
typedef oatpp::Boolean Boolean;
template <class T>
using Enum = oatpp::data::mapping::type::Enum<T>;
public:
/**
@ -209,123 +243,184 @@ public:
public:
template<typename T>
oatpp::String convertParameterToString(const oatpp::String& typeName, const T& parameter) {
struct TypeInterpretation {
(void) parameter;
static oatpp::String toString(const oatpp::String& typeName, const T& parameter) {
OATPP_LOGE("[oatpp::web::client::ApiClient::convertParameterToString()]",
"Error. No conversion from '%s' to '%s' is defined.", typeName->getData(), "oatpp::String");
throw std::runtime_error("[oatpp::web::client::ApiClient::convertParameterToString()]: Error. "
"No conversion from '" + typeName->std_str() + "' to 'oatpp::String' is defined. "
"Please define type conversion.");
}
(void) parameter;
OATPP_LOGE("[oatpp::web::client::ApiClient::TypeInterpretation::toString()]",
"Error. No conversion from '%s' to '%s' is defined.", typeName->getData(), "oatpp::String");
throw std::runtime_error(
"[oatpp::web::client::ApiClient::TypeInterpretation::toString()]: Error. "
"No conversion from '" + typeName->std_str() + "' to 'oatpp::String' is defined. "
"Please define type conversion."
);
}
};
};
template<>
inline oatpp::String ApiClient::convertParameterToString(const oatpp::String& typeName, const oatpp::String& parameter) {
(void) typeName;
return parameter;
}
struct ApiClient::TypeInterpretation<oatpp::String> {
static oatpp::String toString(const oatpp::String &typeName, const oatpp::String &parameter) {
(void) typeName;
return parameter;
}
};
template<>
inline oatpp::String ApiClient::convertParameterToString(const oatpp::String& typeName, const oatpp::Int8& parameter) {
(void) typeName;
if(parameter) {
return utils::conversion::int32ToStr(parameter->getValue());
struct ApiClient::TypeInterpretation<oatpp::Int8> {
static oatpp::String toString(const oatpp::String &typeName, const oatpp::Int8 &parameter) {
(void) typeName;
if (parameter) {
return utils::conversion::int32ToStr(*parameter);
}
return nullptr;
}
return "nullptr";
}
};
template<>
inline oatpp::String ApiClient::convertParameterToString(const oatpp::String& typeName, const oatpp::UInt8& parameter) {
(void) typeName;
if(parameter) {
return utils::conversion::uint32ToStr(parameter->getValue());
struct ApiClient::TypeInterpretation<oatpp::UInt8> {
static oatpp::String toString(const oatpp::String &typeName, const oatpp::UInt8 &parameter) {
(void) typeName;
if (parameter) {
return utils::conversion::uint32ToStr(*parameter);
}
return nullptr;
}
return "nullptr";
}
};
template<>
inline oatpp::String ApiClient::convertParameterToString(const oatpp::String& typeName, const oatpp::Int16& parameter) {
(void) typeName;
if(parameter) {
return utils::conversion::int32ToStr(parameter->getValue());
struct ApiClient::TypeInterpretation<oatpp::Int16> {
static oatpp::String toString(const oatpp::String &typeName, const oatpp::Int16 &parameter) {
(void) typeName;
if (parameter) {
return utils::conversion::int32ToStr(*parameter);
}
return nullptr;
}
return "nullptr";
}
};
template<>
inline oatpp::String ApiClient::convertParameterToString(const oatpp::String& typeName, const oatpp::UInt16& parameter) {
(void) typeName;
if(parameter) {
return utils::conversion::uint32ToStr(parameter->getValue());
struct ApiClient::TypeInterpretation<oatpp::UInt16> {
static oatpp::String toString(const oatpp::String &typeName, const oatpp::UInt16 &parameter) {
(void) typeName;
if (parameter) {
return utils::conversion::uint32ToStr(*parameter);
}
return nullptr;
}
return "nullptr";
}
};
template<>
inline oatpp::String ApiClient::convertParameterToString(const oatpp::String& typeName, const oatpp::Int32& parameter) {
(void) typeName;
if(parameter) {
return utils::conversion::int32ToStr(parameter->getValue());
struct ApiClient::TypeInterpretation<oatpp::Int32> {
static oatpp::String toString(const oatpp::String &typeName, const oatpp::Int32 &parameter) {
(void) typeName;
if (parameter) {
return utils::conversion::int32ToStr(*parameter);
}
return nullptr;
}
return "nullptr";
}
};
template<>
inline oatpp::String ApiClient::convertParameterToString(const oatpp::String& typeName, const oatpp::UInt32& parameter) {
(void) typeName;
if(parameter) {
return utils::conversion::uint32ToStr(parameter->getValue());
struct ApiClient::TypeInterpretation<oatpp::UInt32> {
static oatpp::String toString(const oatpp::String &typeName, const oatpp::UInt32 &parameter) {
(void) typeName;
if (parameter) {
return utils::conversion::uint32ToStr(*parameter);
}
return nullptr;
}
return "nullptr";
}
};
template<>
inline oatpp::String ApiClient::convertParameterToString(const oatpp::String& typeName, const oatpp::Int64& parameter) {
(void) typeName;
if(parameter) {
return utils::conversion::int64ToStr(parameter->getValue());
struct ApiClient::TypeInterpretation<oatpp::Int64> {
static oatpp::String toString(const oatpp::String &typeName, const oatpp::Int64 &parameter) {
(void) typeName;
if (parameter) {
return utils::conversion::int64ToStr(*parameter);
}
return nullptr;
}
return "nullptr";
}
};
template<>
inline oatpp::String ApiClient::convertParameterToString(const oatpp::String& typeName, const oatpp::UInt64& parameter) {
(void) typeName;
if(parameter) {
return utils::conversion::uint64ToStr(parameter->getValue());
struct ApiClient::TypeInterpretation<oatpp::UInt64> {
static oatpp::String toString(const oatpp::String &typeName, const oatpp::UInt64 &parameter) {
(void) typeName;
if (parameter) {
return utils::conversion::uint64ToStr(*parameter);
}
return nullptr;
}
return "nullptr";
}
};
template<>
inline oatpp::String ApiClient::convertParameterToString(const oatpp::String& typeName, const oatpp::Float32& parameter) {
(void) typeName;
if(parameter) {
return utils::conversion::float32ToStr(parameter->getValue());
struct ApiClient::TypeInterpretation<oatpp::Float32> {
static oatpp::String toString(const oatpp::String &typeName, const oatpp::Float32 &parameter) {
(void) typeName;
if (parameter) {
return utils::conversion::float32ToStr(*parameter);
}
return nullptr;
}
return "nullptr";
}
};
template<>
inline oatpp::String ApiClient::convertParameterToString(const oatpp::String& typeName, const oatpp::Float64& parameter) {
(void) typeName;
if(parameter) {
return utils::conversion::float64ToStr(parameter->getValue());
struct ApiClient::TypeInterpretation<oatpp::Float64> {
static oatpp::String toString(const oatpp::String &typeName, const oatpp::Float64 &parameter) {
(void) typeName;
if (parameter) {
return utils::conversion::float64ToStr(*parameter);
}
return nullptr;
}
return "nullptr";
}
};
template<>
inline oatpp::String ApiClient::convertParameterToString(const oatpp::String& typeName, const oatpp::Boolean& parameter) {
(void) typeName;
if(parameter) {
return utils::conversion::boolToStr(parameter->getValue());
struct ApiClient::TypeInterpretation<oatpp::Boolean> {
static oatpp::String toString(const oatpp::String &typeName, const oatpp::Boolean &parameter) {
(void) typeName;
if (parameter) {
return utils::conversion::boolToStr(*parameter);
}
return nullptr;
}
return "nullptr";
}
};
template<class T, class I>
struct ApiClient::TypeInterpretation<data::mapping::type::EnumObjectWrapper<T, I>> {
typedef data::mapping::type::EnumObjectWrapper<T, I> EnumOW;
typedef typename I::UnderlyingTypeObjectWrapper UTOW;
static oatpp::String toString(const oatpp::String &typeName, const EnumOW &parameter) {
data::mapping::type::EnumInterpreterError error = data::mapping::type::EnumInterpreterError::OK;
const auto& value = I::toInterpretation(parameter, error);
switch(error){
case data::mapping::type::EnumInterpreterError::OK: break;
case data::mapping::type::EnumInterpreterError::CONSTRAINT_NOT_NULL:
throw std::runtime_error(
"[oatpp::web::client::ApiClient::TypeInterpretation::toString()]: Error. Enum constraint violation - NotNull."
);
default:
throw std::runtime_error(
"[oatpp::web::client::ApiClient::TypeInterpretation::toString()]: Error. Can't interpret Enum."
);
}
return ApiClient::TypeInterpretation<UTOW>::toString(typeName, value.template staticCast<UTOW>());
}
};
}}}

View File

@ -735,7 +735,7 @@ namespace std {
struct hash<oatpp::web::protocol::http::Status> {
typedef oatpp::web::protocol::http::Status argument_type;
typedef v_uint32 result_type;
typedef v_uint64 result_type;
result_type operator()(oatpp::web::protocol::http::Status const& s) const noexcept {
return s.code;

View File

@ -199,22 +199,9 @@ public:
* @return DTO
*/
template<class Type>
typename Type::ObjectWrapper readBodyToDto(data::mapping::ObjectMapper* objectMapper) const {
typename Type::__Wrapper readBodyToDto(data::mapping::ObjectMapper* objectMapper) const {
return objectMapper->readFromString<Type>(m_bodyDecoder->decodeToString(m_headers, m_bodyStream.get()));
}
/**
* Transfer body to String and parse it as DTO
* (used in ApiController's codegens)
* @tparam Type
* @param objectMapper
* @return DTO
*/
template<class Type>
void readBodyToDto(data::mapping::type::PolymorphicWrapper<Type>& objectWrapper,
data::mapping::ObjectMapper* objectMapper) const {
objectWrapper = objectMapper->readFromString<Type>(m_bodyDecoder->decodeToString(m_headers, m_bodyStream.get()));
}
// Async
@ -246,7 +233,7 @@ public:
* @return - &id:oatpp::async::CoroutineStarterForResult;.
*/
template<class DtoType>
oatpp::async::CoroutineStarterForResult<const typename DtoType::ObjectWrapper&>
oatpp::async::CoroutineStarterForResult<const typename DtoType::__Wrapper&>
readBodyToDtoAsync(const std::shared_ptr<oatpp::data::mapping::ObjectMapper>& objectMapper) const {
return m_bodyDecoder->decodeToDtoAsync<DtoType>(m_headers, m_bodyStream, objectMapper);
}

View File

@ -35,7 +35,7 @@ ResponseFactory::createResponse(const Status& status, const oatpp::String& text)
std::shared_ptr<Response>
ResponseFactory::createResponse(const Status& status,
const data::mapping::type::AbstractObjectWrapper& dto,
const oatpp::Void& dto,
const std::shared_ptr<data::mapping::ObjectMapper>& objectMapper) {
return Response::createShared(status, BufferBody::createShared(
objectMapper->writeToString(dto),

View File

@ -55,7 +55,7 @@ public:
* @return - `std::shared_ptr` to &id:oatpp::web::protocol::http::outgoing::Response;.
*/
static std::shared_ptr<Response> createResponse(const Status& status,
const data::mapping::type::AbstractObjectWrapper& dto,
const oatpp::Void& dto,
const std::shared_ptr<data::mapping::ObjectMapper>& objectMapper);
};

View File

@ -95,13 +95,13 @@ std::shared_ptr<ApiController::OutgoingResponse> ApiController::createResponse(c
}
std::shared_ptr<ApiController::OutgoingResponse> ApiController::createDtoResponse(const Status& status,
const oatpp::data::mapping::type::AbstractObjectWrapper& dto,
const oatpp::Void& dto,
const std::shared_ptr<oatpp::data::mapping::ObjectMapper>& objectMapper) const {
return ResponseFactory::createResponse(status, dto, objectMapper);
}
std::shared_ptr<ApiController::OutgoingResponse> ApiController::createDtoResponse(const Status& status,
const oatpp::data::mapping::type::AbstractObjectWrapper& dto) const {
const oatpp::Void& dto) const {
return ResponseFactory::createResponse(status, dto, m_defaultObjectMapper);
}

View File

@ -126,62 +126,62 @@ public:
/**
* Convenience typedef for &id:oatpp::data::mapping::type::String;.
*/
typedef oatpp::data::mapping::type::String String;
typedef oatpp::String String;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::Int8;.
*/
typedef oatpp::data::mapping::type::Int8 Int8;
typedef oatpp::Int8 Int8;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::UInt8;.
*/
typedef oatpp::data::mapping::type::UInt8 UInt8;
typedef oatpp::UInt8 UInt8;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::Int16;.
*/
typedef oatpp::data::mapping::type::Int16 Int16;
typedef oatpp::Int16 Int16;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::UInt16;.
*/
typedef oatpp::data::mapping::type::UInt16 UInt16;
typedef oatpp::UInt16 UInt16;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::Int32;.
*/
typedef oatpp::data::mapping::type::Int32 Int32;
typedef oatpp::Int32 Int32;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::UInt32;.
*/
typedef oatpp::data::mapping::type::UInt32 UInt32;
typedef oatpp::UInt32 UInt32;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::Int64;.
*/
typedef oatpp::data::mapping::type::Int64 Int64;
typedef oatpp::Int64 Int64;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::UInt64;.
*/
typedef oatpp::data::mapping::type::UInt64 UInt64;
typedef oatpp::UInt64 UInt64;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::Float32;.
*/
typedef oatpp::data::mapping::type::Float32 Float32;
typedef oatpp::Float32 Float32;
/**
* Convenience typedef for &id:atpp::data::mapping::type::Float64;.
*/
typedef oatpp::data::mapping::type::Float64 Float64;
typedef oatpp::Float64 Float64;
/**
* Convenience typedef for &id:oatpp::data::mapping::type::Boolean;.
*/
typedef oatpp::data::mapping::type::Boolean Boolean;
typedef oatpp::Boolean Boolean;
/*
* Convenience typedef for std::function<std::shared_ptr<Endpoint::Info>()>.
@ -189,9 +189,13 @@ public:
typedef std::function<std::shared_ptr<Endpoint::Info>()> EndpointInfoBuilder;
template <class T>
using List = oatpp::data::mapping::type::List<T>;
using List = oatpp::List<T>;
template <class Value>
using Fields = oatpp::data::mapping::type::ListMap<String, Value>;
using Fields = oatpp::Fields<Value>;
template <class T>
using Enum = oatpp::data::mapping::type::Enum<T>;
protected:
@ -440,99 +444,148 @@ public:
const oatpp::String& str) const;
std::shared_ptr<OutgoingResponse> createDtoResponse(const Status& status,
const oatpp::data::mapping::type::AbstractObjectWrapper& dto,
const oatpp::Void& dto,
const std::shared_ptr<oatpp::data::mapping::ObjectMapper>& objectMapper) const;
std::shared_ptr<OutgoingResponse> createDtoResponse(const Status& status,
const oatpp::data::mapping::type::AbstractObjectWrapper& dto) const;
const oatpp::Void& dto) const;
public:
template<typename T>
T parseParameterFromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) text;
success = false;
OATPP_LOGE("[oatpp::web::server::api::ApiController::parseParameterFromString()]",
"Error. No conversion from '%s' to '%s' is defined.", "oatpp::String", typeName->getData());
throw std::runtime_error("[oatpp::web::server::api::ApiController::parseParameterFromString()]: Error. "
"No conversion from 'oatpp::String' to '" + typeName->std_str() + "' is defined. "
"Please define type conversion.");
}
struct TypeInterpretation {
static T fromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) text;
success = false;
OATPP_LOGE("[oatpp::web::server::api::ApiController::TypeInterpretation::fromString()]",
"Error. No conversion from '%s' to '%s' is defined.", "oatpp::String", typeName->getData());
throw std::runtime_error("[oatpp::web::server::api::ApiController::TypeInterpretation::fromString()]: Error. "
"No conversion from 'oatpp::String' to '" + typeName->std_str() + "' is defined. "
"Please define type conversion.");
}
};
};
template<>
inline oatpp::String ApiController::parseParameterFromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
success = true;
return text;
}
struct ApiController::TypeInterpretation <oatpp::String> {
static oatpp::String fromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
success = true;
return text;
}
};
template<>
inline oatpp::Int8 ApiController::parseParameterFromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToInt32(text, success);
}
struct ApiController::TypeInterpretation <oatpp::Int8> {
static oatpp::Int8 fromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToInt32(text, success);
}
};
template<>
inline oatpp::UInt8 ApiController::parseParameterFromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToUInt32(text, success);
}
struct ApiController::TypeInterpretation <oatpp::UInt8> {
static oatpp::UInt8 fromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToUInt32(text, success);
}
};
template<>
inline oatpp::Int16 ApiController::parseParameterFromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToInt32(text, success);
}
struct ApiController::TypeInterpretation <oatpp::Int16> {
static oatpp::Int16 fromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToInt32(text, success);
}
};
template<>
inline oatpp::UInt16 ApiController::parseParameterFromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToUInt32(text, success);
}
struct ApiController::TypeInterpretation <oatpp::UInt16> {
static oatpp::UInt16 fromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToUInt32(text, success);
}
};
template<>
inline oatpp::Int32 ApiController::parseParameterFromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToInt32(text, success);
}
struct ApiController::TypeInterpretation <oatpp::Int32> {
static oatpp::Int32 fromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToInt32(text, success);
}
};
template<>
inline oatpp::UInt32 ApiController::parseParameterFromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToUInt32(text, success);
}
struct ApiController::TypeInterpretation <oatpp::UInt32> {
static oatpp::UInt32 fromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToUInt32(text, success);
}
};
template<>
inline oatpp::Int64 ApiController::parseParameterFromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToInt64(text, success);
}
struct ApiController::TypeInterpretation <oatpp::Int64> {
static oatpp::Int64 fromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToInt64(text, success);
}
};
template<>
inline oatpp::UInt64 ApiController::parseParameterFromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToUInt64(text, success);
}
struct ApiController::TypeInterpretation <oatpp::UInt64> {
static oatpp::UInt64 fromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToUInt64(text, success);
}
};
template<>
inline oatpp::Float32 ApiController::parseParameterFromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToFloat32(text, success);
}
struct ApiController::TypeInterpretation <oatpp::Float32> {
static oatpp::Float32 fromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToFloat32(text, success);
}
};
template<>
inline oatpp::Float64 ApiController::parseParameterFromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToFloat64(text, success);
}
struct ApiController::TypeInterpretation <oatpp::Float64> {
static oatpp::Float64 fromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToFloat64(text, success);
}
};
template<>
inline oatpp::Boolean ApiController::parseParameterFromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToBool(text, success);
}
struct ApiController::TypeInterpretation <oatpp::Boolean> {
static oatpp::Boolean fromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
(void) typeName;
return utils::conversion::strToBool(text, success);
}
};
template<class T, class I>
struct ApiController::TypeInterpretation <data::mapping::type::EnumObjectWrapper<T, I>> {
typedef data::mapping::type::EnumObjectWrapper<T, I> EnumOW;
typedef typename I::UnderlyingTypeObjectWrapper UTOW;
static EnumOW fromString(const oatpp::String& typeName, const oatpp::String& text, bool& success) {
const auto& parsedValue = ApiController::TypeInterpretation<UTOW>::fromString(typeName, text, success);
if(success) {
data::mapping::type::EnumInterpreterError error = data::mapping::type::EnumInterpreterError::OK;
const auto& result = I::fromInterpretation(parsedValue, error);
if(error == data::mapping::type::EnumInterpreterError::OK) {
return result.template staticCast<EnumOW>();
}
success = false;
}
return nullptr;
}
};
}}}}

View File

@ -96,7 +96,7 @@ public:
*/
template<class T>
Param& add(const oatpp::String& name) {
return add(name, T::Class::getType());
return add(name, T::__Wrapper::Class::getType());
}
/**
@ -220,7 +220,7 @@ public:
*/
template<class T>
void addConsumes(const oatpp::String& contentType) {
consumes.push_back({contentType, T::Class::getType()});
consumes.push_back({contentType, T::__Wrapper::Class::getType()});
}
/**
@ -232,7 +232,7 @@ public:
*/
template<class T>
void addResponse(const oatpp::web::protocol::http::Status& status, const oatpp::String& contentType, const oatpp::String& responseDescription = oatpp::String()) {
responses[status] = {contentType, T::Class::getType(), responseDescription.get() == nullptr ? status.description : responseDescription};
responses[status] = {contentType, T::__Wrapper::Class::getType(), responseDescription.get() == nullptr ? status.description : responseDescription};
}
/**

View File

@ -5,8 +5,6 @@ add_executable(oatppAllTests
oatpp/core/async/LockTest.hpp
oatpp/core/base/CommandLineArgumentsTest.cpp
oatpp/core/base/CommandLineArgumentsTest.hpp
oatpp/core/base/RegRuleTest.cpp
oatpp/core/base/RegRuleTest.hpp
oatpp/core/base/collection/LinkedListTest.cpp
oatpp/core/base/collection/LinkedListTest.hpp
oatpp/core/base/memory/MemoryPoolTest.cpp
@ -15,8 +13,30 @@ add_executable(oatppAllTests
oatpp/core/base/memory/PerfTest.hpp
oatpp/core/data/buffer/ProcessorTest.cpp
oatpp/core/data/buffer/ProcessorTest.hpp
oatpp/core/data/mapping/type/AnyTest.cpp
oatpp/core/data/mapping/type/AnyTest.hpp
oatpp/core/data/mapping/type/EnumTest.cpp
oatpp/core/data/mapping/type/EnumTest.hpp
oatpp/core/data/mapping/type/ListTest.cpp
oatpp/core/data/mapping/type/ListTest.hpp
oatpp/core/data/mapping/type/ObjectTest.cpp
oatpp/core/data/mapping/type/ObjectTest.hpp
oatpp/core/data/mapping/type/ObjectWrapperTest.cpp
oatpp/core/data/mapping/type/ObjectWrapperTest.hpp
oatpp/core/data/mapping/type/PairListTest.cpp
oatpp/core/data/mapping/type/PairListTest.hpp
oatpp/core/data/mapping/type/PrimitiveTest.cpp
oatpp/core/data/mapping/type/PrimitiveTest.hpp
oatpp/core/data/mapping/type/StringTest.cpp
oatpp/core/data/mapping/type/StringTest.hpp
oatpp/core/data/mapping/type/TypeTest.cpp
oatpp/core/data/mapping/type/TypeTest.hpp
oatpp/core/data/mapping/type/UnorderedMapTest.cpp
oatpp/core/data/mapping/type/UnorderedMapTest.hpp
oatpp/core/data/mapping/type/UnorderedSetTest.cpp
oatpp/core/data/mapping/type/UnorderedSetTest.hpp
oatpp/core/data/mapping/type/VectorTest.cpp
oatpp/core/data/mapping/type/VectorTest.hpp
oatpp/core/data/share/LazyStringMapTest.cpp
oatpp/core/data/share/LazyStringMapTest.hpp
oatpp/core/data/share/MemoryLabelTest.cpp
@ -45,6 +65,10 @@ add_executable(oatppAllTests
oatpp/parser/json/mapping/DTOMapperTest.hpp
oatpp/parser/json/mapping/DeserializerTest.cpp
oatpp/parser/json/mapping/DeserializerTest.hpp
oatpp/parser/json/mapping/EnumTest.cpp
oatpp/parser/json/mapping/EnumTest.hpp
oatpp/parser/json/mapping/UnorderedSetTest.cpp
oatpp/parser/json/mapping/UnorderedSetTest.hpp
oatpp/web/protocol/http/encoding/ChunkedTest.cpp
oatpp/web/protocol/http/encoding/ChunkedTest.hpp
oatpp/web/mime/multipart/StatefulParserTest.cpp

View File

@ -30,6 +30,8 @@
#include "oatpp/parser/json/mapping/DeserializerTest.hpp"
#include "oatpp/parser/json/mapping/DTOMapperPerfTest.hpp"
#include "oatpp/parser/json/mapping/DTOMapperTest.hpp"
#include "oatpp/parser/json/mapping/EnumTest.hpp"
#include "oatpp/parser/json/mapping/UnorderedSetTest.hpp"
#include "oatpp/encoding/UnicodeTest.hpp"
#include "oatpp/encoding/Base64Test.hpp"
@ -38,12 +40,23 @@
#include "oatpp/core/parser/CaretTest.hpp"
#include "oatpp/core/data/mapping/type/UnorderedMapTest.hpp"
#include "oatpp/core/data/mapping/type/PairListTest.hpp"
#include "oatpp/core/data/mapping/type/VectorTest.hpp"
#include "oatpp/core/data/mapping/type/UnorderedSetTest.hpp"
#include "oatpp/core/data/mapping/type/ListTest.hpp"
#include "oatpp/core/data/mapping/type/ObjectTest.hpp"
#include "oatpp/core/data/mapping/type/StringTest.hpp"
#include "oatpp/core/data/mapping/type/PrimitiveTest.hpp"
#include "oatpp/core/data/mapping/type/ObjectWrapperTest.hpp"
#include "oatpp/core/data/mapping/type/TypeTest.hpp"
#include "oatpp/core/data/mapping/type/AnyTest.hpp"
#include "oatpp/core/data/mapping/type/EnumTest.hpp"
#include "oatpp/core/base/collection/LinkedListTest.hpp"
#include "oatpp/core/base/memory/MemoryPoolTest.hpp"
#include "oatpp/core/base/memory/PerfTest.hpp"
#include "oatpp/core/base/CommandLineArgumentsTest.hpp"
#include "oatpp/core/base/RegRuleTest.hpp"
#include "oatpp/core/async/Coroutine.hpp"
#include "oatpp/core/Types.hpp"
@ -64,7 +77,6 @@ void runTests() {
OATPP_LOGD("aaa", "coroutine size=%d", sizeof(oatpp::async::AbstractCoroutine));
OATPP_LOGD("aaa", "action size=%d", sizeof(oatpp::async::Action));
OATPP_RUN_TEST(oatpp::test::base::RegRuleTest);
OATPP_RUN_TEST(oatpp::test::base::CommandLineArgumentsTest);
OATPP_RUN_TEST(oatpp::test::memory::MemoryPoolTest);
@ -81,15 +93,30 @@ void runTests() {
OATPP_RUN_TEST(oatpp::test::core::data::stream::ChunkedBufferTest);
OATPP_RUN_TEST(oatpp::test::core::data::stream::BufferStreamTest);
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::ObjectWrapperTest);
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::TypeTest);
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::StringTest);
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::PrimitiveTest);
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::ListTest);
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::VectorTest);
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::UnorderedSetTest);
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::PairListTest);
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::UnorderedMapTest);
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::AnyTest);
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::EnumTest);
OATPP_RUN_TEST(oatpp::test::core::data::mapping::type::ObjectTest);
OATPP_RUN_TEST(oatpp::test::async::LockTest);
OATPP_RUN_TEST(oatpp::test::parser::CaretTest);
OATPP_RUN_TEST(oatpp::test::parser::json::mapping::EnumTest);
OATPP_RUN_TEST(oatpp::test::parser::json::mapping::UnorderedSetTest);
OATPP_RUN_TEST(oatpp::test::parser::json::mapping::DeserializerTest);
OATPP_RUN_TEST(oatpp::test::parser::json::mapping::DTOMapperPerfTest);
OATPP_RUN_TEST(oatpp::test::parser::json::mapping::DTOMapperTest);
OATPP_RUN_TEST(oatpp::test::encoding::Base64Test);

View File

@ -1,158 +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 "RegRuleTest.hpp"
#include "oatpp/core/data/mapping/type/Primitive.hpp"
#include "oatpp/core/Types.hpp"
#include <unordered_map>
namespace oatpp { namespace test { namespace base {
namespace {
class BaseClass : public oatpp::base::Countable {
public:
template<class T>
static T create1() {
return new BaseClass();
}
template<class T>
static T create2() {
return T(new BaseClass());
}
};
class ChildClass : public BaseClass {
public:
template<class T>
static T create1() {
return new ChildClass();
}
template<class T>
static T create2() {
return T(new ChildClass());
}
};
typedef oatpp::String String;
template<typename T>
using ObjectWrapper = oatpp::data::mapping::type::PolymorphicWrapper<T>;
template<typename T>
using PolymorphicWrapper = oatpp::data::mapping::type::PolymorphicWrapper<T>;
template<typename T>
using TypeObjectWrapper = oatpp::data::mapping::type::ObjectWrapper<T, oatpp::data::mapping::type::__class::Void>;
typedef oatpp::data::mapping::type::Int32 Int32;
typedef oatpp::data::mapping::type::Int64 Int64;
typedef oatpp::data::mapping::type::Float32 Float32;
typedef oatpp::data::mapping::type::Float64 Float64;
typedef oatpp::data::mapping::type::Boolean Boolean;
}
void RegRuleTest::onRun() {
{
String reg1("");
String reg2(reg1);
OATPP_ASSERT(reg1);
String reg3(std::move(reg1));
OATPP_ASSERT(!reg1);
String reg4 = String(100);
}
{
String reg1("");
String reg2(reg1);
OATPP_ASSERT(reg1);
String reg3(std::move(reg1));
OATPP_ASSERT(!reg1);
String reg4 = String(100) + "Leonid";
}
{
String reg1 = String(100);
String reg2(reg1);
OATPP_ASSERT(reg1);
String reg3(std::move(reg1));
OATPP_ASSERT(!reg1);
}
{
String reg1(String(100) + "Leonid");
String reg2(reg1);
OATPP_ASSERT(reg1);
String reg3(std::move(reg1));
OATPP_ASSERT(!reg1);
String reg4 = String(100);
}
{
String reg1 = String(100);
String reg2(reg1);
OATPP_ASSERT(reg1);
String reg3(std::move(reg1));
OATPP_ASSERT(!reg1);
}
{
String reg1 = String(100);
String reg2(reg1);
OATPP_ASSERT(reg1);
String reg3(std::move(reg1));
OATPP_ASSERT(!reg1);
}
{
String reg1 = String(100);
String reg2(reg1);
OATPP_ASSERT(reg1);
String reg3(std::move(reg1));
OATPP_ASSERT(!reg1);
}
std::unordered_map<String, String> map;
map["str_1"] = "val_1";
map["str_2"] = "val_2";
map["str_3"] = "val_3";
OATPP_ASSERT(map.find("str_1")->second == "val_1");
OATPP_ASSERT(map.find("str_2")->second == "val_2");
OATPP_ASSERT(map.find("str_3")->second == "val_3");
}
}}}

View File

@ -0,0 +1,183 @@
/***************************************************************************
*
* 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 "AnyTest.hpp"
#include "oatpp/core/data/mapping/type/Any.hpp"
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
#include "oatpp/core/macro/codegen.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
namespace {
#include OATPP_CODEGEN_BEGIN(DTO)
class Dto1 : public oatpp::Object {
DTO_INIT(Dto1, Object);
};
class Dto2 : public oatpp::Object {
DTO_INIT(Dto2, Object);
};
class Test : public oatpp::Object {
DTO_INIT(Test, Object);
DTO_FIELD(oatpp::Any, any);
};
#include OATPP_CODEGEN_END(DTO)
}
void AnyTest::onRun() {
{
OATPP_LOGI(TAG, "Test default constructor...");
oatpp::Any any;
OATPP_ASSERT(!any);
OATPP_ASSERT(any.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any.getStoredType() == nullptr);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test nullptr constructor...");
oatpp::Any any(nullptr);
OATPP_ASSERT(!any);
OATPP_ASSERT(any.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any.getStoredType() == nullptr);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test retrieve()...");
oatpp::Any any(oatpp::String("Hello Any!"));
OATPP_ASSERT(any);
OATPP_ASSERT(any.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any.getStoredType() == oatpp::data::mapping::type::__class::String::getType());
auto str = any.retrieve<oatpp::String>();
OATPP_ASSERT(str == "Hello Any!");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test store()...");
oatpp::Any any(oatpp::Int32(32));
OATPP_ASSERT(any);
OATPP_ASSERT(any.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any.getStoredType() == oatpp::data::mapping::type::__class::Int32::getType());
any.store(oatpp::String("Hello Any!"));
OATPP_ASSERT(any);
OATPP_ASSERT(any.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any.getStoredType() == oatpp::data::mapping::type::__class::String::getType());
auto str = any.retrieve<oatpp::String>();
OATPP_ASSERT(str == "Hello Any!");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test retrieve() class check...");
oatpp::Any any(Dto1::createShared());
OATPP_ASSERT(any);
OATPP_ASSERT(any.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any.getStoredType() == Dto1::ObjectWrapper::Class::getType());
bool wasError = false;
try {
auto obj = any.retrieve<Dto2>(); // wrong object
} catch (std::runtime_error& e) {
wasError = true;
}
OATPP_ASSERT(wasError);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test copy-assign operator...");
oatpp::Any any1(oatpp::String("Hello!"));
oatpp::Any any2;
any2 = any1;
OATPP_ASSERT(any1);
OATPP_ASSERT(any2);
OATPP_ASSERT(any1.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any2.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any1.getStoredType() == oatpp::data::mapping::type::__class::String::getType());
OATPP_ASSERT(any2.getStoredType() == oatpp::data::mapping::type::__class::String::getType());
OATPP_ASSERT(any1 == any2);
OATPP_ASSERT(any1.getPtr().get() != any2.getPtr().get());
auto str1 = any1.retrieve<oatpp::String>();
auto str2 = any2.retrieve<oatpp::String>();
OATPP_ASSERT(str1 == str2);
OATPP_ASSERT(str1.get() == str2.get() && str1 == "Hello!");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test move-assign operator...");
oatpp::Any any1(oatpp::String("Hello!"));
oatpp::Any any2;
any2 = std::move(any1);
OATPP_ASSERT(!any1);
OATPP_ASSERT(any2);
OATPP_ASSERT(any1.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any2.valueType == oatpp::data::mapping::type::__class::Any::getType());
OATPP_ASSERT(any1.getStoredType() == nullptr);
OATPP_ASSERT(any2.getStoredType() == oatpp::data::mapping::type::__class::String::getType());
OATPP_ASSERT(any1 != any2);
OATPP_ASSERT(any1.getPtr().get() != any2.getPtr().get());
auto str1 = any1.retrieve<oatpp::String>();
auto str2 = any2.retrieve<oatpp::String>();
OATPP_ASSERT(str1 != str2);
OATPP_ASSERT(str2 == "Hello!");
OATPP_LOGI(TAG, "OK");
}
}
}}}}}}

View File

@ -0,0 +1,42 @@
/***************************************************************************
*
* 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 oatpp_test_core_data_mapping_type_AnyTest_hpp
#define oatpp_test_core_data_mapping_type_AnyTest_hpp
#include "oatpp-test/UnitTest.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
class AnyTest : public UnitTest{
public:
AnyTest():UnitTest("TEST[core::data::mapping::type::AnyTest]"){}
void onRun() override;
};
}}}}}}
#endif /* oatpp_test_core_data_mapping_type_AnyTest_hpp */

View File

@ -0,0 +1,300 @@
/***************************************************************************
*
* 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 "EnumTest.hpp"
#include "oatpp/core/Types.hpp"
#include "oatpp/core/macro/codegen.hpp"
#include <unordered_map>
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
#include OATPP_CODEGEN_BEGIN(DTO)
ENUM(Enum0, v_int32)
ENUM(Enum1, v_int32,
VALUE(V1, 1),
VALUE(V2, 2),
VALUE(V3, 3)
)
ENUM(Enum2, v_int32,
VALUE(NAME_1, 1, "name-1"),
VALUE(NAME_2, 2, "name-2"),
VALUE(NAME_3, 3, "name-3")
)
ENUM(Enum3, v_int32,
VALUE(V_1, 1, "v-1", "description_1"),
VALUE(V_2, 2, "v-2", "description_2"),
VALUE(V_3, 3, "v-3", "description_3")
)
#include OATPP_CODEGEN_END(DTO)
void EnumTest::onRun() {
{
OATPP_LOGI(TAG, "Check Hash...");
{
auto v = std::hash<oatpp::Enum<Enum1>>{}(oatpp::Enum<Enum1>());
OATPP_ASSERT(v == 0);
}
{
auto v = std::hash<oatpp::Enum<Enum1>>{}(oatpp::Enum<Enum1>(Enum1::V1));
OATPP_ASSERT(v == 1);
}
{
auto v = std::hash<oatpp::Enum<Enum1>>{}(oatpp::Enum<Enum1>(Enum1::V2));
OATPP_ASSERT(v == 2);
}
{
auto v = std::hash<oatpp::Enum<Enum1>>{}(oatpp::Enum<Enum1>(Enum1::V3));
OATPP_ASSERT(v == 3);
}
std::unordered_map<oatpp::Enum<Enum1>, oatpp::String> map({
{Enum1::V1, "v1"},
{Enum1::V2, "v2"},
{Enum1::V3, "v3"},
});
OATPP_ASSERT(map.size() == 3);
OATPP_ASSERT(map[Enum1::V1] == "v1");
OATPP_ASSERT(map[Enum1::V2] == "v2");
OATPP_ASSERT(map[Enum1::V3] == "v3");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Check Meta...");
{
const auto &entries = oatpp::Enum<Enum0>::getEntries();
OATPP_ASSERT(entries.size() == 0);
}
{
const auto &v = oatpp::Enum<Enum1>::getEntries();
OATPP_ASSERT(v.size() == 3);
OATPP_ASSERT(v[0].index == 0 && v[0].name == "V1" && v[0].value == Enum1::V1 && v[0].description == nullptr);
OATPP_ASSERT(v[1].index == 1 && v[1].name == "V2" && v[1].value == Enum1::V2 && v[1].description == nullptr);
OATPP_ASSERT(v[2].index == 2 && v[2].name == "V3" && v[2].value == Enum1::V3 && v[2].description == nullptr);
}
{
const auto &v = oatpp::Enum<Enum2>::getEntries();
OATPP_ASSERT(v.size() == 3);
OATPP_ASSERT(v[0].index == 0 && v[0].name == "name-1" && v[0].value == Enum2::NAME_1 && v[0].description == nullptr);
OATPP_ASSERT(v[1].index == 1 && v[1].name == "name-2" && v[1].value == Enum2::NAME_2 && v[1].description == nullptr);
OATPP_ASSERT(v[2].index == 2 && v[2].name == "name-3" && v[2].value == Enum2::NAME_3 && v[2].description == nullptr);
}
{
const auto &v = oatpp::Enum<Enum3>::getEntries();
OATPP_ASSERT(v.size() == 3);
OATPP_ASSERT(v[0].index == 0 && v[0].name == "v-1" && v[0].value == Enum3::V_1 && v[0].description == "description_1");
OATPP_ASSERT(v[1].index == 1 && v[1].name == "v-2" && v[1].value == Enum3::V_2 && v[1].description == "description_2");
OATPP_ASSERT(v[2].index == 2 && v[2].name == "v-3" && v[2].value == Enum3::V_3 && v[2].description == "description_3");
}
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Declaration...");
OATPP_ASSERT(oatpp::Enum<Enum2>::Interpreter::notNull == false);
OATPP_ASSERT(oatpp::Enum<Enum2>::NotNull::Interpreter::notNull == true);
OATPP_ASSERT(oatpp::Enum<Enum2>::AsString::Interpreter::notNull == false);
OATPP_ASSERT(oatpp::Enum<Enum2>::AsString::NotNull::Interpreter::notNull == true);
OATPP_ASSERT(oatpp::Enum<Enum2>::AsNumber::Interpreter::notNull == false);
OATPP_ASSERT(oatpp::Enum<Enum2>::AsNumber::NotNull::Interpreter::notNull == true);
OATPP_ASSERT(oatpp::Enum<Enum2>::NotNull::AsString::Interpreter::notNull == true);
OATPP_ASSERT(oatpp::Enum<Enum2>::NotNull::AsNumber::Interpreter::notNull == true);
auto pd1 = static_cast<const oatpp::data::mapping::type::__class::AbstractEnum::AbstractPolymorphicDispatcher*>(
oatpp::Enum<Enum2>::Class::getType()->polymorphicDispatcher
);
auto pd2 = static_cast<const oatpp::data::mapping::type::__class::AbstractEnum::AbstractPolymorphicDispatcher*>(
oatpp::Enum<Enum2>::NotNull::Class::getType()->polymorphicDispatcher
);
OATPP_ASSERT(pd1->notNull == false);
OATPP_ASSERT(pd2->notNull == true);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test Interpreter AsString...");
oatpp::data::mapping::type::EnumInterpreterError e = oatpp::data::mapping::type::EnumInterpreterError::OK;
auto inter = oatpp::Enum<Enum2>::AsString::Interpreter::toInterpretation(oatpp::Enum<Enum2>::AsString(Enum2::NAME_1), e);
OATPP_ASSERT(inter.valueType == oatpp::String::Class::getType());
OATPP_ASSERT(e == oatpp::data::mapping::type::EnumInterpreterError::OK);
auto interValue = inter.staticCast<oatpp::String>();
OATPP_ASSERT(interValue == "name-1");
oatpp::Void voidValue = oatpp::Enum<Enum2>::AsString::Interpreter::fromInterpretation(interValue, e);
OATPP_ASSERT(voidValue.valueType == oatpp::Enum<Enum2>::AsString::Class::getType());
OATPP_ASSERT(e == oatpp::data::mapping::type::EnumInterpreterError::OK);
auto value = voidValue.staticCast<oatpp::Enum<Enum2>::AsString>();
OATPP_ASSERT(value == Enum2::NAME_1);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test Interpreter AsNumber...");
oatpp::data::mapping::type::EnumInterpreterError e = oatpp::data::mapping::type::EnumInterpreterError::OK;
auto inter = oatpp::Enum<Enum2>::AsNumber::Interpreter::toInterpretation(oatpp::Enum<Enum2>::AsNumber(Enum2::NAME_1), e);
OATPP_ASSERT(inter.valueType == oatpp::Int32::Class::getType());
OATPP_ASSERT(e == oatpp::data::mapping::type::EnumInterpreterError::OK);
auto interValue = inter.staticCast<oatpp::Int32>();
OATPP_ASSERT(interValue == static_cast<v_int32>(Enum2::NAME_1));
oatpp::Void voidValue = oatpp::Enum<Enum2>::AsNumber::Interpreter::fromInterpretation(interValue, e);
OATPP_ASSERT(voidValue.valueType == oatpp::Enum<Enum2>::AsNumber::Class::getType());
OATPP_ASSERT(e == oatpp::data::mapping::type::EnumInterpreterError::OK);
auto value = voidValue.staticCast<oatpp::Enum<Enum2>::AsNumber>();
OATPP_ASSERT(value == Enum2::NAME_1);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test default constructors and == operators...");
oatpp::Enum<Enum2>::AsString e1;
oatpp::Enum<Enum2>::AsString e2;
OATPP_ASSERT(!e1);
OATPP_ASSERT(e1 == nullptr);
OATPP_ASSERT(e1 == e2);
OATPP_ASSERT(e2 == e1);
oatpp::Enum<Enum2>::NotNull e3;
OATPP_ASSERT(e1 == e3);
OATPP_ASSERT(e3 == e1);
oatpp::Enum<Enum2>::AsNumber::NotNull e4;
OATPP_ASSERT(e1 == e4);
OATPP_ASSERT(e4 == e1);
OATPP_ASSERT(e1.valueType != e4.valueType); // Types are not equal because interpreters are different
OATPP_ASSERT(e1.valueType->classId.id == e4.valueType->classId.id); // But classId is the same
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test value constructor and == operators...");
oatpp::Enum<Enum2> e1(Enum2::NAME_1);
oatpp::Enum<Enum2> e2(Enum2::NAME_1);
oatpp::Enum<Enum2> e3;
OATPP_ASSERT(e1);
OATPP_ASSERT(e1 != nullptr);
OATPP_ASSERT(e1 == e2);
OATPP_ASSERT(e1 != e3);
OATPP_ASSERT(e3 != e1);
OATPP_ASSERT(e1 == Enum2::NAME_1);
OATPP_ASSERT(e1 != Enum2::NAME_2);
OATPP_ASSERT(e3 != Enum2::NAME_1);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test copy-assignment operator...");
oatpp::Enum<Enum2>::AsString e1;
oatpp::Enum<Enum2>::AsNumber e2(Enum2::NAME_1);
Enum2 ve;
OATPP_ASSERT(e1.valueType == oatpp::Enum<Enum2>::AsString::Class::getType());
OATPP_ASSERT(e2.valueType == oatpp::Enum<Enum2>::AsNumber::Class::getType());
OATPP_ASSERT(e1.valueType != e2.valueType);
e1 = e2;
OATPP_ASSERT(e1.valueType == oatpp::Enum<Enum2>::AsString::Class::getType());
OATPP_ASSERT(e2.valueType == oatpp::Enum<Enum2>::AsNumber::Class::getType());
OATPP_ASSERT(e1.valueType != e2.valueType);
OATPP_ASSERT(e1 == e2);
OATPP_ASSERT(e2 == e1);
OATPP_ASSERT(e1.get() == e2.get());
e1 = Enum2::NAME_2;
OATPP_ASSERT(e1 != e2);
OATPP_ASSERT(e2 != e1);
OATPP_ASSERT(e1.get() != e2.get());
OATPP_ASSERT(e1 == Enum2::NAME_2);
OATPP_ASSERT(e2 == Enum2::NAME_1);
ve = e1;
OATPP_ASSERT(ve == Enum2::NAME_2);
ve = e2;
OATPP_ASSERT(ve == Enum2::NAME_1);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test move-assignment operator...");
oatpp::Enum<Enum2>::AsString e1;
oatpp::Enum<Enum2>::AsNumber e2(Enum2::NAME_1);
e1 = std::move(e2);
OATPP_ASSERT(e1);
OATPP_ASSERT(!e2);
OATPP_ASSERT(e1 == Enum2::NAME_1);
OATPP_LOGI(TAG, "OK");
}
}
}}}}}}

View File

@ -0,0 +1,42 @@
/***************************************************************************
*
* 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 oatpp_test_core_data_mapping_type_EnumTest_hpp
#define oatpp_test_core_data_mapping_type_EnumTest_hpp
#include "oatpp-test/UnitTest.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
class EnumTest : public UnitTest{
public:
EnumTest():UnitTest("TEST[core::data::mapping::type::EnumTest]"){}
void onRun() override;
};
}}}}}}
#endif /* oatpp_test_core_data_mapping_type_EnumTest_hpp */

View File

@ -0,0 +1,160 @@
/***************************************************************************
*
* 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 "ListTest.hpp"
#include "oatpp/core/Types.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
void ListTest::onRun() {
{
OATPP_LOGI(TAG, "test default constructor...");
oatpp::List<oatpp::String> list;
OATPP_ASSERT(!list);
OATPP_ASSERT(list == nullptr);
OATPP_ASSERT(list.get() == nullptr);
OATPP_ASSERT(list.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractList::CLASS_ID.id);
OATPP_ASSERT(list.valueType->params.size() == 1);
OATPP_ASSERT(list.valueType->params.front() == oatpp::String::Class::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test empty ilist constructor...");
oatpp::List<oatpp::String> list({});
OATPP_ASSERT(list);
OATPP_ASSERT(list != nullptr);
OATPP_ASSERT(list->size() == 0);
OATPP_ASSERT(list.get() != nullptr);
OATPP_ASSERT(list.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractList::CLASS_ID.id);
OATPP_ASSERT(list.valueType->params.size() == 1);
OATPP_ASSERT(list.valueType->params.front() == oatpp::String::Class::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test createShared()...");
oatpp::List<oatpp::String> list = oatpp::List<oatpp::String>::createShared();
OATPP_ASSERT(list);
OATPP_ASSERT(list != nullptr);
OATPP_ASSERT(list->size() == 0);
OATPP_ASSERT(list.get() != nullptr);
OATPP_ASSERT(list.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractList::CLASS_ID.id);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test copy-assignment operator...");
oatpp::List<oatpp::String> list1({});
oatpp::List<oatpp::String> list2;
list2 = list1;
OATPP_ASSERT(list1);
OATPP_ASSERT(list2);
OATPP_ASSERT(list1->size() == 0);
OATPP_ASSERT(list2->size() == 0);
OATPP_ASSERT(list1.get() == list2.get());
list2->push_back("a");
OATPP_ASSERT(list1->size() == 1);
OATPP_ASSERT(list2->size() == 1);
list2 = {"b", "c"};
OATPP_ASSERT(list1->size() == 1);
OATPP_ASSERT(list2->size() == 2);
OATPP_ASSERT(list2[0] == "b");
OATPP_ASSERT(list2[1] == "c");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test move-assignment operator...");
oatpp::List<oatpp::String> list1({});
oatpp::List<oatpp::String> list2;
list2 = std::move(list1);
OATPP_ASSERT(!list1);
OATPP_ASSERT(list2);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test get element by index...");
oatpp::List<oatpp::String> list = {"a", "b", "c"};
OATPP_ASSERT(list);
OATPP_ASSERT(list != nullptr);
OATPP_ASSERT(list->size() == 3);
OATPP_ASSERT(list[0] == "a");
OATPP_ASSERT(list[1] == "b");
OATPP_ASSERT(list[2] == "c");
list[1] = "Hello!";
OATPP_ASSERT(list->size() == 3);
OATPP_ASSERT(list[0] == "a");
OATPP_ASSERT(list[1] == "Hello!");
OATPP_ASSERT(list[2] == "c");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test polymorphicDispatcher...");
oatpp::List<oatpp::String> list = {"a", "b", "c"};
auto polymorphicDispatcher = static_cast<const typename oatpp::List<oatpp::String>::Class::AbstractPolymorphicDispatcher*>(
list.valueType->polymorphicDispatcher
);
polymorphicDispatcher->addPolymorphicItem(list, oatpp::String("d"));
OATPP_ASSERT(list->size() == 4);
OATPP_ASSERT(list[0] == "a");
OATPP_ASSERT(list[1] == "b");
OATPP_ASSERT(list[2] == "c");
OATPP_ASSERT(list[3] == "d");
OATPP_LOGI(TAG, "OK");
}
}
}}}}}}

View File

@ -0,0 +1,42 @@
/***************************************************************************
*
* 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 oatpp_test_core_data_mapping_type_ListTest_hpp
#define oatpp_test_core_data_mapping_type_ListTest_hpp
#include "oatpp-test/UnitTest.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
class ListTest : public UnitTest{
public:
ListTest():UnitTest("TEST[core::data::mapping::type::ListTest]"){}
void onRun() override;
};
}}}}}}
#endif /* oatpp_test_core_data_mapping_type_ListTest_hpp */

View File

@ -0,0 +1,301 @@
/***************************************************************************
*
* 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 "ObjectTest.hpp"
#include "oatpp/core/macro/codegen.hpp"
#include "oatpp/core/Types.hpp"
#include "oatpp-test/Checker.hpp"
#include <thread>
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
namespace {
#include OATPP_CODEGEN_BEGIN(DTO)
class Dto0 : public oatpp::Object {
DTO_INIT(Dto0, Object)
};
class DtoA : public oatpp::Object {
DTO_INIT(DtoA, Object)
DTO_FIELD_INFO(id) {
info->description = "identifier";
}
DTO_FIELD(String, id) = "Some default id";
DTO_HC_EQ(id)
public:
DtoA(const String& pId)
: id(pId)
{}
};
class DtoB : public DtoA {
DTO_INIT(DtoB, DtoA)
DTO_FIELD_INFO(a) {
info->description = "some field with a qualified name";
}
DTO_FIELD(String, a, "field-a") = "default-value";
};
class DtoC : public DtoA {
DTO_INIT(DtoC, DtoA)
DTO_FIELD(String, a);
DTO_FIELD(String, b);
DTO_FIELD(String, c);
DTO_HC_EQ(a, b, c);
};
#include OATPP_CODEGEN_END(DTO)
void runDtoInitializations() {
for(v_int32 i = 0; i < 1000; i ++) {
auto dto = DtoB::createShared();
}
}
void runDtoInitializetionsInThreads() {
std::list<std::thread> threads;
for(v_int32 i = 0; i < 500; i++) {
threads.push_back(std::thread(runDtoInitializations));
}
for(auto& t : threads) {
t.join();
}
}
}
void ObjectTest::onRun() {
{
oatpp::test::PerformanceChecker timer("DTO - Initializations.");
runDtoInitializetionsInThreads();
}
{
auto dto = DtoA::createShared("id1");
OATPP_ASSERT(dto->id == "id1");
}
{
OATPP_LOGI(TAG, "Test Meta 1...");
auto type = DtoA::ObjectWrapper::Class::getType();
const auto& propsMap = type->propertiesGetter()->getMap();
OATPP_ASSERT(propsMap.size() == 1);
auto it = propsMap.find("id");
OATPP_ASSERT(it != propsMap.end());
OATPP_ASSERT(it->second->info.description == "identifier");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test Meta 2...");
auto type = DtoB::ObjectWrapper::Class::getType();
const auto& propsMap = type->propertiesGetter()->getMap();
OATPP_ASSERT(propsMap.size() == 2);
{
auto it = propsMap.find("id");
OATPP_ASSERT("id" && it != propsMap.end());
OATPP_ASSERT(it->second->info.description == "identifier");
}
{
auto it = propsMap.find("field-a");
OATPP_ASSERT("field-a" && it != propsMap.end());
OATPP_ASSERT(it->second->info.description == "some field with a qualified name");
}
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test 1...");
DtoA::ObjectWrapper a;
OATPP_ASSERT(!a);
OATPP_ASSERT(a == nullptr);
OATPP_ASSERT(a.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractObject::CLASS_ID.id);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test 2...");
DtoA::ObjectWrapper a;
DtoA::ObjectWrapper b;
OATPP_ASSERT(a == b);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test 3...");
auto a = DtoA::createShared();
DtoA::ObjectWrapper b;
OATPP_ASSERT(a != b);
OATPP_ASSERT(b != a);
auto ohc = a->hashCode();
auto whc = std::hash<DtoA::ObjectWrapper>{}(a);
OATPP_ASSERT(ohc == whc);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test 4...");
auto a = Dto0::createShared();
auto b = Dto0::createShared();
OATPP_ASSERT(a != b);
OATPP_ASSERT(a->hashCode() != b->hashCode());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test 5...");
auto a = DtoA::createShared();
auto b = DtoA::createShared();
OATPP_ASSERT(a == b);
OATPP_ASSERT(a->hashCode() == b->hashCode());
a->id = "hello";
OATPP_ASSERT(a != b);
OATPP_ASSERT(a->hashCode() != b->hashCode());
b->id = "hello";
OATPP_ASSERT(a == b);
OATPP_ASSERT(a->hashCode() == b->hashCode());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test 6...");
auto a = DtoB::createShared();
auto b = DtoB::createShared();
OATPP_ASSERT(a->a == "default-value");
OATPP_ASSERT(b->a == "default-value");
a->a = "value1"; // value that is ignored in HC & EQ
a->a = "value2"; // value that is ignored in HC & EQ
OATPP_ASSERT(a == b);
OATPP_ASSERT(a->hashCode() == b->hashCode());
a->id = "hello";
OATPP_ASSERT(a != b);
OATPP_ASSERT(a->hashCode() != b->hashCode());
b->id = "hello";
OATPP_ASSERT(a == b);
OATPP_ASSERT(a->hashCode() == b->hashCode());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test 7...");
auto a = DtoC::createShared();
auto b = DtoC::createShared();
a->id = "1";
b->id = "2";
OATPP_ASSERT(a != b);
OATPP_ASSERT(a->hashCode() != b->hashCode());
a->id = "2";
OATPP_ASSERT(a == b);
OATPP_ASSERT(a->hashCode() == b->hashCode());
a->c = "a";
OATPP_ASSERT(a != b);
OATPP_ASSERT(a->hashCode() != b->hashCode());
b->c = "a";
OATPP_ASSERT(a == b);
OATPP_ASSERT(a->hashCode() == b->hashCode());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test 8...");
auto a = DtoB::createShared();
auto b = DtoB::createShared();
auto c = DtoB::createShared();
auto d = DtoB::createShared();
auto e = DtoB::createShared();
a->a = "1";
b->a = "2";
c->a = "3";
d->a = "4";
e->a = "5";
a->id = "1";
e->id = "1";
oatpp::UnorderedSet<DtoB> set = {a, b, c, d, e};
OATPP_ASSERT(set->size() == 2);
OATPP_ASSERT(set[a] == true);
OATPP_ASSERT(set[b] == true);
OATPP_ASSERT(set[c] == true);
OATPP_ASSERT(set[d] == true);
OATPP_ASSERT(set[e] == true);
OATPP_LOGI(TAG, "OK");
}
}
}}}}}}

View File

@ -0,0 +1,42 @@
/***************************************************************************
*
* 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 oatpp_test_core_data_mapping_type_ObjectTest_hpp
#define oatpp_test_core_data_mapping_type_ObjectTest_hpp
#include "oatpp-test/UnitTest.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
class ObjectTest : public UnitTest{
public:
ObjectTest():UnitTest("TEST[core::data::mapping::type::ObjectTest]"){}
void onRun() override;
};
}}}}}}
#endif /* oatpp_test_core_data_mapping_type_ObjectTest_hpp */

View File

@ -0,0 +1,169 @@
/***************************************************************************
*
* 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 "ObjectWrapperTest.hpp"
#include "oatpp/core/Types.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
namespace {
template<class T, class Clazz = oatpp::data::mapping::type::__class::Void>
using ObjectWrapper = oatpp::data::mapping::type::ObjectWrapper<T, Clazz>;
}
void ObjectWrapperTest::onRun() {
{
OATPP_LOGI(TAG, "Check default valueType is assigned (default tparam Clazz)...");
ObjectWrapper<base::StrBuffer> pw;
OATPP_ASSERT(!pw);
OATPP_ASSERT(pw == nullptr);
OATPP_ASSERT(pw.valueType == oatpp::data::mapping::type::__class::Void::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Check default valueType is assigned (specified tparam Clazz)...");
ObjectWrapper<base::StrBuffer, oatpp::data::mapping::type::__class::String> pw;
OATPP_ASSERT(!pw);
OATPP_ASSERT(pw == nullptr);
OATPP_ASSERT(pw.valueType == oatpp::data::mapping::type::__class::String::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Check valueType is assigned from constructor...");
ObjectWrapper<base::StrBuffer> pw(oatpp::data::mapping::type::__class::String::getType());
OATPP_ASSERT(!pw);
OATPP_ASSERT(pw == nullptr);
OATPP_ASSERT(pw.valueType == oatpp::data::mapping::type::__class::String::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Check valueType is assigned from copy constructor...");
ObjectWrapper<base::StrBuffer> pw1(oatpp::data::mapping::type::__class::String::getType());
ObjectWrapper<base::StrBuffer> pw2(pw1);
OATPP_ASSERT(pw2.valueType == oatpp::data::mapping::type::__class::String::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Check valueType is assigned from move constructor...");
ObjectWrapper<base::StrBuffer> pw1(oatpp::data::mapping::type::__class::String::getType());
ObjectWrapper<base::StrBuffer> pw2(std::move(pw1));
OATPP_ASSERT(pw2.valueType == oatpp::data::mapping::type::__class::String::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Check valueType is NOT assigned from copy-assign operator...");
ObjectWrapper<base::StrBuffer> pw1(oatpp::data::mapping::type::__class::String::getType());
ObjectWrapper<base::StrBuffer> pw2;
pw2 = pw1;
OATPP_ASSERT(pw2.valueType == oatpp::data::mapping::type::__class::Void::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Check valueType is NOT assigned from move-assign operator...");
ObjectWrapper<base::StrBuffer> pw1(oatpp::data::mapping::type::__class::String::getType());
ObjectWrapper<base::StrBuffer> pw2;
pw2 = std::move(pw1);
OATPP_ASSERT(pw2.valueType == oatpp::data::mapping::type::__class::Void::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Check copy-assign operator. Check == operator...");
ObjectWrapper<base::StrBuffer> pw1;
OATPP_ASSERT(!pw1);
OATPP_ASSERT(pw1 == nullptr);
OATPP_ASSERT(pw1.valueType == oatpp::data::mapping::type::__class::Void::getType());
ObjectWrapper<base::StrBuffer> pw2 = base::StrBuffer::createShared("Hello!");
OATPP_ASSERT(pw2);
OATPP_ASSERT(pw2 != nullptr);
OATPP_ASSERT(pw2.valueType == oatpp::data::mapping::type::__class::Void::getType());
pw1 = pw2;
OATPP_ASSERT(pw1);
OATPP_ASSERT(pw1 != nullptr);
OATPP_ASSERT(pw2);
OATPP_ASSERT(pw2 != nullptr);
OATPP_ASSERT(pw1 == pw2);
OATPP_ASSERT(pw1.get() == pw2.get());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Check != operator...");
ObjectWrapper<base::StrBuffer, oatpp::data::mapping::type::__class::String> pw1(base::StrBuffer::createShared("Hello!"));
OATPP_ASSERT(pw1);
OATPP_ASSERT(pw1 != nullptr);
OATPP_ASSERT(pw1.valueType == oatpp::data::mapping::type::__class::String::getType());
ObjectWrapper<base::StrBuffer, oatpp::data::mapping::type::__class::String> pw2(base::StrBuffer::createShared("Hello!"));
OATPP_ASSERT(pw2);
OATPP_ASSERT(pw2 != nullptr);
OATPP_ASSERT(pw2.valueType == oatpp::data::mapping::type::__class::String::getType());
OATPP_ASSERT(pw1 != pw2);
OATPP_ASSERT(pw1.get() != pw2.get());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Check move-assign operator. Check != operator...");
ObjectWrapper<base::StrBuffer> pw1;
OATPP_ASSERT(!pw1);
OATPP_ASSERT(pw1 == nullptr);
OATPP_ASSERT(pw1.valueType == oatpp::data::mapping::type::__class::Void::getType());
ObjectWrapper<base::StrBuffer> pw2 = base::StrBuffer::createShared("Hello!");
OATPP_ASSERT(pw2);
OATPP_ASSERT(pw2 != nullptr);
OATPP_ASSERT(pw2.valueType == oatpp::data::mapping::type::__class::Void::getType());
pw1 = std::move(pw2);
OATPP_ASSERT(pw1);
OATPP_ASSERT(pw1 != nullptr);
OATPP_ASSERT(!pw2);
OATPP_ASSERT(pw2 == nullptr);
OATPP_ASSERT(pw1 != pw2);
OATPP_ASSERT(pw1.get() != pw2.get());
OATPP_LOGI(TAG, "OK");
}
}
}}}}}}

View File

@ -0,0 +1,42 @@
/***************************************************************************
*
* 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 oatpp_test_core_data_mapping_type_ObjectWrapperTest_hpp
#define oatpp_test_core_data_mapping_type_ObjectWrapperTest_hpp
#include "oatpp-test/UnitTest.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
class ObjectWrapperTest : public UnitTest{
public:
ObjectWrapperTest():UnitTest("TEST[core::data::mapping::type::ObjectWrapperTest]"){}
void onRun() override;
};
}}}}}}
#endif /* oatpp_test_core_data_mapping_type_ObjectWrapperTest_hpp */

View File

@ -0,0 +1,164 @@
/***************************************************************************
*
* 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 "PairListTest.hpp"
#include "oatpp/core/Types.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
void PairListTest::onRun() {
{
OATPP_LOGI(TAG, "test default constructor...");
oatpp::Fields<String> map;
OATPP_ASSERT(!map);
OATPP_ASSERT(map == nullptr);
OATPP_ASSERT(map.get() == nullptr);
OATPP_ASSERT(map.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractPairList::CLASS_ID.id);
OATPP_ASSERT(map.valueType->params.size() == 2);
auto it = map.valueType->params.begin();
OATPP_ASSERT(*it++ == oatpp::String::Class::getType());
OATPP_ASSERT(*it++ == oatpp::String::Class::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test empty ilist constructor...");
oatpp::Fields<String> map({});
OATPP_ASSERT(map);
OATPP_ASSERT(map != nullptr);
OATPP_ASSERT(map->size() == 0);
OATPP_ASSERT(map.get() != nullptr);
OATPP_ASSERT(map.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractPairList::CLASS_ID.id);
OATPP_ASSERT(map.valueType->params.size() == 2);
auto it = map.valueType->params.begin();
OATPP_ASSERT(*it++ == oatpp::String::Class::getType());
OATPP_ASSERT(*it++ == oatpp::String::Class::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test createShared()...");
oatpp::Fields<String> map = oatpp::Fields<String>::createShared();
OATPP_ASSERT(map);
OATPP_ASSERT(map != nullptr);
OATPP_ASSERT(map->size() == 0);
OATPP_ASSERT(map.get() != nullptr);
OATPP_ASSERT(map.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractPairList::CLASS_ID.id);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test copy-assignment operator...");
oatpp::Fields<String> map1({});
oatpp::Fields<String> map2;
map2 = map1;
OATPP_ASSERT(map1);
OATPP_ASSERT(map2);
OATPP_ASSERT(map1->size() == 0);
OATPP_ASSERT(map2->size() == 0);
OATPP_ASSERT(map1.get() == map2.get());
map2->push_back({"key", "a"});
OATPP_ASSERT(map1->size() == 1);
OATPP_ASSERT(map2->size() == 1);
map2 = {{"key1", "b"}, {"key2", "c"}};
OATPP_ASSERT(map1->size() == 1);
OATPP_ASSERT(map2->size() == 2);
OATPP_ASSERT(map2["key1"] == "b");
OATPP_ASSERT(map2["key2"] == "c");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test move-assignment operator...");
oatpp::Fields<String> map1({});
oatpp::Fields<String> map2;
map2 = std::move(map1);
OATPP_ASSERT(!map1);
OATPP_ASSERT(map2);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test get element by index...");
oatpp::Fields<String> map = {{"key1", "a"}, {"key2", "b"}, {"key3", "c"}};
OATPP_ASSERT(map);
OATPP_ASSERT(map != nullptr);
OATPP_ASSERT(map->size() == 3);
OATPP_ASSERT(map["key1"] == "a");
OATPP_ASSERT(map["key2"] == "b");
OATPP_ASSERT(map["key3"] == "c");
map["key2"] = "Hello!";
OATPP_ASSERT(map->size() == 3);
OATPP_ASSERT(map["key1"] == "a");
OATPP_ASSERT(map["key2"] == "Hello!");
OATPP_ASSERT(map["key3"] == "c");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test polymorphicDispatcher...");
oatpp::Fields<String> map = {{"key1", "a"}, {"key2", "b"}, {"key3", "c"}};
auto polymorphicDispatcher = static_cast<const typename oatpp::Fields<String>::Class::AbstractPolymorphicDispatcher*>(
map.valueType->polymorphicDispatcher
);
polymorphicDispatcher->addPolymorphicItem(map, oatpp::String("key1"), oatpp::String("d"));
OATPP_ASSERT(map->size() == 4);
OATPP_ASSERT(map[0].first == "key1" && map[0].second == "a");
OATPP_ASSERT(map[1].first == "key2" && map[1].second == "b");
OATPP_ASSERT(map[2].first == "key3" && map[2].second == "c");
OATPP_ASSERT(map[3].first == "key1" && map[3].second == "d");
OATPP_LOGI(TAG, "OK");
}
}
}}}}}}

View File

@ -0,0 +1,42 @@
/***************************************************************************
*
* 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 oatpp_test_core_data_mapping_type_PairListTest_hpp
#define oatpp_test_core_data_mapping_type_PairListTest_hpp
#include "oatpp-test/UnitTest.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
class PairListTest : public UnitTest{
public:
PairListTest():UnitTest("TEST[core::data::mapping::type::PairListTest]"){}
void onRun() override;
};
}}}}}}
#endif /* oatpp_test_core_data_mapping_type_PairListTest_hpp */

View File

@ -0,0 +1,249 @@
/***************************************************************************
*
* 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 "PrimitiveTest.hpp"
#include "oatpp/core/Types.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
namespace {
template<class T>
void checkHash(const T& val) {
auto h = std::hash<T>{}(val);
OATPP_LOGI("HASH", "type='%s', hash=%llu", val.valueType->classId.name, h);
}
}
void PrimitiveTest::onRun() {
{
checkHash(oatpp::Boolean(true));
checkHash(oatpp::Int8(0xFF));
checkHash(oatpp::UInt8(0xFF));
checkHash(oatpp::Int16(0xFFFF));
checkHash(oatpp::UInt16(0xFFFF));
checkHash(oatpp::Int32(0xFFFFFFFF));
checkHash(oatpp::UInt32(0xFFFFFFFF));
checkHash(oatpp::Int64(0xFFFFFFFFFFFFFFFF));
checkHash(oatpp::UInt64(0xFFFFFFFFFFFFFFFF));
checkHash(oatpp::Float32(0.2));
checkHash(oatpp::Float64(0.2));
}
{
OATPP_LOGI(TAG, "test default constructor");
oatpp::Int32 i;
OATPP_ASSERT(!i);
OATPP_ASSERT(i == nullptr);
OATPP_ASSERT(i.valueType == oatpp::Int32::Class::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test value constructor");
oatpp::Int32 i(0);
OATPP_ASSERT(i);
OATPP_ASSERT(i != nullptr);
OATPP_ASSERT(i == 0);
OATPP_ASSERT(i.valueType == oatpp::Int32::Class::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test implicit value constructor");
oatpp::Int32 i = 0;
OATPP_ASSERT(i);
OATPP_ASSERT(i != nullptr);
OATPP_ASSERT(i == 0);
OATPP_ASSERT(i.valueType == oatpp::Int32::Class::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test '==' and '!=' operators");
oatpp::Int32 i1 = 0;
oatpp::Int32 i2;
OATPP_ASSERT(i1);
OATPP_ASSERT(i1 != nullptr);
OATPP_ASSERT(i1 == 0);
OATPP_ASSERT(i1 != 1);
OATPP_ASSERT(!i2);
OATPP_ASSERT(i2 == nullptr)
OATPP_ASSERT(i1 != i2);
OATPP_ASSERT(i2 != i1);
i2 = 0;
OATPP_ASSERT(i1 == i2);
OATPP_ASSERT(i2 == i1);
i1 = nullptr;
i2 = nullptr;
OATPP_ASSERT(i1 == i2);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test copy-assign operator");
oatpp::Int32 i1 = 0;
oatpp::Int32 i2;
OATPP_ASSERT(i1 != i2);
i2 = i1;
OATPP_ASSERT(i1 == i2);
OATPP_ASSERT(i1.get() == i2.get());
i2 = 1;
OATPP_ASSERT(i1 != i2);
OATPP_ASSERT(i1.get() != i2.get());
OATPP_ASSERT(i1 == 0);
OATPP_ASSERT(i2 == 1);
}
{
OATPP_LOGI(TAG, "test move-assign operator");
oatpp::Int32 i1 = 0;
oatpp::Int32 i2;
OATPP_ASSERT(i1 != i2);
i2 = std::move(i1);
OATPP_ASSERT(i1 == nullptr);
OATPP_ASSERT(i2 != nullptr);
OATPP_ASSERT(i2 == 0);
}
{
OATPP_LOGI(TAG, "test move-assign operator");
oatpp::Int32 i = 0;
v_int32 v = i;
OATPP_ASSERT(v == i);
}
{
OATPP_LOGI(TAG, "Test Boolean [nullptr]");
oatpp::Boolean b;
OATPP_ASSERT(!b);
OATPP_ASSERT(b == nullptr);
OATPP_ASSERT(b != false);
OATPP_ASSERT(b != true);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test Boolean nullptr constructor");
oatpp::Boolean b = nullptr;
OATPP_ASSERT(!b);
OATPP_ASSERT(b == nullptr);
OATPP_ASSERT(b != false);
OATPP_ASSERT(b != true);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test Boolean [false]");
oatpp::Boolean b = false;
OATPP_ASSERT(!b); // <--- still !b
OATPP_ASSERT(b != nullptr);
OATPP_ASSERT(b == false);
OATPP_ASSERT(b != true);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test Boolean [true]");
oatpp::Boolean b = true;
OATPP_ASSERT(b);
OATPP_ASSERT(b != nullptr);
OATPP_ASSERT(b != false);
OATPP_ASSERT(b == true);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test Boolean copy-assign operator");
oatpp::Boolean b1 = true;
oatpp::Boolean b2;
b2 = b1;
OATPP_ASSERT(b2);
OATPP_ASSERT(b1);
OATPP_ASSERT(b1 == b2);
OATPP_ASSERT(b1.get() == b2.get());
b2 = false;
OATPP_ASSERT(b1.get() != b2.get());
OATPP_ASSERT(b1 != b2);
OATPP_ASSERT(b2 != b1);
b1 = false;
b2 = nullptr;
OATPP_ASSERT(b1 != b2);
OATPP_ASSERT(b2 != b1);
b1 = nullptr;
b2 = nullptr;
OATPP_ASSERT(b1 == b2);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test Boolean move-assign operator");
oatpp::Boolean b1 = true;
oatpp::Boolean b2;
b2 = std::move(b1);
OATPP_ASSERT(b2 != nullptr);
OATPP_ASSERT(b1 == nullptr);
OATPP_LOGI(TAG, "OK");
}
}
}}}}}}

View File

@ -0,0 +1,42 @@
/***************************************************************************
*
* 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 oatpp_test_core_data_mapping_type_PrimitiveTest_hpp
#define oatpp_test_core_data_mapping_type_PrimitiveTest_hpp
#include "oatpp-test/UnitTest.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
class PrimitiveTest : public UnitTest{
public:
PrimitiveTest():UnitTest("TEST[core::data::mapping::type::PrimitiveTest]"){}
void onRun() override;
};
}}}}}}
#endif /* oatpp_test_core_data_mapping_type_PrimitiveTest_hpp */

View File

@ -0,0 +1,139 @@
/***************************************************************************
*
* 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 "StringTest.hpp"
#include "oatpp/core/Types.hpp"
#include <functional>
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
void StringTest::onRun() {
{
oatpp::String s = "hello"; // check hash function exists
std::hash<oatpp::String>{}(s);
}
{
OATPP_LOGI(TAG, "test default constructor");
oatpp::String s;
OATPP_ASSERT(!s);
OATPP_ASSERT(s == nullptr);
OATPP_ASSERT(s == (const char*) nullptr);
OATPP_ASSERT(s.valueType == oatpp::String::Class::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test const char* constructor");
oatpp::String s("");
OATPP_ASSERT(s);
OATPP_ASSERT(s != nullptr);
OATPP_ASSERT(s != (const char*) nullptr)
OATPP_ASSERT(s->getSize() == 0);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test const char* implicit constructor");
oatpp::String s = "";
OATPP_ASSERT(s);
OATPP_ASSERT(s != nullptr);
OATPP_ASSERT(s != (const char*) nullptr)
OATPP_ASSERT(s->getSize() == 0);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test '==', '!=' operators");
oatpp::String s1 = "a";
oatpp::String s2;
OATPP_ASSERT(s1 != s2);
OATPP_ASSERT(s2 != s1);
OATPP_ASSERT(s1 == "a");
OATPP_ASSERT(s1 != "aa");
OATPP_ASSERT(s1 != "");
s2 = "aa";
OATPP_ASSERT(s1 != s2);
OATPP_ASSERT(s2 != s1);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test copy-asssign operator");
oatpp::String s1 = "s1";
oatpp::String s2;
s2 = s1;
OATPP_ASSERT(s1 == s2);
OATPP_ASSERT(s1.get() == s2.get());
s1 = "s2";
OATPP_ASSERT(s1 != s2);
OATPP_ASSERT(s2 != s1);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test const char* assign operator");
oatpp::String s1 = "s1";
oatpp::String s2(s1);
OATPP_ASSERT(s1 == s2);
OATPP_ASSERT(s1.get() == s2.get());
s1 = "s2";
OATPP_ASSERT(s1 != s2);
OATPP_ASSERT(s2 != s1);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test move assign operator");
oatpp::String s1 = "s1";
oatpp::String s2;
s2 = std::move(s1);
OATPP_ASSERT(s1 == nullptr);
OATPP_ASSERT(s2 != nullptr);
OATPP_ASSERT(s2 == "s1");
OATPP_ASSERT(s1 != s2);
OATPP_ASSERT(s1.get() != s2.get());
OATPP_LOGI(TAG, "OK");
}
}
}}}}}}

View File

@ -0,0 +1,42 @@
/***************************************************************************
*
* 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 oatpp_test_core_data_mapping_type_StringTest_hpp
#define oatpp_test_core_data_mapping_type_StringTest_hpp
#include "oatpp-test/UnitTest.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
class StringTest : public UnitTest{
public:
StringTest():UnitTest("TEST[core::data::mapping::type::StringTest]"){}
void onRun() override;
};
}}}}}}
#endif /* oatpp_test_core_data_mapping_type_StringTest_hpp */

View File

@ -26,6 +26,7 @@
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
#include "oatpp/core/macro/codegen.hpp"
#include "oatpp/core/Types.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
@ -33,11 +34,9 @@ namespace {
#include OATPP_CODEGEN_BEGIN(DTO)
typedef oatpp::data::mapping::type::Object DTO;
class TestDto : public DTO {
class TestDto : public oatpp::Object {
DTO_INIT(TestDto, DTO);
DTO_INIT(TestDto, Object);
DTO_FIELD(String, field_string);
DTO_FIELD(Int8, field_int8);
@ -48,16 +47,16 @@ namespace {
DTO_FIELD(Float64, field_float64);
DTO_FIELD(Boolean, field_boolean);
DTO_FIELD(List<String>::ObjectWrapper, field_list_string);
DTO_FIELD(List<Int32>::ObjectWrapper, field_list_int32);
DTO_FIELD(List<Int64>::ObjectWrapper, field_list_int64);
DTO_FIELD(List<Float32>::ObjectWrapper, field_list_float32);
DTO_FIELD(List<Float64>::ObjectWrapper, field_list_float64);
DTO_FIELD(List<Boolean>::ObjectWrapper, field_list_boolean);
DTO_FIELD(List<String>, field_list_string);
DTO_FIELD(List<Int32>, field_list_int32);
DTO_FIELD(List<Int64>, field_list_int64);
DTO_FIELD(List<Float32>, field_list_float32);
DTO_FIELD(List<Float64>, field_list_float64);
DTO_FIELD(List<Boolean>, field_list_boolean);
DTO_FIELD(Fields<String>::ObjectWrapper, field_map_string_string);
DTO_FIELD(Fields<String>, field_map_string_string);
DTO_FIELD(TestDto::ObjectWrapper, obj1);
DTO_FIELD(TestDto, obj1);
};
@ -112,7 +111,7 @@ void TypeTest::onRun() {
OATPP_ASSERT(obj->field_list_boolean.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractList::CLASS_ID.id);
OATPP_LOGV(TAG, "type: '%s'", obj->field_map_string_string.valueType->classId.name);
OATPP_ASSERT(obj->field_map_string_string.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractListMap::CLASS_ID.id);
OATPP_ASSERT(obj->field_map_string_string.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractPairList::CLASS_ID.id);
OATPP_LOGV(TAG, "type: '%s'", obj->obj1.valueType->classId.name);
OATPP_ASSERT(obj->obj1.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractObject::CLASS_ID.id);

View File

@ -0,0 +1,163 @@
/***************************************************************************
*
* 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 "UnorderedMapTest.hpp"
#include "oatpp/core/Types.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
void UnorderedMapTest::onRun() {
{
OATPP_LOGI(TAG, "test default constructor...");
oatpp::UnorderedFields<String> map;
OATPP_ASSERT(!map);
OATPP_ASSERT(map == nullptr);
OATPP_ASSERT(map.get() == nullptr);
OATPP_ASSERT(map.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID.id);
OATPP_ASSERT(map.valueType->params.size() == 2);
auto it = map.valueType->params.begin();
OATPP_ASSERT(*it++ == oatpp::String::Class::getType());
OATPP_ASSERT(*it++ == oatpp::String::Class::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test empty ilist constructor...");
oatpp::UnorderedFields<String> map({});
OATPP_ASSERT(map);
OATPP_ASSERT(map != nullptr);
OATPP_ASSERT(map->size() == 0);
OATPP_ASSERT(map.get() != nullptr);
OATPP_ASSERT(map.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID.id);
OATPP_ASSERT(map.valueType->params.size() == 2);
auto it = map.valueType->params.begin();
OATPP_ASSERT(*it++ == oatpp::String::Class::getType());
OATPP_ASSERT(*it++ == oatpp::String::Class::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test createShared()...");
oatpp::UnorderedFields<String> map = oatpp::UnorderedFields<String>::createShared();
OATPP_ASSERT(map);
OATPP_ASSERT(map != nullptr);
OATPP_ASSERT(map->size() == 0);
OATPP_ASSERT(map.get() != nullptr);
OATPP_ASSERT(map.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID.id);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test copy-assignment operator...");
oatpp::UnorderedFields<String> map1({});
oatpp::UnorderedFields<String> map2;
map2 = map1;
OATPP_ASSERT(map1);
OATPP_ASSERT(map2);
OATPP_ASSERT(map1->size() == 0);
OATPP_ASSERT(map2->size() == 0);
OATPP_ASSERT(map1.get() == map2.get());
map2->insert({"key", "a"});
OATPP_ASSERT(map1->size() == 1);
OATPP_ASSERT(map2->size() == 1);
map2 = {{"key1", "b"}, {"key2", "c"}};
OATPP_ASSERT(map1->size() == 1);
OATPP_ASSERT(map2->size() == 2);
OATPP_ASSERT(map2["key1"] == "b");
OATPP_ASSERT(map2["key2"] == "c");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test move-assignment operator...");
oatpp::UnorderedFields<String> map1({});
oatpp::UnorderedFields<String> map2;
map2 = std::move(map1);
OATPP_ASSERT(!map1);
OATPP_ASSERT(map2);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test get element by index...");
oatpp::UnorderedFields<String> map = {{"key1", "a"}, {"key2", "b"}, {"key3", "c"}};
OATPP_ASSERT(map);
OATPP_ASSERT(map != nullptr);
OATPP_ASSERT(map->size() == 3);
OATPP_ASSERT(map["key1"] == "a");
OATPP_ASSERT(map["key2"] == "b");
OATPP_ASSERT(map["key3"] == "c");
map["key2"] = "Hello!";
OATPP_ASSERT(map->size() == 3);
OATPP_ASSERT(map["key1"] == "a");
OATPP_ASSERT(map["key2"] == "Hello!");
OATPP_ASSERT(map["key3"] == "c");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test polymorphicDispatcher...");
oatpp::UnorderedFields<String> map = {{"key1", "a"}, {"key2", "b"}, {"key3", "c"}};
auto polymorphicDispatcher = static_cast<const typename oatpp::UnorderedFields<String>::Class::AbstractPolymorphicDispatcher*>(
map.valueType->polymorphicDispatcher
);
polymorphicDispatcher->addPolymorphicItem(map, oatpp::String("key1"), oatpp::String("d"));
OATPP_ASSERT(map->size() == 3);
OATPP_ASSERT(map["key1"] == "d");
OATPP_ASSERT(map["key2"] == "b");
OATPP_ASSERT(map["key3"] == "c");
OATPP_LOGI(TAG, "OK");
}
}
}}}}}}

View File

@ -0,0 +1,42 @@
/***************************************************************************
*
* 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 oatpp_test_core_data_mapping_type_UnorderedMapTest_hpp
#define oatpp_test_core_data_mapping_type_UnorderedMapTest_hpp
#include "oatpp-test/UnitTest.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
class UnorderedMapTest : public UnitTest{
public:
UnorderedMapTest():UnitTest("TEST[core::data::mapping::type::UnorderedMapTest]"){}
void onRun() override;
};
}}}}}}
#endif /* oatpp_test_core_data_mapping_type_UnorderedMapTest_hpp */

View File

@ -0,0 +1,144 @@
/***************************************************************************
*
* 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 "UnorderedSetTest.hpp"
#include "oatpp/core/Types.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
void UnorderedSetTest::onRun() {
{
OATPP_LOGI(TAG, "test default constructor...");
oatpp::UnorderedSet<oatpp::String> set;
OATPP_ASSERT(!set);
OATPP_ASSERT(set == nullptr);
OATPP_ASSERT(set.get() == nullptr);
OATPP_ASSERT(set.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID.id);
OATPP_ASSERT(set.valueType->params.size() == 1);
OATPP_ASSERT(set.valueType->params.front() == oatpp::String::Class::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test empty ilist constructor...");
oatpp::UnorderedSet<oatpp::String> set({});
OATPP_ASSERT(set);
OATPP_ASSERT(set != nullptr);
OATPP_ASSERT(set->size() == 0);
OATPP_ASSERT(set.get() != nullptr);
OATPP_ASSERT(set.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID.id);
OATPP_ASSERT(set.valueType->params.size() == 1);
OATPP_ASSERT(set.valueType->params.front() == oatpp::String::Class::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test createShared()...");
oatpp::UnorderedSet<oatpp::String> set = oatpp::UnorderedSet<oatpp::String>::createShared();
OATPP_ASSERT(set);
OATPP_ASSERT(set != nullptr);
OATPP_ASSERT(set->size() == 0);
OATPP_ASSERT(set.get() != nullptr);
OATPP_ASSERT(set.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID.id);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test copy-assignment operator...");
oatpp::UnorderedSet<oatpp::String> set1({});
oatpp::UnorderedSet<oatpp::String> set2;
set2 = set1;
OATPP_ASSERT(set1);
OATPP_ASSERT(set2);
OATPP_ASSERT(set1->size() == 0);
OATPP_ASSERT(set2->size() == 0);
OATPP_ASSERT(set1.get() == set2.get());
set2->insert("a");
OATPP_ASSERT(set1->size() == 1);
OATPP_ASSERT(set2->size() == 1);
set2 = {"b", "c"};
OATPP_ASSERT(set1->size() == 1);
OATPP_ASSERT(set2->size() == 2);
OATPP_ASSERT(set2["b"] == true);
OATPP_ASSERT(set2["c"] == true);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test move-assignment operator...");
oatpp::UnorderedSet<oatpp::String> set1({});
oatpp::UnorderedSet<oatpp::String> set2;
set2 = std::move(set1);
OATPP_ASSERT(!set1);
OATPP_ASSERT(set2);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test polymorphicDispatcher...");
oatpp::UnorderedSet<oatpp::String> set = {"a", "b", "c"};
auto polymorphicDispatcher = static_cast<const typename oatpp::UnorderedSet<oatpp::String>::Class::AbstractPolymorphicDispatcher*>(
set.valueType->polymorphicDispatcher
);
polymorphicDispatcher->addPolymorphicItem(set, oatpp::String("a"));
polymorphicDispatcher->addPolymorphicItem(set, oatpp::String("b"));
polymorphicDispatcher->addPolymorphicItem(set, oatpp::String("c"));
polymorphicDispatcher->addPolymorphicItem(set, oatpp::String("d"));
OATPP_ASSERT(set->size() == 4);
OATPP_ASSERT(set["a"]);
OATPP_ASSERT(set["b"]);
OATPP_ASSERT(set["c"]);
OATPP_ASSERT(set["d"]);
OATPP_LOGI(TAG, "OK");
}
}
}}}}}}

View File

@ -0,0 +1,42 @@
/***************************************************************************
*
* 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 oatpp_test_core_data_mapping_type_UnorderedSetTest_hpp
#define oatpp_test_core_data_mapping_type_UnorderedSetTest_hpp
#include "oatpp-test/UnitTest.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
class UnorderedSetTest : public UnitTest{
public:
UnorderedSetTest():UnitTest("TEST[core::data::mapping::type::UnorderedSetTest]"){}
void onRun() override;
};
}}}}}}
#endif /* oatpp_test_core_data_mapping_type_UnorderedSetTest_hpp */

View File

@ -0,0 +1,160 @@
/***************************************************************************
*
* 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 "VectorTest.hpp"
#include "oatpp/core/Types.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
void VectorTest::onRun() {
{
OATPP_LOGI(TAG, "test default constructor...");
oatpp::Vector<oatpp::String> vector;
OATPP_ASSERT(!vector);
OATPP_ASSERT(vector == nullptr);
OATPP_ASSERT(vector.get() == nullptr);
OATPP_ASSERT(vector.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractVector::CLASS_ID.id);
OATPP_ASSERT(vector.valueType->params.size() == 1);
OATPP_ASSERT(vector.valueType->params.front() == oatpp::String::Class::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test empty ilist constructor...");
oatpp::Vector<oatpp::String> vector({});
OATPP_ASSERT(vector);
OATPP_ASSERT(vector != nullptr);
OATPP_ASSERT(vector->size() == 0);
OATPP_ASSERT(vector.get() != nullptr);
OATPP_ASSERT(vector.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractVector::CLASS_ID.id);
OATPP_ASSERT(vector.valueType->params.size() == 1);
OATPP_ASSERT(vector.valueType->params.front() == oatpp::String::Class::getType());
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test createShared()...");
oatpp::Vector<oatpp::String> vector = oatpp::Vector<oatpp::String>::createShared();
OATPP_ASSERT(vector);
OATPP_ASSERT(vector != nullptr);
OATPP_ASSERT(vector->size() == 0);
OATPP_ASSERT(vector.get() != nullptr);
OATPP_ASSERT(vector.valueType->classId.id == oatpp::data::mapping::type::__class::AbstractVector::CLASS_ID.id);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test copy-assignment operator...");
oatpp::Vector<oatpp::String> vector1({});
oatpp::Vector<oatpp::String> vector2;
vector2 = vector1;
OATPP_ASSERT(vector1);
OATPP_ASSERT(vector2);
OATPP_ASSERT(vector1->size() == 0);
OATPP_ASSERT(vector2->size() == 0);
OATPP_ASSERT(vector1.get() == vector2.get());
vector2->push_back("a");
OATPP_ASSERT(vector1->size() == 1);
OATPP_ASSERT(vector2->size() == 1);
vector2 = {"b", "c"};
OATPP_ASSERT(vector1->size() == 1);
OATPP_ASSERT(vector2->size() == 2);
OATPP_ASSERT(vector2[0] == "b");
OATPP_ASSERT(vector2[1] == "c");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test move-assignment operator...");
oatpp::Vector<oatpp::String> vector1({});
oatpp::Vector<oatpp::String> vector2;
vector2 = std::move(vector1);
OATPP_ASSERT(!vector1);
OATPP_ASSERT(vector2);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test get element by index...");
oatpp::Vector<oatpp::String> vector = {"a", "b", "c"};
OATPP_ASSERT(vector);
OATPP_ASSERT(vector != nullptr);
OATPP_ASSERT(vector->size() == 3);
OATPP_ASSERT(vector[0] == "a");
OATPP_ASSERT(vector[1] == "b");
OATPP_ASSERT(vector[2] == "c");
vector[1] = "Hello!";
OATPP_ASSERT(vector->size() == 3);
OATPP_ASSERT(vector[0] == "a");
OATPP_ASSERT(vector[1] == "Hello!");
OATPP_ASSERT(vector[2] == "c");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "test polymorphicDispatcher...");
oatpp::Vector<oatpp::String> vector = {"a", "b", "c"};
auto polymorphicDispatcher = static_cast<const typename oatpp::Vector<oatpp::String>::Class::AbstractPolymorphicDispatcher*>(
vector.valueType->polymorphicDispatcher
);
polymorphicDispatcher->addPolymorphicItem(vector, oatpp::String("d"));
OATPP_ASSERT(vector->size() == 4);
OATPP_ASSERT(vector[0] == "a");
OATPP_ASSERT(vector[1] == "b");
OATPP_ASSERT(vector[2] == "c");
OATPP_ASSERT(vector[3] == "d");
OATPP_LOGI(TAG, "OK");
}
}
}}}}}}

View File

@ -0,0 +1,42 @@
/***************************************************************************
*
* 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 oatpp_test_core_data_mapping_type_VectorTest_hpp
#define oatpp_test_core_data_mapping_type_VectorTest_hpp
#include "oatpp-test/UnitTest.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace mapping { namespace type {
class VectorTest : public UnitTest{
public:
VectorTest():UnitTest("TEST[core::data::mapping::type::VectorTest]"){}
void onRun() override;
};
}}}}}}
#endif /* oatpp_test_core_data_mapping_type_VectorTest_hpp */

View File

@ -25,6 +25,7 @@
#include "LazyStringMapTest.hpp"
#include "oatpp/core/data/share/LazyStringMap.hpp"
#include "oatpp/core/Types.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace share {

View File

@ -32,130 +32,291 @@
#include "oatpp-test/Checker.hpp"
namespace oatpp { namespace test { namespace core { namespace data { namespace share {
namespace {
typedef oatpp::data::share::MemoryLabel MemoryLabel;
typedef oatpp::data::share::StringKeyLabel StringKeyLabel;
typedef oatpp::data::share::StringKeyLabelCI StringKeyLabelCI;
typedef oatpp::data::share::StringKeyLabelCI_FAST StringKeyLabelCI_FAST;
}
void MemoryLabelTest::onRun() {
oatpp::String sharedData = "big text goes here";
oatpp::String key1 = "key1";
oatpp::String key2 = "key2";
oatpp::String key3 = "key3";
oatpp::String key4 = "key4";
std::unordered_map<oatpp::data::share::StringKeyLabel, oatpp::data::share::MemoryLabel> stringMap;
std::unordered_map<oatpp::data::share::StringKeyLabelCI, oatpp::data::share::MemoryLabel> stringMapCI;
std::unordered_map<oatpp::data::share::StringKeyLabelCI_FAST, oatpp::data::share::MemoryLabel> stringMapCI_FAST;
// Case-Sensitive
stringMap[key1] = oatpp::data::share::MemoryLabel(sharedData.getPtr(), &sharedData->getData()[0], 3);
stringMap[key2] = oatpp::data::share::MemoryLabel(sharedData.getPtr(), &sharedData->getData()[4], 4);
stringMap[key3] = oatpp::data::share::MemoryLabel(sharedData.getPtr(), &sharedData->getData()[9], 4);
stringMap[key4] = oatpp::data::share::MemoryLabel(sharedData.getPtr(), &sharedData->getData()[14], 4);
OATPP_ASSERT(oatpp::base::StrBuffer::equals("big", stringMap["key1"].getData(), 3));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("text", stringMap["key2"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("goes", stringMap["key3"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("here", stringMap["key4"].getData(), 4));
OATPP_ASSERT(stringMap.find("Key1") == stringMap.end());
OATPP_ASSERT(stringMap.find("Key2") == stringMap.end());
OATPP_ASSERT(stringMap.find("Key3") == stringMap.end());
OATPP_ASSERT(stringMap.find("Key4") == stringMap.end());
// CI
stringMapCI[key1] = oatpp::data::share::MemoryLabel(sharedData.getPtr(), &sharedData->getData()[0], 3);
stringMapCI[key2] = oatpp::data::share::MemoryLabel(sharedData.getPtr(), &sharedData->getData()[4], 4);
stringMapCI[key3] = oatpp::data::share::MemoryLabel(sharedData.getPtr(), &sharedData->getData()[9], 4);
stringMapCI[key4] = oatpp::data::share::MemoryLabel(sharedData.getPtr(), &sharedData->getData()[14], 4);
OATPP_ASSERT(oatpp::base::StrBuffer::equals("big", stringMapCI["key1"].getData(), 3));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("text", stringMapCI["key2"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("goes", stringMapCI["key3"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("here", stringMapCI["key4"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("big", stringMapCI["KEY1"].getData(), 3));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("text", stringMapCI["KEY2"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("goes", stringMapCI["KEY3"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("here", stringMapCI["KEY4"].getData(), 4));
// CI_FAST
stringMapCI_FAST[key1] = oatpp::data::share::MemoryLabel(sharedData.getPtr(), &sharedData->getData()[0], 3);
stringMapCI_FAST[key2] = oatpp::data::share::MemoryLabel(sharedData.getPtr(), &sharedData->getData()[4], 4);
stringMapCI_FAST[key3] = oatpp::data::share::MemoryLabel(sharedData.getPtr(), &sharedData->getData()[9], 4);
stringMapCI_FAST[key4] = oatpp::data::share::MemoryLabel(sharedData.getPtr(), &sharedData->getData()[14], 4);
OATPP_ASSERT(oatpp::base::StrBuffer::equals("big", stringMapCI_FAST["key1"].getData(), 3));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("text", stringMapCI_FAST["key2"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("goes", stringMapCI_FAST["key3"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("here", stringMapCI_FAST["key4"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("big", stringMapCI_FAST["KEY1"].getData(), 3));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("text", stringMapCI_FAST["KEY2"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("goes", stringMapCI_FAST["KEY3"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("here", stringMapCI_FAST["KEY4"].getData(), 4));
{
v_int32 iterationsCount = 100;
oatpp::String headersText =
"header0: value0\r\n"
"header1: value1\r\n"
"header2: value2\r\n"
"header3: value3\r\n"
"header4: value4\r\n"
"header5: value5\r\n"
"header6: value6\r\n"
"header7: value7\r\n"
"header8: value8\r\n"
"header9: value9\r\n"
"\r\n";
{
oatpp::test::PerformanceChecker timer("timer");
for(v_int32 i = 0; i < iterationsCount; i ++) {
oatpp::parser::Caret caret(headersText);
oatpp::web::protocol::http::Status status;
oatpp::web::protocol::http::Headers headers;
oatpp::web::protocol::http::Parser::parseHeaders(headers, headersText.getPtr(), caret, status);
OATPP_ASSERT(status.code == 0);
OATPP_ASSERT(headers.getSize() == 10);
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header0").equals("value0", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header1").equals("value1", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header2").equals("value2", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header3").equals("value3", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header4").equals("value4", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header5").equals("value5", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header6").equals("value6", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header7").equals("value7", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header8").equals("value8", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header9").equals("value9", 6));
OATPP_LOGI(TAG, "StringKeyLabel default constructor...");
StringKeyLabel s;
StringKeyLabel s0;
OATPP_ASSERT(!s);
OATPP_ASSERT(s == nullptr);
OATPP_ASSERT(s == s0);
OATPP_ASSERT(s != "text");
OATPP_ASSERT(s != oatpp::String("text"));
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "StringKeyLabel nullptr constructor...");
StringKeyLabel s(nullptr);
OATPP_ASSERT(!s);
OATPP_ASSERT(s == nullptr);
OATPP_ASSERT(s != "text");
OATPP_ASSERT(s != oatpp::String("text"));
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "StringKeyLabel const char* constructor...");
StringKeyLabel s("hello");
StringKeyLabel s0;
OATPP_ASSERT(s);
OATPP_ASSERT(s != nullptr);
OATPP_ASSERT(s != s0);
OATPP_ASSERT(s0 != s);
OATPP_ASSERT(s == "hello");
OATPP_ASSERT(s == oatpp::String("hello"));
OATPP_ASSERT(s != "text");
OATPP_ASSERT(s != oatpp::String("text"));
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "StringKeyLabel oatpp::String constructor...");
StringKeyLabel s(oatpp::String("hello"));
OATPP_ASSERT(s);
OATPP_ASSERT(s != nullptr);
OATPP_ASSERT(s == "hello");
OATPP_ASSERT(s == oatpp::String("hello"));
OATPP_ASSERT(s != "text");
OATPP_ASSERT(s != oatpp::String("text"));
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "StringKeyLabelCI default constructor...");
StringKeyLabelCI s;
StringKeyLabelCI s0;
OATPP_ASSERT(!s);
OATPP_ASSERT(s == nullptr);
OATPP_ASSERT(s == s0);
OATPP_ASSERT(s != "teXt");
OATPP_ASSERT(s != oatpp::String("teXt"));
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "StringKeyLabelCI nullptr constructor...");
StringKeyLabelCI s(nullptr);
OATPP_ASSERT(!s);
OATPP_ASSERT(s == nullptr);
OATPP_ASSERT(s != "teXt");
OATPP_ASSERT(s != oatpp::String("teXt"));
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "StringKeyLabelCI const char* constructor...");
StringKeyLabelCI s("hello");
StringKeyLabelCI s0;
OATPP_ASSERT(s);
OATPP_ASSERT(s != nullptr);
OATPP_ASSERT(s != s0);
OATPP_ASSERT(s0 != s);
OATPP_ASSERT(s == "helLO");
OATPP_ASSERT(s == oatpp::String("helLO"));
OATPP_ASSERT(s != "text");
OATPP_ASSERT(s != oatpp::String("teXt"));
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "StringKeyLabelCI oatpp::String constructor...");
StringKeyLabelCI s(oatpp::String("hello"));
OATPP_ASSERT(s);
OATPP_ASSERT(s != nullptr);
OATPP_ASSERT(s == "helLO");
OATPP_ASSERT(s == oatpp::String("helLO"));
OATPP_ASSERT(s != "text");
OATPP_ASSERT(s != oatpp::String("teXt"));
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "StringKeyLabelCI_FAST default constructor...");
StringKeyLabelCI_FAST s;
StringKeyLabelCI_FAST s0;
OATPP_ASSERT(!s);
OATPP_ASSERT(s == nullptr);
OATPP_ASSERT(s == s0);
OATPP_ASSERT(s != "teXt");
OATPP_ASSERT(s != oatpp::String("teXt"));
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "StringKeyLabelCI_FAST nullptr constructor...");
StringKeyLabelCI_FAST s(nullptr);
OATPP_ASSERT(!s);
OATPP_ASSERT(s == nullptr);
OATPP_ASSERT(s != "teXt");
OATPP_ASSERT(s != oatpp::String("teXt"));
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "StringKeyLabelCI_FAST const char* constructor...");
StringKeyLabelCI_FAST s("hello");
StringKeyLabelCI_FAST s0;
OATPP_ASSERT(s);
OATPP_ASSERT(s != nullptr);
OATPP_ASSERT(s != s0);
OATPP_ASSERT(s0 != s);
OATPP_ASSERT(s == "helLO");
OATPP_ASSERT(s == oatpp::String("helLO"));
OATPP_ASSERT(s != "text");
OATPP_ASSERT(s != oatpp::String("teXt"));
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "StringKeyLabelCI_FAST oatpp::String constructor...");
StringKeyLabelCI_FAST s(oatpp::String("hello"));
OATPP_ASSERT(s);
OATPP_ASSERT(s != nullptr);
OATPP_ASSERT(s == "helLO");
OATPP_ASSERT(s == oatpp::String("helLO"));
OATPP_ASSERT(s != "text");
OATPP_ASSERT(s != oatpp::String("teXt"));
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "general test...");
oatpp::String sharedData = "big text goes here";
oatpp::String key1 = "key1";
oatpp::String key2 = "key2";
oatpp::String key3 = "key3";
oatpp::String key4 = "key4";
std::unordered_map<StringKeyLabel, MemoryLabel> stringMap;
std::unordered_map<StringKeyLabelCI, MemoryLabel> stringMapCI;
std::unordered_map<StringKeyLabelCI_FAST, MemoryLabel> stringMapCI_FAST;
// Case-Sensitive
stringMap[key1] = MemoryLabel(sharedData.getPtr(), &sharedData->getData()[0], 3);
stringMap[key2] = MemoryLabel(sharedData.getPtr(), &sharedData->getData()[4], 4);
stringMap[key3] = MemoryLabel(sharedData.getPtr(), &sharedData->getData()[9], 4);
stringMap[key4] = MemoryLabel(sharedData.getPtr(), &sharedData->getData()[14], 4);
OATPP_ASSERT(oatpp::base::StrBuffer::equals("big", stringMap["key1"].getData(), 3));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("text", stringMap["key2"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("goes", stringMap["key3"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("here", stringMap["key4"].getData(), 4));
OATPP_ASSERT(stringMap.find("Key1") == stringMap.end());
OATPP_ASSERT(stringMap.find("Key2") == stringMap.end());
OATPP_ASSERT(stringMap.find("Key3") == stringMap.end());
OATPP_ASSERT(stringMap.find("Key4") == stringMap.end());
// CI
stringMapCI[key1] = MemoryLabel(sharedData.getPtr(), &sharedData->getData()[0], 3);
stringMapCI[key2] = MemoryLabel(sharedData.getPtr(), &sharedData->getData()[4], 4);
stringMapCI[key3] = MemoryLabel(sharedData.getPtr(), &sharedData->getData()[9], 4);
stringMapCI[key4] = MemoryLabel(sharedData.getPtr(), &sharedData->getData()[14], 4);
OATPP_ASSERT(oatpp::base::StrBuffer::equals("big", stringMapCI["key1"].getData(), 3));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("text", stringMapCI["key2"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("goes", stringMapCI["key3"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("here", stringMapCI["key4"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("big", stringMapCI["KEY1"].getData(), 3));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("text", stringMapCI["KEY2"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("goes", stringMapCI["KEY3"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("here", stringMapCI["KEY4"].getData(), 4));
// CI_FAST
stringMapCI_FAST[key1] = MemoryLabel(sharedData.getPtr(), &sharedData->getData()[0], 3);
stringMapCI_FAST[key2] = MemoryLabel(sharedData.getPtr(), &sharedData->getData()[4], 4);
stringMapCI_FAST[key3] = MemoryLabel(sharedData.getPtr(), &sharedData->getData()[9], 4);
stringMapCI_FAST[key4] = MemoryLabel(sharedData.getPtr(), &sharedData->getData()[14], 4);
OATPP_ASSERT(oatpp::base::StrBuffer::equals("big", stringMapCI_FAST["key1"].getData(), 3));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("text", stringMapCI_FAST["key2"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("goes", stringMapCI_FAST["key3"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("here", stringMapCI_FAST["key4"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("big", stringMapCI_FAST["KEY1"].getData(), 3));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("text", stringMapCI_FAST["KEY2"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("goes", stringMapCI_FAST["KEY3"].getData(), 4));
OATPP_ASSERT(oatpp::base::StrBuffer::equals("here", stringMapCI_FAST["KEY4"].getData(), 4));
{
v_int32 iterationsCount = 100;
oatpp::String headersText =
"header0: value0\r\n"
"header1: value1\r\n"
"header2: value2\r\n"
"header3: value3\r\n"
"header4: value4\r\n"
"header5: value5\r\n"
"header6: value6\r\n"
"header7: value7\r\n"
"header8: value8\r\n"
"header9: value9\r\n"
"\r\n";
{
oatpp::test::PerformanceChecker timer("timer");
for (v_int32 i = 0; i < iterationsCount; i++) {
oatpp::parser::Caret caret(headersText);
oatpp::web::protocol::http::Status status;
oatpp::web::protocol::http::Headers headers;
oatpp::web::protocol::http::Parser::parseHeaders(headers, headersText.getPtr(), caret, status);
OATPP_ASSERT(status.code == 0);
OATPP_ASSERT(headers.getSize() == 10);
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header0").equals("value0", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header1").equals("value1", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header2").equals("value2", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header3").equals("value3", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header4").equals("value4", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header5").equals("value5", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header6").equals("value6", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header7").equals("value7", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header8").equals("value8", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header9").equals("value9", 6));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header0").equals("value0"));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header1").equals("value1"));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header2").equals("value2"));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header3").equals("value3"));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header4").equals("value4"));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header5").equals("value5"));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header6").equals("value6"));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header7").equals("value7"));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header8").equals("value8"));
OATPP_ASSERT(headers.getAsMemoryLabel<StringKeyLabel>("header9").equals("value9"));
}
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header0").equals("value0"));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header1").equals("value1"));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header2").equals("value2"));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header3").equals("value3"));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header4").equals("value4"));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header5").equals("value5"));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header6").equals("value6"));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header7").equals("value7"));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header8").equals("value8"));
OATPP_ASSERT(headers.getAsMemoryLabel<oatpp::data::share::StringKeyLabel>("header9").equals("value9"));
}
}
OATPP_LOGI(TAG, "OK");
}
}

View File

@ -50,16 +50,16 @@ typedef oatpp::parser::json::mapping::Deserializer Deserializer;
DTO_FIELD(String, field_string);
DTO_FIELD(Int32, field_int32);
DTO_FIELD(List<Int32>::ObjectWrapper, field_list);
DTO_FIELD(List<Int32>, field_list);
static ObjectWrapper createTestInstance(){
auto result = Test1::createShared();
result->field_string = "String Field";
result->field_int32 = 5;
result->field_list = List<Int32>::createShared();
result->field_list->pushBack(1);
result->field_list->pushBack(2);
result->field_list->pushBack(3);
result->field_list->push_back(1);
result->field_list->push_back(2);
result->field_list->push_back(3);
return result;
}

View File

@ -30,6 +30,8 @@
#include "oatpp/core/data/mapping/type/List.hpp"
#include "oatpp/core/data/mapping/type/Primitive.hpp"
#include "oatpp/core/utils/ConversionUtils.hpp"
#include "oatpp/core/macro/codegen.hpp"
namespace oatpp { namespace test { namespace parser { namespace json { namespace mapping {
@ -38,11 +40,9 @@ namespace {
#include OATPP_CODEGEN_BEGIN(DTO)
typedef oatpp::data::mapping::type::Object DTO;
class TestChild : public oatpp::Object {
class TestChild : public DTO {
DTO_INIT(TestChild, DTO)
DTO_INIT(TestChild, Object)
static ObjectWrapper createShared(const char* name, const char* secondName){
auto result = createShared();
@ -56,9 +56,9 @@ class TestChild : public DTO {
};
class Test : public DTO {
class Test : public oatpp::Object {
DTO_INIT(Test, DTO)
DTO_INIT(Test, Object)
DTO_FIELD(String, field_string, "string-field-name-qualifier");
DTO_FIELD(Int32, field_int32, "int32-field-name-qualifier");
@ -67,20 +67,41 @@ class Test : public DTO {
DTO_FIELD(Float64, field_float64);
DTO_FIELD(Boolean, field_boolean);
DTO_FIELD(List<String>::ObjectWrapper, field_list_string) = List<String>::createShared();
DTO_FIELD(List<Int32>::ObjectWrapper, field_list_int32) = List<Int32>::createShared();
DTO_FIELD(List<Int64>::ObjectWrapper, field_list_int64) = List<Int64>::createShared();
DTO_FIELD(List<Float32>::ObjectWrapper, field_list_float32) = List<Float32>::createShared();
DTO_FIELD(List<Float64>::ObjectWrapper, field_list_float64) = List<Float64>::createShared();
DTO_FIELD(List<Boolean>::ObjectWrapper, field_list_boolean) = List<Boolean>::createShared();
DTO_FIELD(List<String>, field_list_string) = List<String>::createShared();
DTO_FIELD(List<Int32>, field_list_int32) = List<Int32>::createShared();
DTO_FIELD(List<Int64>, field_list_int64) = List<Int64>::createShared();
DTO_FIELD(List<Float32>, field_list_float32) = List<Float32>::createShared();
DTO_FIELD(List<Float64>, field_list_float64) = List<Float64>::createShared();
DTO_FIELD(List<Boolean>, field_list_boolean) = List<Boolean>::createShared();
DTO_FIELD(List<TestChild::ObjectWrapper>::ObjectWrapper, field_list_object) = List<TestChild::ObjectWrapper>::createShared();
DTO_FIELD(List<List<TestChild::ObjectWrapper>::ObjectWrapper>::ObjectWrapper, field_list_list_object) = List<List<TestChild::ObjectWrapper>::ObjectWrapper>::createShared();
DTO_FIELD(List<TestChild>, field_list_object) = List<TestChild>::createShared();
DTO_FIELD(List<List<TestChild>>, field_list_list_object) = List<List<TestChild>>::createShared();
DTO_FIELD(Vector<String>, field_vector);
DTO_FIELD(Fields<String>, field_fields);
DTO_FIELD(UnorderedFields<String>, field_unordered_fields);
DTO_FIELD(Test::ObjectWrapper, obj1);
DTO_FIELD(TestChild::ObjectWrapper, child1);
DTO_FIELD(Test, obj1);
DTO_FIELD(TestChild, child1);
};
class TestAny : public oatpp::Object {
DTO_INIT(TestAny, Object)
DTO_FIELD(List<Any>, anyList) = List<Any>::createShared();
};
class TestAnyNested : public oatpp::Object {
DTO_INIT(TestAnyNested, Object)
DTO_FIELD(String, f1) = "Field_1";
DTO_FIELD(String, f2) = "Field_2";
};
#include OATPP_CODEGEN_END(DTO)
@ -89,7 +110,8 @@ class Test : public DTO {
void DTOMapperTest::onRun(){
auto mapper = oatpp::parser::json::mapping::ObjectMapper::createShared();
mapper->getSerializer()->getConfig()->useBeautifier = true;
Test::ObjectWrapper test1 = Test::createShared();
test1->field_string = "string value";
@ -101,61 +123,93 @@ void DTOMapperTest::onRun(){
test1->obj1 = Test::createShared();
test1->obj1->field_string = "inner string";
test1->obj1->field_list_string->pushBack("inner str_item_1");
test1->obj1->field_list_string->pushBack("inner str_item_2");
test1->obj1->field_list_string->pushBack("inner str_item_3");
test1->obj1->field_list_string->push_back("inner str_item_1");
test1->obj1->field_list_string->push_back("inner str_item_2");
test1->obj1->field_list_string->push_back("inner str_item_3");
test1->child1 = TestChild::createShared();
test1->child1->name = "child1_name";
test1->child1->secondName = "child1_second_name";
test1->field_list_string->pushBack("str_item_1");
test1->field_list_string->pushBack("str_item_2");
test1->field_list_string->pushBack("str_item_3");
test1->field_list_string->push_back("str_item_1");
test1->field_list_string->push_back("str_item_2");
test1->field_list_string->push_back("str_item_3");
test1->field_list_int32->pushBack(321);
test1->field_list_int32->pushBack(322);
test1->field_list_int32->pushBack(323);
test1->field_list_int32->push_back(321);
test1->field_list_int32->push_back(322);
test1->field_list_int32->push_back(323);
test1->field_list_int64->pushBack(641);
test1->field_list_int64->pushBack(642);
test1->field_list_int64->pushBack(643);
test1->field_list_int64->push_back(641);
test1->field_list_int64->push_back(642);
test1->field_list_int64->push_back(643);
test1->field_list_float32->pushBack(0.321f);
test1->field_list_float32->pushBack(0.322f);
test1->field_list_float32->pushBack(0.323f);
test1->field_list_float32->push_back(0.321f);
test1->field_list_float32->push_back(0.322f);
test1->field_list_float32->push_back(0.323f);
test1->field_list_float64->pushBack(0.641);
test1->field_list_float64->pushBack(0.642);
test1->field_list_float64->pushBack(0.643);
test1->field_list_float64->push_back(0.641);
test1->field_list_float64->push_back(0.642);
test1->field_list_float64->push_back(0.643);
test1->field_list_boolean->pushBack(true);
test1->field_list_boolean->pushBack(false);
test1->field_list_boolean->pushBack(true);
test1->field_list_boolean->push_back(true);
test1->field_list_boolean->push_back(false);
test1->field_list_boolean->push_back(true);
test1->field_list_object->pushBack(TestChild::createShared("child", "1"));
test1->field_list_object->pushBack(TestChild::createShared("child", "2"));
test1->field_list_object->pushBack(TestChild::createShared("child", "3"));
test1->field_list_object->push_back(TestChild::createShared("child", "1"));
test1->field_list_object->push_back(TestChild::createShared("child", "2"));
test1->field_list_object->push_back(TestChild::createShared("child", "3"));
auto l1 = DTO::List<TestChild::ObjectWrapper>::createShared();
auto l2 = DTO::List<TestChild::ObjectWrapper>::createShared();
auto l3 = DTO::List<TestChild::ObjectWrapper>::createShared();
auto l1 = oatpp::List<TestChild>::createShared();
auto l2 = oatpp::List<TestChild>::createShared();
auto l3 = oatpp::List<TestChild>::createShared();
l1->pushBack(TestChild::createShared("list_1", "item_1"));
l1->pushBack(TestChild::createShared("list_1", "item_2"));
l1->pushBack(TestChild::createShared("list_1", "item_3"));
l1->push_back(TestChild::createShared("list_1", "item_1"));
l1->push_back(TestChild::createShared("list_1", "item_2"));
l1->push_back(TestChild::createShared("list_1", "item_3"));
l2->pushBack(TestChild::createShared("list_2", "item_1"));
l2->pushBack(TestChild::createShared("list_2", "item_2"));
l2->pushBack(TestChild::createShared("list_2", "item_3"));
l2->push_back(TestChild::createShared("list_2", "item_1"));
l2->push_back(TestChild::createShared("list_2", "item_2"));
l2->push_back(TestChild::createShared("list_2", "item_3"));
l3->pushBack(TestChild::createShared("list_3", "item_1"));
l3->pushBack(TestChild::createShared("list_3", "item_2"));
l3->pushBack(TestChild::createShared("list_3", "item_3"));
l3->push_back(TestChild::createShared("list_3", "item_1"));
l3->push_back(TestChild::createShared("list_3", "item_2"));
l3->push_back(TestChild::createShared("list_3", "item_3"));
test1->field_list_list_object->pushBack(l1);
test1->field_list_list_object->pushBack(l2);
test1->field_list_list_object->pushBack(l3);
test1->field_list_list_object->push_back(l1);
test1->field_list_list_object->push_back(l2);
test1->field_list_list_object->push_back(l3);
test1->field_vector = {"vector_item1", "vector_item2", "vector_item3"};
test1->field_fields = {
{"key0", "pair_item0"},
{"key1", "pair_item1"},
{"key2", "pair_item2"},
{"key3", "pair_item3"},
{"key4", "pair_item4"},
{"key5", "pair_item5"},
{"key6", "pair_item6"},
{"key7", "pair_item7"},
{"key8", "pair_item8"},
{"key9", "pair_item9"},
{"key10", "pair_item10"},
{"key11", "pair_item11"}
};
test1->field_unordered_fields = {
{"key0", "map_item0"},
{"key1", "map_item1"},
{"key2", "map_item2"},
{"key3", "map_item3"},
{"key4", "map_item4"},
{"key5", "map_item5"},
{"key6", "map_item6"},
{"key7", "map_item7"},
{"key8", "map_item8"},
{"key9", "map_item9"},
{"key10", "map_item10"},
{"key11", "map_item11"}
};
auto result = mapper->writeToString(test1);
@ -172,24 +226,80 @@ void DTOMapperTest::onRun(){
OATPP_ASSERT(obj->field_string == test1->field_string);
OATPP_ASSERT(obj->field_int32);
OATPP_ASSERT(obj->field_int32->getValue() == test1->field_int32->getValue());
OATPP_ASSERT(obj->field_int32 == test1->field_int32);
OATPP_ASSERT(obj->field_int64);
OATPP_ASSERT(obj->field_int64->getValue() == test1->field_int64->getValue());
OATPP_ASSERT(obj->field_int64 == test1->field_int64);
OATPP_ASSERT(obj->field_float32);
OATPP_ASSERT(obj->field_float32->getValue() == test1->field_float32->getValue());
OATPP_ASSERT(obj->field_float32 == test1->field_float32);
OATPP_ASSERT(obj->field_float64);
OATPP_ASSERT(obj->field_float64->getValue() == test1->field_float64->getValue());
OATPP_ASSERT(obj->field_float64 == test1->field_float64);
OATPP_ASSERT(obj->field_boolean);
OATPP_ASSERT(obj->field_boolean->getValue() == test1->field_boolean->getValue());
OATPP_ASSERT(obj->field_boolean == test1->field_boolean);
{
auto c = obj->field_vector;
OATPP_ASSERT(c[0] == "vector_item1");
OATPP_ASSERT(c[1] == "vector_item2");
OATPP_ASSERT(c[2] == "vector_item3");
}
{
auto c = obj->field_fields;
v_int32 i = 0;
for(auto& pair : *c) {
OATPP_ASSERT(pair.first == "key" + oatpp::utils::conversion::int32ToStr(i));
OATPP_ASSERT(pair.second == "pair_item" + oatpp::utils::conversion::int32ToStr(i));
i++;
}
}
{
auto c = obj->field_unordered_fields;
OATPP_ASSERT(c["key1"] == "map_item1");
OATPP_ASSERT(c["key2"] == "map_item2");
OATPP_ASSERT(c["key3"] == "map_item3");
}
result = mapper->writeToString(obj);
OATPP_LOGV(TAG, "json='%s'", (const char*) result->getData());
{
TestAny::ObjectWrapper::__Wrapper objOW1;
TestAny::__Wrapper objOW2;
auto obj = TestAny::createShared();
obj->anyList = {
oatpp::String("Hello Any!!!"),
oatpp::Int32(32),
oatpp::Int64(64),
oatpp::Float64(0.64),
oatpp::Float64(0.64),
TestAnyNested::createShared()
};
auto map = oatpp::Fields<Any>::createShared();
map["bool-field"] = oatpp::Boolean(false);
map["vector"] = oatpp::Vector<oatpp::String>({"vector_v1", "vector_v2", "vector_v3"});
map["unordered_map"] = oatpp::UnorderedFields<oatpp::String>({{"key1", "value1"}, {"key2", "value2"}});
obj->anyList->push_back(map);
auto json = mapper->writeToString(obj);
OATPP_LOGV(TAG, "any json='%s'", (const char*) json->getData());
auto deserializedAny = mapper->readFromString<oatpp::Fields<oatpp::Any>>(json);
auto json2 = mapper->writeToString(deserializedAny);
OATPP_LOGV(TAG, "any json='%s'", (const char*) json2->getData());
}
}
#include OATPP_CODEGEN_END(DTO)

View File

@ -72,9 +72,9 @@ class Test4 : public DTO {
DTO_INIT(Test4, DTO)
DTO_FIELD(EmptyDto::ObjectWrapper, object);
DTO_FIELD(List<EmptyDto::ObjectWrapper>::ObjectWrapper, list);
DTO_FIELD(Fields<EmptyDto::ObjectWrapper>::ObjectWrapper, map);
DTO_FIELD(EmptyDto, object);
DTO_FIELD(List<EmptyDto>, list);
DTO_FIELD(Fields<EmptyDto>, map);
};
@ -111,12 +111,12 @@ void DeserializerTest::onRun(){
obj2 = mapper->readFromString<Test2>("{\"int32F\": 32}");
OATPP_ASSERT(obj2);
OATPP_ASSERT(obj2->int32F->getValue() == 32);
OATPP_ASSERT(obj2->int32F == 32);
obj2 = mapper->readFromString<Test2>("{\"int32F\": -32}");
OATPP_ASSERT(obj2);
OATPP_ASSERT(obj2->int32F->getValue() == -32);
OATPP_ASSERT(obj2->int32F == -32);
auto obj3 = mapper->readFromString<Test3>("{\"float32F\": null}");
@ -126,7 +126,7 @@ void DeserializerTest::onRun(){
obj3 = mapper->readFromString<Test3>("{\"float32F\": 32}");
OATPP_ASSERT(obj3);
OATPP_ASSERT(obj3->float32F->getValue() == 32);
OATPP_ASSERT(obj3->float32F == 32);
obj3 = mapper->readFromString<Test3>("{\"float32F\": 1.32e1}");
@ -155,10 +155,10 @@ void DeserializerTest::onRun(){
auto list = mapper->readFromString<Test1::List<Test1::Int32>>("[1, 2, 3]");
OATPP_ASSERT(list);
OATPP_ASSERT(list->count() == 3);
OATPP_ASSERT(list->get(0)->getValue() == 1);
OATPP_ASSERT(list->get(1)->getValue() == 2);
OATPP_ASSERT(list->get(2)->getValue() == 3);
OATPP_ASSERT(list->size() == 3);
OATPP_ASSERT(list[0] == 1);
OATPP_ASSERT(list[1] == 2);
OATPP_ASSERT(list[2] == 3);
// Empty test
@ -166,15 +166,15 @@ void DeserializerTest::onRun(){
OATPP_ASSERT(obj4);
OATPP_ASSERT(obj4->object);
OATPP_ASSERT(obj4->list);
OATPP_ASSERT(obj4->list->count() == 0);
OATPP_ASSERT(obj4->map->count() == 0);
OATPP_ASSERT(obj4->list->size() == 0);
OATPP_ASSERT(obj4->map->size() == 0);
obj4 = mapper->readFromString<Test4>("{\"object\": {\n\r\t}, \"list\": [\n\r\t], \"map\": {\n\r\t}}");
OATPP_ASSERT(obj4);
OATPP_ASSERT(obj4->object);
OATPP_ASSERT(obj4->list);
OATPP_ASSERT(obj4->list->count() == 0);
OATPP_ASSERT(obj4->map->count() == 0);
OATPP_ASSERT(obj4->list->size() == 0);
OATPP_ASSERT(obj4->map->size() == 0);
}

View File

@ -0,0 +1,187 @@
/***************************************************************************
*
* 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 "EnumTest.hpp"
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
#include "oatpp/core/macro/codegen.hpp"
namespace oatpp { namespace test { namespace parser { namespace json { namespace mapping {
namespace {
#include OATPP_CODEGEN_BEGIN(DTO)
ENUM(Enum0, v_int32);
ENUM(Enum1, v_int32,
VALUE(V1, 10, "enum1-v1"),
VALUE(V2, 20, "enum1-v2"),
VALUE(V3, 30, "enum1-v3")
);
class DTO1 : public oatpp::Object {
DTO_INIT(DTO1, Object)
DTO_FIELD(Enum<Enum1>::AsString, enum1);
};
#include OATPP_CODEGEN_END(DTO)
}
void EnumTest::onRun() {
oatpp::parser::json::mapping::ObjectMapper mapper;
{
OATPP_LOGI(TAG, "Serializer as string...");
oatpp::Fields<oatpp::Enum<Enum1>::AsString> map = {{"enum", Enum1::V1}};
auto json = mapper.writeToString(map);
OATPP_LOGD(TAG, "json='%s'", json->c_str());
OATPP_ASSERT(json == "{\"enum\":\"enum1-v1\"}");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Serializer as string null...");
oatpp::Fields<oatpp::Enum<Enum1>::AsString> map = {{"enum", nullptr}};
auto json = mapper.writeToString(map);
OATPP_LOGD(TAG, "json='%s'", json->c_str());
OATPP_ASSERT(json == "{\"enum\":null}");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Serializer as string error on null...");
bool error = false;
oatpp::Fields<oatpp::Enum<Enum1>::AsString::NotNull> map = {{"enum", nullptr}};
try {
auto json = mapper.writeToString(map);
} catch (const std::runtime_error& e) {
OATPP_LOGD(TAG, "error - %s", e.what());
error = true;
}
OATPP_ASSERT(error == true);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Serializer as int...");
oatpp::Fields<oatpp::Enum<Enum1>::AsNumber> map = {{"enum", Enum1::V1}};
auto json = mapper.writeToString(map);
OATPP_LOGD(TAG, "json='%s'", json->c_str());
OATPP_ASSERT(json == "{\"enum\":10}");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Serializer as int null...");
oatpp::Fields<oatpp::Enum<Enum1>::AsNumber> map = {{"enum", nullptr}};
auto json = mapper.writeToString(map);
OATPP_LOGD(TAG, "json='%s'", json->c_str());
OATPP_ASSERT(json == "{\"enum\":null}");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Serializer as int error on null...");
bool error = false;
oatpp::Fields<oatpp::Enum<Enum1>::AsNumber::NotNull> map = {{"enum", nullptr}};
try {
auto json = mapper.writeToString(map);
} catch (const std::runtime_error& e) {
OATPP_LOGD(TAG, "error - %s", e.what());
error = true;
}
OATPP_ASSERT(error == true);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Deserializer as string...");
oatpp::String json = "{\"enum\":\"enum1-v2\"}";
auto map = mapper.readFromString<oatpp::Fields<oatpp::Enum<Enum1>::AsString>>(json);
OATPP_ASSERT(map["enum"] == Enum1::V2);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Deserializer as string null...");
oatpp::String json = "{\"enum\":null}";
auto map = mapper.readFromString<oatpp::Fields<oatpp::Enum<Enum1>::AsString>>(json);
OATPP_ASSERT(map["enum"] == nullptr);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Deserializer as string error on null...");
bool error = false;
oatpp::String json = "{\"enum\":null}";
try {
auto map = mapper.readFromString<oatpp::Fields<oatpp::Enum<Enum1>::AsString::NotNull>>(json);
} catch (const oatpp::parser::ParsingError& e) {
OATPP_LOGD(TAG, "error - %s", e.what());
error = true;
}
OATPP_ASSERT(error == true);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Deserializer as int...");
oatpp::String json = "{\"enum\":20}";
auto map = mapper.readFromString<oatpp::Fields<oatpp::Enum<Enum1>::AsNumber>>(json);
OATPP_ASSERT(map["enum"] == Enum1::V2);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Deserializer as int null...");
oatpp::String json = "{\"enum\":null}";
auto map = mapper.readFromString<oatpp::Fields<oatpp::Enum<Enum1>::AsNumber>>(json);
OATPP_ASSERT(map["enum"] == nullptr);
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Deserializer as int error on null...");
bool error = false;
oatpp::String json = "{\"enum\":null}";
try {
auto map = mapper.readFromString<oatpp::Fields<oatpp::Enum<Enum1>::AsNumber::NotNull>>(json);
} catch (const oatpp::parser::ParsingError& e) {
OATPP_LOGD(TAG, "error - %s", e.what());
error = true;
}
OATPP_ASSERT(error == true);
OATPP_LOGI(TAG, "OK");
}
}
}}}}}

View File

@ -22,21 +22,21 @@
*
***************************************************************************/
#ifndef oatpp_test_base_RegRuleTest_hpp
#define oatpp_test_base_RegRuleTest_hpp
#ifndef oatpp_test_parser_json_mapping_EnumTest_hpp
#define oatpp_test_parser_json_mapping_EnumTest_hpp
#include "oatpp-test/UnitTest.hpp"
namespace oatpp { namespace test { namespace base {
class RegRuleTest : public UnitTest{
public:
RegRuleTest():UnitTest("TEST[base::RegRuleTest]"){}
void onRun() override;
};
}}}
namespace oatpp { namespace test { namespace parser { namespace json { namespace mapping {
#endif /* oatpp_test_base_RegRuleTest_hpp */
class EnumTest : public UnitTest{
public:
EnumTest():UnitTest("TEST[parser::json::mapping::EnumTest]"){}
void onRun() override;
};
}}}}}
#endif /* oatpp_test_parser_json_mapping_EnumTest_hpp */

View File

@ -0,0 +1,53 @@
/***************************************************************************
*
* 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 "UnorderedSetTest.hpp"
#include "oatpp/parser/json/mapping/ObjectMapper.hpp"
namespace oatpp { namespace test { namespace parser { namespace json { namespace mapping {
void UnorderedSetTest::onRun() {
oatpp::parser::json::mapping::ObjectMapper mapper;
{
oatpp::UnorderedSet<oatpp::String> set = {"Hello", "World", "!"};
auto json = mapper.writeToString(set);
OATPP_LOGD(TAG, "json='%s'", json->c_str());
}
{
oatpp::String json = "[\"Hello\",\"World\",\"!\",\"Hello\",\"World\",\"!\"]";
auto set = mapper.readFromString<oatpp::UnorderedSet<oatpp::String>>(json);
OATPP_ASSERT(set);
OATPP_ASSERT(set->size() == 3);
for(auto& item : *set) {
OATPP_LOGD(TAG, "item='%s'", item->c_str());
}
}
}
}}}}}

View File

@ -0,0 +1,42 @@
/***************************************************************************
*
* 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 oatpp_test_parser_json_mapping_UnorderedSetTest_hpp
#define oatpp_test_parser_json_mapping_UnorderedSetTest_hpp
#include "oatpp-test/UnitTest.hpp"
namespace oatpp { namespace test { namespace parser { namespace json { namespace mapping {
class UnorderedSetTest : public UnitTest{
public:
UnorderedSetTest():UnitTest("TEST[parser::json::mapping::UnorderedSetTest]"){}
void onRun() override;
};
}}}}}
#endif /* oatpp_test_parser_json_mapping_UnorderedSetTest_hpp */

View File

@ -270,10 +270,10 @@ void FullTest::onRun() {
auto dto = response->readBodyToDto<app::TestDto>(objectMapper.get());
OATPP_ASSERT(dto);
OATPP_ASSERT(dto->testMap);
OATPP_ASSERT(dto->testMap->count() == 3);
OATPP_ASSERT(dto->testMap->get("key1", "") == "value1");
OATPP_ASSERT(dto->testMap->get("key2", "") == "32");
OATPP_ASSERT(dto->testMap->get("key3", "") == oatpp::utils::conversion::float32ToStr(0.32f));
OATPP_ASSERT(dto->testMap->size() == 3);
OATPP_ASSERT(dto->testMap["key1"] == "value1");
OATPP_ASSERT(dto->testMap["key2"] == "32");
OATPP_ASSERT(dto->testMap["key3"] == oatpp::utils::conversion::float32ToStr(0.32f));
}
{ // test GET with header parameter
@ -299,7 +299,19 @@ void FullTest::onRun() {
OATPP_ASSERT(response->getStatusCode() == 200);
auto dtoOut = response->readBodyToDto<app::TestDto>(objectMapper.get());
OATPP_ASSERT(dtoOut);
OATPP_ASSERT(dtoOut->testValueInt->getValue() == i);
OATPP_ASSERT(dtoOut->testValueInt == i);
}
{ // test Enum as String
oatpp::Enum<app::AllowedPathParams> v = app::AllowedPathParams::HELLO;
auto response = client->getHeaderEnumAsString(v);
OATPP_ASSERT(response->getStatusCode() == 200);
}
{ // test Enum as String
oatpp::Enum<app::AllowedPathParams> v = app::AllowedPathParams::HELLO;
auto response = client->getHeaderEnumAsNumber(v);
OATPP_ASSERT(response->getStatusCode() == 200);
}
{ // test Big Echo with body

View File

@ -55,7 +55,11 @@ public:
API_CALL("GET", "queries/map", getWithQueriesMap, QUERY(String, key1), QUERY(Int32, key2), QUERY(Float32, key3))
API_CALL("GET", "headers", getWithHeaders, HEADER(String, param, "X-TEST-HEADER"))
API_CALL("POST", "body", postBody, BODY_STRING(String, body))
API_CALL("POST", "body-dto", postBodyDto, BODY_DTO(TestDto::ObjectWrapper, body))
API_CALL("POST", "body-dto", postBodyDto, BODY_DTO(TestDto, body))
API_CALL("GET", "enum/as-string", getHeaderEnumAsString, HEADER(Enum<AllowedPathParams>::AsString, enumValue, "enum"))
API_CALL("GET", "enum/as-number", getHeaderEnumAsNumber, HEADER(Enum<AllowedPathParams>::AsNumber, enumValue, "enum"))
API_CALL("POST", "echo", echoBody, BODY_STRING(String, body))
API_CALL("GET", "header-value-set", headerValueSet, HEADER(String, valueSet, "X-VALUE-SET"))

View File

@ -109,16 +109,16 @@ public:
ENDPOINT("GET", "queries", getWithQueries,
QUERY(String, name), QUERY(Int32, age)) {
auto dto = TestDto::createShared();
dto->testValue = "name=" + name + "&age=" + oatpp::utils::conversion::int32ToStr(age->getValue());
dto->testValue = "name=" + name + "&age=" + oatpp::utils::conversion::int32ToStr(*age);
return createDtoResponse(Status::CODE_200, dto);
}
ENDPOINT("GET", "queries/map", getWithQueriesMap,
QUERIES(QueryParams, queries)) {
auto dto = TestDto::createShared();
dto->testMap = dto->testMap->createShared();
dto->testMap = dto->testMap.createShared();
for(auto& it : queries.getAll()) {
dto->testMap->put(it.first.toString(), it.second.toString());
dto->testMap[it.first.toString()] = it.second.toString();
}
return createDtoResponse(Status::CODE_200, dto);
}
@ -140,7 +140,7 @@ public:
}
ENDPOINT("POST", "body-dto", postBodyDto,
BODY_DTO(TestDto::ObjectWrapper, body)) {
BODY_DTO(TestDto, body)) {
//OATPP_LOGV(TAG, "POST body %s", body->c_str());
return createDtoResponse(Status::CODE_200, body);
}
@ -216,7 +216,7 @@ public:
REQUEST(std::shared_ptr<IncomingRequest>, request))
{
auto body = std::make_shared<oatpp::web::protocol::http::outgoing::StreamingBody>
(std::make_shared<ReadCallback>(text, numIterations->getValue()));
(std::make_shared<ReadCallback>(text, *numIterations));
return OutgoingResponse::createShared(Status::CODE_200, body);
}
@ -282,6 +282,18 @@ public:
return createResponse(Status::CODE_200, "OK");
}
ENDPOINT("GET", "enum/as-string", testEnumString,
HEADER(Enum<AllowedPathParams>::AsString, enumValue, "enum"))
{
return createResponse(Status::CODE_200, "OK");
}
ENDPOINT("GET", "enum/as-number", testEnumNumber,
HEADER(Enum<AllowedPathParams>::AsNumber, enumValue, "enum"))
{
return createResponse(Status::CODE_200, "OK");
}
};

View File

@ -38,10 +38,15 @@ class TestDto : public oatpp::data::mapping::type::Object {
DTO_FIELD(String, testValue);
DTO_FIELD(Int32, testValueInt);
DTO_FIELD(Fields<String>::ObjectWrapper, testMap);
DTO_FIELD(Fields<String>, testMap);
};
ENUM(AllowedPathParams, v_int32,
VALUE(HELLO, 100, "hello"),
VALUE(WORLD, 200, "world")
)
#include OATPP_CODEGEN_END(DTO)
}}}}