Commit e472c69c authored by Thibault Lemaire's avatar Thibault Lemaire
Browse files

feat: use castToConst in RegistrarDbInternal::getAllRecords

fix: castToConst for unsupported types was always valid
Showing with 108 additions and 35 deletions
/** Copyright (C) 2010-2023 Belledonne Communications SARL
/** Copyright (C) 2010-2024 Belledonne Communications SARL
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
......@@ -10,16 +10,22 @@
namespace type {
template <typename, typename = void>
constexpr bool is_iterable{};
constexpr bool is_iterable = false;
template <typename T>
constexpr bool is_iterable<T, std::void_t<decltype(std::declval<T>().begin()), decltype(std::declval<T>().end())>> =
true;
template <typename, typename = void>
constexpr bool is_streamable{};
constexpr bool is_streamable = false;
template <typename T>
constexpr bool is_streamable<T, std::void_t<decltype(std::declval<std::ostream>() << std::declval<T>())>> = true;
template <typename, typename = void>
constexpr bool is_dereferencable = false;
template <typename T>
constexpr bool is_dereferencable<T, std::void_t<decltype(*std::declval<T>())>> = true;
} // namespace type
......@@ -373,7 +373,7 @@ void RelayedCall::configureRelayChannel(shared_ptr<RelayChannel> ms, sip_t* sip,
#endif
}
const std::array<const std::shared_ptr<const RelaySession>, RelayedCall::sMaxSessions>&
const std::array<std::shared_ptr<const RelaySession>, RelayedCall::sMaxSessions>&
RelayedCall::getSessions() const {
return castToConst(mSessions);
}
......@@ -90,7 +90,7 @@ public:
return mServer;
}
const std::array<const std::shared_ptr<const RelaySession>, sMaxSessions>& getSessions() const;
const std::array<std::shared_ptr<const RelaySession>, sMaxSessions>& getSessions() const;
private:
void setupSpecificRelayTransport(RelayTransport* rt, const char* destHost);
......
......@@ -177,7 +177,7 @@ public:
mLocalRegExpire.getRegisteredAors(aors);
}
const std::multimap<const std::string, const std::weak_ptr<const ContactRegisteredListener>>&
const std::multimap<std::string, std::weak_ptr<const ContactRegisteredListener>>&
getOnContactRegisteredListeners() const {
return castToConst(mContactListenersMap);
}
......
......@@ -44,9 +44,7 @@ public:
* Read-only access to the stored records. As of 2023-07-05, only used in tests
*/
const auto& getAllRecords() const {
// reinterpret_cast is safe here because we're *adding* constness to the pointers.
// (As long as the container type is the same as that of mRecords)
return reinterpret_cast<const std::unordered_map<std::string, std::shared_ptr<const Record>>&>(mRecords);
return castToConst(mRecords);
}
bool isWritable() const override {
......
/** Copyright (C) 2010-2023 Belledonne Communications SARL
/** Copyright (C) 2010-2024 Belledonne Communications SARL
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
......@@ -16,52 +16,60 @@
#pragma once
#include <array>
#include <map>
#include <memory>
#include <type_traits>
#include <unordered_map>
namespace flexisip {
template <typename, typename = void>
constexpr bool is_dereferencable{};
constexpr bool is_interior_const = true;
template <typename T>
constexpr bool is_dereferencable<T, std::void_t<decltype(*std::declval<T>())>> = true;
constexpr bool
is_interior_const<T, std::void_t<decltype(*std::declval<T>() = std::declval<decltype(*std::declval<T>())>())>> =
false;
template <typename, typename = void>
constexpr bool is_iterable{};
template <typename T>
struct add_interior_const {
static_assert(is_interior_const<T>);
using type = T;
};
template <typename T>
constexpr bool is_iterable<T, std::void_t<decltype(std::declval<T>().begin()), decltype(std::declval<T>().end())>> =
true;
using add_interior_const_t = typename add_interior_const<T>::type;
template <typename T, typename = std::enable_if<!is_dereferencable<T> && !is_iterable<T>>>
const T& castToConst(const T& t) {
return t;
}
template <template <typename...> class Tmpl, typename... Args>
struct add_interior_const<Tmpl<Args...>> {
static_assert(is_interior_const<Tmpl<Args...>>);
using type = Tmpl<add_interior_const_t<Args>...>;
};
template <typename T>
using DeepConstType = std::remove_reference_t<decltype(castToConst(std::declval<T>()))>;
struct add_interior_const<std::unique_ptr<T>> {
using type = std::unique_ptr<std::add_const_t<add_interior_const_t<T>>>;
};
template <typename T>
const std::shared_ptr<DeepConstType<T>>& castToConst(const std::shared_ptr<T>& ptr) {
return reinterpret_cast<decltype(castToConst(ptr))>(ptr);
}
struct add_interior_const<std::weak_ptr<T>> {
using type = std::weak_ptr<std::add_const_t<add_interior_const_t<T>>>;
};
template <typename T>
const std::weak_ptr<DeepConstType<T>>& castToConst(const std::weak_ptr<T>& ptr) {
return reinterpret_cast<decltype(castToConst(ptr))>(ptr);
}
struct add_interior_const<std::shared_ptr<T>> {
using type = std::shared_ptr<std::add_const_t<add_interior_const_t<T>>>;
};
template <typename T, std::size_t Size>
const std::array<DeepConstType<T>, Size>& castToConst(const std::array<T, Size>& array) {
return reinterpret_cast<decltype(castToConst(array))>(array);
}
template <typename T, std::size_t S>
struct add_interior_const<std::array<T, S>> {
using type = std::array<add_interior_const_t<T>, S>;
};
template <typename TKey, typename TValue>
const std::multimap<DeepConstType<TKey>, DeepConstType<TValue>>& castToConst(const std::multimap<TKey, TValue>& array) {
return reinterpret_cast<decltype(castToConst(array))>(array);
template <typename T>
const add_interior_const_t<T>& castToConst(const T& t) {
return reinterpret_cast<const add_interior_const_t<T>&>(t);
}
} // namespace flexisip
......@@ -108,6 +108,7 @@ add_executable(flexisip_tester
tests/registrar/registrardb-tester.cc
tests/registrar/registrardb-redis-tester.cc
tests/sofia-wrapper/home-tester.cc
tests/utils/cast-to-const-tester.cc
tests/utils/flow-data-tester.cc
tests/utils/flow-factory-tester.cc
tests/utils/flow-tester.cc
......
/*
Flexisip, a flexible SIP proxy server with media capabilities.
Copyright (C) 2010-2024 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "utils/cast-to-const.hh"
#include <string>
#include <vector>
namespace flexisip::tester {
namespace {
using namespace std;
static_assert(is_interior_const<int>);
static_assert(is_interior_const<char>);
static_assert(is_interior_const<const int>);
static_assert(is_interior_const<const int&>);
static_assert(is_interior_const<int&>);
static_assert(!is_interior_const<int*>);
static_assert(!is_interior_const<int* const>);
static_assert(is_interior_const<int const*>);
static_assert(!is_interior_const<const unique_ptr<int>>);
static_assert(is_interior_const<unique_ptr<const int>>);
static_assert(is_interior_const<string>);
static_assert(is_interior_const<string>);
static_assert(is_interior_const<array<int, 3>>);
static_assert(is_same_v<add_interior_const_t<int>, int>);
static_assert(is_same_v<add_interior_const_t<unique_ptr<int>>, unique_ptr<const int>>);
static_assert(is_same_v<add_interior_const_t<vector<int>>, vector<int>>);
static_assert(is_same_v<add_interior_const_t<array<int, 4>>, array<int, 4>>);
static_assert(is_same_v<add_interior_const_t<array<weak_ptr<int>, 4>>, array<weak_ptr<const int>, 4>>);
static_assert(is_same_v<add_interior_const_t<weak_ptr<int>>, weak_ptr<const int>>);
static_assert(is_same_v<add_interior_const_t<weak_ptr<weak_ptr<int>>>, weak_ptr<const weak_ptr<const int>>>);
static_assert(is_same_v<add_interior_const_t<shared_ptr<int>>, shared_ptr<const int>>);
static_assert(is_same_v<add_interior_const_t<vector<weak_ptr<int>>>, vector<weak_ptr<const int>>>);
static_assert(is_same_v<add_interior_const_t<vector<shared_ptr<int>>>, vector<shared_ptr<const int>>>);
static_assert(is_same_v<add_interior_const_t<char>, char>);
static_assert(is_same_v<basic_string<char, char_traits<char>, allocator<char>>, string>);
static_assert(is_same_v<add_interior_const_t<string>, string>);
static_assert(is_same_v<add_interior_const_t<multimap<string, int>>, multimap<string, int>>);
static_assert(is_same_v<add_interior_const_t<multimap<string, weak_ptr<int>>>, multimap<string, weak_ptr<const int>>>);
} // namespace
} // namespace flexisip::tester
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment