aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/vespa/vespalib/objects/identifiable.hpp
blob: d86f5490bc998695f119819c8962ca790854c71a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#pragma once
/**
 * \class vespalib::Identifiable
 * \ingroup util
 *
 * \brief Superclass for objects adding some runtime type information.
 *
 * This class is a superclass used by many other classes to add some runtime
 * information.
 *
 * This can be used to verify type to be able to do cheap static casts
 * instead of dynamic casts. It can be used to identify type of object, and
 * it can also be used to generate an object of the given type (If it's not
 * an identifiable abstract type).
 *
 */

#include "identifiable.h"

namespace vespalib {

template <typename T>
Serializer & Identifiable::serialize(const T & v, Serializer & os) {
    uint32_t sz(v.size());
    os.put(sz);
    for(size_t i(0); i < sz; i++) {
        v[i].serialize(os);
    }
    return os;
}

template <typename T>
Deserializer & Identifiable::deserialize(T & v, Deserializer & is) {
    uint32_t sz(0);
    is.get(sz);
    v.resize(sz);
    for(size_t i(0); i < sz; i++) {
        v[i].deserialize(is);
    }
    return is;
}

template <typename T>
class IdentifiablePtr : public CloneablePtr<T>
{
public:
    IdentifiablePtr(const T &t) : CloneablePtr<T>(t.clone()) {}
    IdentifiablePtr(IdentifiablePtr &&) noexcept = default;
    IdentifiablePtr & operator = (IdentifiablePtr &&) noexcept = default;
    IdentifiablePtr(const IdentifiablePtr &) = default;
    IdentifiablePtr & operator = (const IdentifiablePtr &) = default;
    IdentifiablePtr(T * p=nullptr) noexcept : CloneablePtr<T>(p) { }
    IdentifiablePtr(std::unique_ptr<T> &&rhs) noexcept
        : CloneablePtr<T>(std::move(rhs))
    {
    }
    IdentifiablePtr &operator=(std::unique_ptr<T> &&rhs) noexcept
    {
        CloneablePtr<T>::operator=(std::move(rhs));
        return *this;
    }
    int cmp(const IdentifiablePtr<T> &rhs) const {
        const T *a = this->get();
        const T *b = rhs.get();
        if (a == 0) {
            return (b == 0) ? 0 : -1;
        }
        return (b == 0) ? 1 : a->cmp(*b);
    }
    bool operator  < (const IdentifiablePtr<T> &rhs) const { return (cmp(rhs) < 0); }
    bool operator  > (const IdentifiablePtr<T> &rhs) const { return (cmp(rhs) > 0); }
    bool operator == (const IdentifiablePtr<T> &rhs) const { return (cmp(rhs) == 0); }
    bool operator != (const IdentifiablePtr<T> &rhs) const { return (cmp(rhs) != 0); }
    Serializer & serialize(Serializer & os) const {
        if (this->get()) {
            os.put(uint8_t(1)) << *this->get();
        } else {
            os.put(uint8_t(0));
        }
        return os;
    }
    Deserializer & deserialize(Deserializer & is) {
        uint8_t hasObject;
        is.get(hasObject);
        if (hasObject) {
            this->reset(static_cast<T *>(Identifiable::create(is).release()));
        }
        return is;
    }
    friend Serializer & operator << (Serializer & os, const IdentifiablePtr<T> & agg) { return agg.serialize(os); }
    friend Deserializer & operator >> (Deserializer & is, IdentifiablePtr<T> & agg)   { return agg.deserialize(is); }
};

template <typename T>
class IdentifiableSharedPtr : public std::shared_ptr<T>
{
public:
    IdentifiableSharedPtr(const T &t) : std::shared_ptr<T>(t.clone()) {}
    IdentifiableSharedPtr(T * p=nullptr) : std::shared_ptr<T>(p) { }
    int cmp(const IdentifiableSharedPtr<T> &rhs) const {
        const T *a = this->get();
        const T *b = rhs.get();
        if (a == 0) {
            return (b == 0) ? 0 : -1;
        }
        return (b == 0) ? 1 : a->cmp(*b);
    }
    bool operator < (const IdentifiableSharedPtr<T> &rhs) const {
        return (cmp(rhs) < 0);
    }
    Serializer & serialize(Serializer & os) const {
        if (this->get()) {
            os.put(uint8_t(1)) << *this->get();
        } else {
            os.put(uint8_t(0));
        }
        return os;
    }
    Deserializer & deserialize(Deserializer & is) {
        uint8_t hasObject;
        is.get(hasObject);
        if (hasObject) {
            reset(static_cast<T *>(Identifiable::create(is).release()));
        }
        return is;
    }
    friend Serializer & operator << (Serializer & os, const IdentifiableSharedPtr<T> & agg) { return agg.serialize(os); }
    friend Deserializer & operator >> (Deserializer & is, IdentifiableSharedPtr<T> & agg)   { return agg.deserialize(is); }
};

}