Coverage Report

Created: 2025-12-14 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/oatpp/src/oatpp/data/type/Object.hpp
Line
Count
Source
1
/***************************************************************************
2
 *
3
 * Project         _____    __   ____   _      _
4
 *                (  _  )  /__\ (_  _)_| |_  _| |_
5
 *                 )(_)(  /(__)\  )( (_   _)(_   _)
6
 *                (_____)(__)(__)(__)  |_|    |_|
7
 *
8
 *
9
 * Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
10
 *
11
 * Licensed under the Apache License, Version 2.0 (the "License");
12
 * you may not use this file except in compliance with the License.
13
 * You may obtain a copy of the License at
14
 *
15
 *     http://www.apache.org/licenses/LICENSE-2.0
16
 *
17
 * Unless required by applicable law or agreed to in writing, software
18
 * distributed under the License is distributed on an "AS IS" BASIS,
19
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
 * See the License for the specific language governing permissions and
21
 * limitations under the License.
22
 *
23
 ***************************************************************************/
24
25
#ifndef oatpp_data_type_Object_hpp
26
#define oatpp_data_type_Object_hpp
27
28
#include "./Type.hpp"
29
30
#include "./Tree.hpp"
31
#include "./Any.hpp"
32
#include "./Primitive.hpp"
33
#include "./Enum.hpp"
34
#include "./UnorderedMap.hpp"
35
#include "./PairList.hpp"
36
#include "./List.hpp"
37
#include "./Vector.hpp"
38
#include "./UnorderedSet.hpp"
39
40
#include "oatpp/base/Countable.hpp"
41
42
#include <type_traits>
43
44
namespace oatpp { namespace data { namespace type {
45
46
/**
47
 * Base class of all object-like mapping-enabled structures ex.: oatpp::DTO.
48
 */
49
class BaseObject : public oatpp::base::Countable {
50
public:
51
52
  /**
53
   * Class to map object properties.
54
   */
55
  class Property {
56
  public:
57
58
    /**
59
     * Property Type Selector.
60
     */
61
    class TypeSelector {
62
    public:
63
64
      /**
65
       * Default destructor.
66
       */
67
      virtual ~TypeSelector() = default;
68
69
      /**
70
       * Select property type.
71
       * @param self - pointer to `this` object.
72
       * @return - &id:oatpp::Type;.
73
       */
74
      virtual const type::Type* selectType(BaseObject* self) = 0;
75
    };
76
77
    template<class DTOType>
78
    class FieldTypeSelector : public TypeSelector {
79
    public:
80
81
      const type::Type* selectType(BaseObject* self) override {
82
        return selectFieldType(static_cast<DTOType*>(self));
83
      }
84
85
      virtual const type::Type* selectFieldType(DTOType* self) = 0;
86
87
    };
88
89
  public:
90
91
    /**
92
     * Editional Info about Property.
93
     */
94
    struct Info {
95
96
      /**
97
       * Description.
98
       */
99
      std::string description = "";
100
101
      /**
102
       * Pattern.
103
       */
104
      std::string pattern = "";
105
106
      /**
107
       * Required.
108
       */
109
      bool required = false;
110
111
      /**
112
       * Type selector.
113
       * &l:Property::TypeSelector;.
114
       */
115
      TypeSelector* typeSelector = nullptr;
116
117
    };
118
119
  private:
120
    const v_int64 offset;
121
  public:
122
123
    /**
124
     * Constructor.
125
     * @param pOffset - memory offset of object field from object start address.
126
     * @param pName - name of the property.
127
     * @param pUName - unqualified name of the property. Name of the class field in the code.
128
     * @param pType - &l:Type; of the property.
129
     */
130
    Property(v_int64 pOffset, std::string pName, std::string pUName, const Type* pType);
131
132
    /**
133
     * Property name.
134
     */
135
    const std::string name;
136
137
    /**
138
     * Unqualified property name.
139
     * Name of the class field that is used in the code.
140
     */
141
    const std::string unqualifiedName;
142
143
    /**
144
     * Property type.
145
     */
146
    const Type* const type;
147
148
    /**
149
     * Property additional info.
150
     */
151
    Info info;
152
153
    /**
154
     * Set value of object field mapped by this property.
155
     * @param object - object address.
156
     * @param value - value to set.
157
     */
158
    void set(BaseObject* object, const Void& value) const;
159
160
    /**
161
     * Get value of object field mapped by this property.
162
     * @param object - object address.
163
     * @return - value of the field.
164
     */
165
    Void get(BaseObject* object) const;
166
167
    /**
168
     * Get reference to ObjectWrapper of the object field.
169
     * @param object - object address.
170
     * @return - reference to ObjectWrapper of the object field.
171
     */
172
    Void& getAsRef(BaseObject* object) const;
173
174
  };
175
176
  /**
177
   * Object type properties table.
178
   */
179
  class Properties {
180
  private:
181
    std::unordered_map<std::string, Property*> m_map;
182
    std::unordered_map<std::string, Property*> m_unqualifiedMap;
183
    std::list<Property*> m_list;
184
  public:
185
186
    /**
187
     * Add property to the end of the list.
188
     * @param property
189
     */
190
    Property* pushBack(Property* property);
191
192
    /**
193
     * Add all properties to the beginning of the list.
194
     * @param properties
195
     */
196
    void pushFrontAll(Properties* properties);
197
198
    /**
199
     * Get properties as unordered map for random access.
200
     * @return reference to std::unordered_map of std::string to &id:oatpp::data::type::BaseObject::Property;*.
201
     */
202
    const std::unordered_map<std::string, Property*>& getMap() const;
203
204
    /**
205
     * Get properties as unordered map for random access by unqualified names.
206
     * @return reference to std::unordered_map of std::string to &id:oatpp::data::type::BaseObject::Property;*.
207
     */
208
    const std::unordered_map<std::string, Property*>& getUnqualifiedMap() const;
209
210
    /**
211
     * Get properties in ordered way.
212
     * @return std::list of &id:oatpp::data::type::BaseObject::Property;*.
213
     */
214
    const std::list<Property*>& getList() const;
215
216
  };
217
218
private:
219
  void* m_basePointer = this;
220
private:
221
  void set(v_int64 offset, const Void& value);
222
  Void get(v_int64 offset) const;
223
  Void& getAsRef(v_int64 offset) const;
224
protected:
225
  void setBasePointer(void* basePointer);
226
  void* getBasePointer() const;
227
};
228
229
namespace __class {
230
231
  /**
232
   * AbstractObject class.
233
   */
234
  class AbstractObject {
235
  public:
236
237
    class PolymorphicDispatcher {
238
    public:
239
      
240
3
      virtual ~PolymorphicDispatcher() = default;
241
242
      virtual type::Void createObject() const = 0;
243
244
      virtual const type::BaseObject::Properties* getProperties() const = 0;
245
246
    };
247
248
  public:
249
250
    /**
251
     * Class id.
252
     */
253
    static const ClassId CLASS_ID;
254
255
  };
256
257
  /**
258
   * Template for Object class of type T.
259
   * @tparam T - object type.
260
   */
261
  template<class T>
262
  class Object : public AbstractObject {
263
  public:
264
265
    class PolymorphicDispatcher : public AbstractObject::PolymorphicDispatcher {
266
    public:
267
268
3.31k
      type::Void createObject() const override {
269
3.31k
        return type::Void(std::make_shared<T>(), getType());
270
3.31k
      }
oatpp::data::type::__class::Object<Test1>::PolymorphicDispatcher::createObject() const
Line
Count
Source
268
3.30k
      type::Void createObject() const override {
269
3.30k
        return type::Void(std::make_shared<T>(), getType());
270
3.30k
      }
oatpp::data::type::__class::Object<Empty>::PolymorphicDispatcher::createObject() const
Line
Count
Source
268
16
      type::Void createObject() const override {
269
16
        return type::Void(std::make_shared<T>(), getType());
270
16
      }
Unexecuted instantiation: oatpp::data::type::__class::Object<oatpp::data::type::DTO>::PolymorphicDispatcher::createObject() const
271
272
5.48k
      const type::BaseObject::Properties* getProperties() const override {
273
5.48k
        return propertiesGetter();
274
5.48k
      }
oatpp::data::type::__class::Object<Empty>::PolymorphicDispatcher::getProperties() const
Line
Count
Source
272
28
      const type::BaseObject::Properties* getProperties() const override {
273
28
        return propertiesGetter();
274
28
      }
Unexecuted instantiation: oatpp::data::type::__class::Object<oatpp::data::type::DTO>::PolymorphicDispatcher::getProperties() const
oatpp::data::type::__class::Object<Test1>::PolymorphicDispatcher::getProperties() const
Line
Count
Source
272
5.45k
      const type::BaseObject::Properties* getProperties() const override {
273
5.45k
        return propertiesGetter();
274
5.45k
      }
275
276
    };
277
278
  private:
279
280
2
    static type::BaseObject::Properties* initProperties() {
281
282
      /* initializer */
283
2
      T obj;
284
285
      /* init parent properties */
286
2
      auto parentType = Object<typename T::Z__CLASS_EXTENDED>::getType();
287
2
      if(parentType->parent != nullptr) {
288
0
        auto dispatcher = static_cast<const AbstractObject::PolymorphicDispatcher*>(parentType->polymorphicDispatcher);
289
0
        dispatcher->getProperties();
290
0
      }
291
292
      /* extend parent properties */
293
2
      T::Z__CLASS_EXTEND(T::Z__CLASS::Z__CLASS_GET_FIELDS_MAP(), T::Z__CLASS_EXTENDED::Z__CLASS_GET_FIELDS_MAP());
294
295
2
      return T::Z__CLASS::Z__CLASS_GET_FIELDS_MAP();
296
297
2
    }
oatpp::data::type::__class::Object<Empty>::initProperties()
Line
Count
Source
280
1
    static type::BaseObject::Properties* initProperties() {
281
282
      /* initializer */
283
1
      T obj;
284
285
      /* init parent properties */
286
1
      auto parentType = Object<typename T::Z__CLASS_EXTENDED>::getType();
287
1
      if(parentType->parent != nullptr) {
288
0
        auto dispatcher = static_cast<const AbstractObject::PolymorphicDispatcher*>(parentType->polymorphicDispatcher);
289
0
        dispatcher->getProperties();
290
0
      }
291
292
      /* extend parent properties */
293
1
      T::Z__CLASS_EXTEND(T::Z__CLASS::Z__CLASS_GET_FIELDS_MAP(), T::Z__CLASS_EXTENDED::Z__CLASS_GET_FIELDS_MAP());
294
295
1
      return T::Z__CLASS::Z__CLASS_GET_FIELDS_MAP();
296
297
1
    }
Unexecuted instantiation: oatpp::data::type::__class::Object<oatpp::data::type::DTO>::initProperties()
oatpp::data::type::__class::Object<Test1>::initProperties()
Line
Count
Source
280
1
    static type::BaseObject::Properties* initProperties() {
281
282
      /* initializer */
283
1
      T obj;
284
285
      /* init parent properties */
286
1
      auto parentType = Object<typename T::Z__CLASS_EXTENDED>::getType();
287
1
      if(parentType->parent != nullptr) {
288
0
        auto dispatcher = static_cast<const AbstractObject::PolymorphicDispatcher*>(parentType->polymorphicDispatcher);
289
0
        dispatcher->getProperties();
290
0
      }
291
292
      /* extend parent properties */
293
1
      T::Z__CLASS_EXTEND(T::Z__CLASS::Z__CLASS_GET_FIELDS_MAP(), T::Z__CLASS_EXTENDED::Z__CLASS_GET_FIELDS_MAP());
294
295
1
      return T::Z__CLASS::Z__CLASS_GET_FIELDS_MAP();
296
297
1
    }
298
299
5.48k
    static const BaseObject::Properties* propertiesGetter() {
300
5.48k
      static type::BaseObject::Properties* properties = initProperties();
301
5.48k
      return properties;
302
5.48k
    }
oatpp::data::type::__class::Object<Empty>::propertiesGetter()
Line
Count
Source
299
28
    static const BaseObject::Properties* propertiesGetter() {
300
28
      static type::BaseObject::Properties* properties = initProperties();
301
28
      return properties;
302
28
    }
Unexecuted instantiation: oatpp::data::type::__class::Object<oatpp::data::type::DTO>::propertiesGetter()
oatpp::data::type::__class::Object<Test1>::propertiesGetter()
Line
Count
Source
299
5.45k
    static const BaseObject::Properties* propertiesGetter() {
300
5.45k
      static type::BaseObject::Properties* properties = initProperties();
301
5.45k
      return properties;
302
5.45k
    }
303
304
3
    static std::unique_ptr<Type> createType() {
305
3
      Type::Info info;
306
3
      info.nameQualifier = T::Z__CLASS_TYPE_NAME();
307
3
      static std::unique_ptr<PolymorphicDispatcher> disp(new PolymorphicDispatcher());
308
3
      info.polymorphicDispatcher = disp.get();
309
3
      info.parent = T::getParentType();
310
3
      return std::unique_ptr<Type>(new Type(CLASS_ID, info));
311
3
    }
oatpp::data::type::__class::Object<Test1>::createType()
Line
Count
Source
304
1
    static std::unique_ptr<Type> createType() {
305
1
      Type::Info info;
306
1
      info.nameQualifier = T::Z__CLASS_TYPE_NAME();
307
1
      static std::unique_ptr<PolymorphicDispatcher> disp(new PolymorphicDispatcher());
308
1
      info.polymorphicDispatcher = disp.get();
309
1
      info.parent = T::getParentType();
310
1
      return std::unique_ptr<Type>(new Type(CLASS_ID, info));
311
1
    }
oatpp::data::type::__class::Object<Empty>::createType()
Line
Count
Source
304
1
    static std::unique_ptr<Type> createType() {
305
1
      Type::Info info;
306
1
      info.nameQualifier = T::Z__CLASS_TYPE_NAME();
307
1
      static std::unique_ptr<PolymorphicDispatcher> disp(new PolymorphicDispatcher());
308
1
      info.polymorphicDispatcher = disp.get();
309
1
      info.parent = T::getParentType();
310
1
      return std::unique_ptr<Type>(new Type(CLASS_ID, info));
311
1
    }
oatpp::data::type::__class::Object<oatpp::data::type::DTO>::createType()
Line
Count
Source
304
1
    static std::unique_ptr<Type> createType() {
305
1
      Type::Info info;
306
1
      info.nameQualifier = T::Z__CLASS_TYPE_NAME();
307
1
      static std::unique_ptr<PolymorphicDispatcher> disp(new PolymorphicDispatcher());
308
1
      info.polymorphicDispatcher = disp.get();
309
1
      info.parent = T::getParentType();
310
1
      return std::unique_ptr<Type>(new Type(CLASS_ID, info));
311
1
    }
312
313
  public:
314
315
    /**
316
     * Get type describing this class.
317
     * @return - &id:oatpp::data::type::Type;
318
     */
319
18.6k
    static Type* getType() {
320
18.6k
      static std::unique_ptr<Type> type = createType();
321
18.6k
      return type.get();
322
18.6k
    }
oatpp::data::type::__class::Object<Test1>::getType()
Line
Count
Source
319
15.3k
    static Type* getType() {
320
15.3k
      static std::unique_ptr<Type> type = createType();
321
15.3k
      return type.get();
322
15.3k
    }
oatpp::data::type::__class::Object<Empty>::getType()
Line
Count
Source
319
3.32k
    static Type* getType() {
320
3.32k
      static std::unique_ptr<Type> type = createType();
321
3.32k
      return type.get();
322
3.32k
    }
oatpp::data::type::__class::Object<oatpp::data::type::DTO>::getType()
Line
Count
Source
319
4
    static Type* getType() {
320
4
      static std::unique_ptr<Type> type = createType();
321
4
      return type.get();
322
4
    }
323
    
324
  };
325
  
326
}
327
328
/**
329
 * ObjectWrapper for &l:DTO;. AKA `oatpp::Object<T>`.
330
 * @tparam ObjT - class extended from &l:DTO;.
331
 */
332
template<class ObjT>
333
class DTOWrapper : public ObjectWrapper<ObjT, __class::Object<ObjT>> {
334
  template<class Type>
335
  friend class DTOWrapper;
336
public:
337
  typedef ObjT TemplateObjectType;
338
  typedef __class::Object<ObjT> TemplateObjectClass;
339
public:
340
341
  OATPP_DEFINE_OBJECT_WRAPPER_DEFAULTS(DTOWrapper, TemplateObjectType, TemplateObjectClass)
342
343
  template<class OtherT>
344
  DTOWrapper(const OtherT& other)
345
    : type::ObjectWrapper<ObjT, __class::Object<ObjT>>(other.m_ptr)
346
  {}
347
348
  template<class OtherT>
349
  DTOWrapper(OtherT&& other)
350
    : type::ObjectWrapper<ObjT, __class::Object<ObjT>>(std::move(other.m_ptr))
351
  {}
352
353
  static DTOWrapper createShared() {
354
    return std::make_shared<TemplateObjectType>();
355
  }
356
357
  template<class T>
358
  DTOWrapper& operator = (const DTOWrapper<T>& other) {
359
    this->m_ptr = other.m_ptr;
360
    return *this;
361
  }
362
363
  template<class T>
364
  DTOWrapper& operator = (DTOWrapper<T>&& other) {
365
    this->m_ptr = std::move(other.m_ptr);
366
    return *this;
367
  }
368
369
  template<typename T,
370
    typename enabled = typename std::enable_if<std::is_same<T, std::nullptr_t>::value, void>::type
371
  >
372
  inline bool operator == (T){
373
    return this->m_ptr.get() == nullptr;
374
  }
375
376
  template<typename T,
377
    typename enabled = typename std::enable_if<std::is_same<T, std::nullptr_t>::value, void>::type
378
  >
379
  inline bool operator != (T){
380
    return this->m_ptr.get() != nullptr;
381
  }
382
383
  template<typename T,
384
    typename enabled = typename std::enable_if<std::is_same<T, DTOWrapper>::value, void>::type
385
  >
386
  inline bool operator == (const T &other) const {
387
    if(this->m_ptr.get() == other.m_ptr.get()) return true;
388
    if(!this->m_ptr || !other.m_ptr) return false;
389
    return *this->m_ptr == *other.m_ptr;
390
  }
391
392
  template<typename T,
393
    typename enabled = typename std::enable_if<std::is_same<T, DTOWrapper>::value, void>::type
394
  >
395
  inline bool operator != (const T &other) const {
396
    return !operator == (other);
397
  }
398
399
  static const std::unordered_map<std::string, BaseObject::Property*>& getPropertiesMap() {
400
    auto dispatcher = static_cast<const __class::AbstractObject::PolymorphicDispatcher*>(
401
      __class::Object<ObjT>::getType()->polymorphicDispatcher
402
    );
403
    return dispatcher->getProperties()->getMap();
404
  }
405
406
  static const std::list<BaseObject::Property*>& getPropertiesList() {
407
    auto dispatcher = static_cast<const __class::AbstractObject::PolymorphicDispatcher*>(
408
      __class::Object<ObjT>::getType()->polymorphicDispatcher
409
    );
410
    return dispatcher->getProperties()->getList();
411
  }
412
413
  static v_int64 getPropertiesCount() {
414
    auto dispatcher = static_cast<const __class::AbstractObject::PolymorphicDispatcher*>(
415
      __class::Object<ObjT>::getType()->polymorphicDispatcher
416
    );
417
    return static_cast<v_int64>(dispatcher->getProperties()->getList().size());
418
  }
419
420
  ObjectWrapper<void>& operator[](const std::string& propertyName) {
421
    return getPropertiesMap().at(propertyName)->getAsRef(this->m_ptr.get());
422
  }
423
424
};
425
426
/**
427
 * Base class for all DTO objects.
428
 * For more info about Data Transfer Object (DTO) see [Data Transfer Object (DTO)](https://oatpp.io/docs/components/dto/).
429
 */
430
class DTO : public BaseObject {
431
  template<class T>
432
  friend class __class::Object;
433
private:
434
  typedef DTO Z__CLASS;
435
  typedef DTO Z__CLASS_EXTENDED;
436
public:
437
  typedef oatpp::data::type::Void Void;
438
  typedef oatpp::data::type::Any Any;
439
  typedef oatpp::data::type::Tree Tree;
440
  typedef oatpp::data::type::String String;
441
  typedef oatpp::data::type::Int8 Int8;
442
  typedef oatpp::data::type::UInt8 UInt8;
443
  typedef oatpp::data::type::Int16 Int16;
444
  typedef oatpp::data::type::UInt16 UInt16;
445
  typedef oatpp::data::type::Int32 Int32;
446
  typedef oatpp::data::type::UInt32 UInt32;
447
  typedef oatpp::data::type::Int64 Int64;
448
  typedef oatpp::data::type::UInt64 UInt64;
449
  typedef oatpp::data::type::Float32 Float32;
450
  typedef oatpp::data::type::Float64 Float64;
451
  typedef oatpp::data::type::Boolean Boolean;
452
453
  template <class T>
454
  using Object = DTOWrapper<T>;
455
456
  template <class T>
457
  using Enum = oatpp::data::type::Enum<T>;
458
459
  template <class T>
460
  using Vector = oatpp::data::type::Vector<T>;
461
462
  template <class T>
463
  using UnorderedSet = oatpp::data::type::UnorderedSet<T>;
464
465
  template <class T>
466
  using List = oatpp::data::type::List<T>;
467
468
  template <class Value>
469
  using Fields = oatpp::data::type::PairList<String, Value>;
470
471
  template <class Value>
472
  using UnorderedFields = oatpp::data::type::UnorderedMap<String, Value>;
473
474
private:
475
  static const type::Type* getParentType();
476
  static const char* Z__CLASS_TYPE_NAME();
477
  static data::type::BaseObject::Properties* Z__CLASS_GET_FIELDS_MAP();
478
  static BaseObject::Properties* Z__CLASS_EXTEND(BaseObject::Properties* properties, BaseObject::Properties* extensionProperties);
479
public:
480
481
0
  virtual v_uint64 defaultHashCode() const {
482
0
    return reinterpret_cast<v_uint64>(this);
483
0
  }
484
485
0
  virtual bool defaultEquals(const DTO& other) const {
486
0
    return this == &other;
487
0
  }
488
489
0
  v_uint64 hashCode() const {
490
0
    return defaultHashCode();
491
0
  }
492
493
0
  bool operator==(const DTO& other) const {
494
0
    return defaultEquals(other);
495
0
  }
496
497
};
498
  
499
}}}
500
501
namespace std {
502
503
  template<class T>
504
  struct hash<oatpp::data::type::DTOWrapper<T>> {
505
506
    typedef oatpp::data::type::DTOWrapper<T> argument_type;
507
    typedef v_uint64 result_type;
508
509
    result_type operator()(argument_type const &ow) const noexcept {
510
      if(ow) {
511
        return ow->hashCode();
512
      }
513
      return 0;
514
    }
515
516
  };
517
518
}
519
520
#endif /* oatpp_data_type_Object_hpp */