// 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 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 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 class IdentifiablePtr : public CloneablePtr { public: IdentifiablePtr(const T &t) : CloneablePtr(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(p) { } IdentifiablePtr(std::unique_ptr &&rhs) noexcept : CloneablePtr(std::move(rhs)) { } IdentifiablePtr &operator=(std::unique_ptr &&rhs) noexcept { CloneablePtr::operator=(std::move(rhs)); return *this; } int cmp(const IdentifiablePtr &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 &rhs) const { return (cmp(rhs) < 0); } bool operator > (const IdentifiablePtr &rhs) const { return (cmp(rhs) > 0); } bool operator == (const IdentifiablePtr &rhs) const { return (cmp(rhs) == 0); } bool operator != (const IdentifiablePtr &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(Identifiable::create(is).release())); } return is; } friend Serializer & operator << (Serializer & os, const IdentifiablePtr & agg) { return agg.serialize(os); } friend Deserializer & operator >> (Deserializer & is, IdentifiablePtr & agg) { return agg.deserialize(is); } }; template class IdentifiableSharedPtr : public std::shared_ptr { public: IdentifiableSharedPtr(const T &t) : std::shared_ptr(t.clone()) {} IdentifiableSharedPtr(T * p=nullptr) : std::shared_ptr(p) { } int cmp(const IdentifiableSharedPtr &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 &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(Identifiable::create(is).release())); } return is; } friend Serializer & operator << (Serializer & os, const IdentifiableSharedPtr & agg) { return agg.serialize(os); } friend Deserializer & operator >> (Deserializer & is, IdentifiableSharedPtr & agg) { return agg.deserialize(is); } }; }