Commit e0b2b412 authored by Ronan's avatar Ronan

Many things:

  - Provide a StaticString object to build const char* at compile time
  - Use StaticString in MainDb to transforms enum in const char* automatically (events filters)
  - In future: Abuse of this component in MainDb to build queries easily between Mysql/Sqlite3
parent 07b33a41
......@@ -114,6 +114,8 @@ std::unique_ptr<T> makeUnique(Args && ...args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
#define L_AUTO_RETURN(VALUE) -> decltype(VALUE) { return VALUE; }
// -----------------------------------------------------------------------------
// Class tools.
// -----------------------------------------------------------------------------
......@@ -259,17 +261,13 @@ namespace Private {
template<typename... Args>
struct ResolveMemberFunctionOverload {
template<typename Ret, typename Obj>
constexpr auto operator() (Ret (Obj::*func)(Args...)) const -> decltype(func) {
return func;
}
constexpr auto operator() (Ret (Obj::*func)(Args...)) const L_AUTO_RETURN(func);
};
template<typename... Args>
struct ResolveConstMemberFunctionOverload {
template<typename Ret, typename Obj>
constexpr auto operator() (Ret (Obj::*func)(Args...) const) const -> decltype(func) {
return func;
}
constexpr auto operator() (Ret (Obj::*func)(Args...) const) L_AUTO_RETURN(func);
};
template<typename... Args>
......@@ -278,9 +276,7 @@ namespace Private {
using ResolveConstMemberFunctionOverload<Args...>::operator();
template<typename Ret>
constexpr auto operator() (Ret (*func)(Args...)) const -> decltype(func) {
return func;
}
constexpr auto operator() (Ret (*func)(Args...)) const L_AUTO_RETURN(func);
};
}
......@@ -288,6 +284,40 @@ namespace Private {
template<typename... Args>
using resolveOverload = Private::ResolveOverload<Args...>;
// -----------------------------------------------------------------------------
// Math.
// -----------------------------------------------------------------------------
// Get the length of one integer.
constexpr int getIntLength (int n) {
return n < 0 ? 1 + getIntLength(-n) : (n < 10 ? 1 : 1 + getIntLength(n / 10));
}
namespace Private {
constexpr int pow10Impl (int n, int acc) {
return n == 0 ? acc : pow10Impl(n - 1, acc * 10);
}
}
template<typename T>
constexpr T abs (const T &value) {
return value < 0 ? -value : value;
}
constexpr int pow10 (int n) {
return (n < 0 ? -1 : +1) * Private::pow10Impl(abs(n), 1);
}
// Returns the sum of n elements.
constexpr int sums () {
return 0;
}
template<typename T, typename... Args>
constexpr int sums (T i, Args... args) {
return i + sums(args...);
}
// -----------------------------------------------------------------------------
// Wrapper public.
// -----------------------------------------------------------------------------
......
/*
* static-string.h
* Copyright (C) 2010-2018 Belledonne Communications SARL
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _L_STATIC_STRING_H_
#define _L_STATIC_STRING_H_
#include "linphone/utils/general.h"
// =============================================================================
// Compile time strings. Useful to build const char * at compilation.
// =============================================================================
LINPHONE_BEGIN_NAMESPACE
template<std::size_t...>
struct IndexSequence {
using Type = IndexSequence;
};
namespace Private {
template<typename S1, typename S2>
struct ConcatIndexSequenceImpl;
template<std::size_t... S1, std::size_t... S2>
struct ConcatIndexSequenceImpl<IndexSequence<S1...>, IndexSequence<S2...>> :
IndexSequence<S1..., (sizeof...(S1) + S2)...> {};
template<std::size_t N>
struct MakeIndexSequenceImpl : ConcatIndexSequenceImpl<
typename MakeIndexSequenceImpl<N / 2>::Type,
typename MakeIndexSequenceImpl<N - N / 2>::Type
> {};
template<>
struct MakeIndexSequenceImpl<0> : IndexSequence<> {};
template<>
struct MakeIndexSequenceImpl<1> : IndexSequence<0> {};
}
template<std::size_t N>
using MakeIndexSequence = typename Private::MakeIndexSequenceImpl<N>::Type;
// =============================================================================
// See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4121.pdf
template<std::size_t N>
using RawStaticString = const char [N];
namespace Private {
template<std::size_t N, typename = MakeIndexSequence<N>>
struct StaticString;
template<std::size_t N, std::size_t... Index>
struct StaticString<N, IndexSequence<Index...>> {
constexpr StaticString (const RawStaticString<N> &inRaw) : raw{ (inRaw[Index])... } {}
constexpr char operator[] (std::size_t i) const {
return raw[i];
}
constexpr operator const char * () const {
return raw;
}
RawStaticString<N> raw;
};
template<std::size_t N>
class StaticStringConcatHelper {
public:
template<std::size_t N1>
constexpr StaticStringConcatHelper(
const Private::StaticString<N1> &s1,
const Private::StaticString<N - N1 + 1> &s2
) : StaticStringConcatHelper(s1, s2, MakeIndexSequence<N1 - 1>{}, MakeIndexSequence<N - N1 + 1>{}) {}
RawStaticString<N> raw;
private:
template<std::size_t N1, std::size_t... Index1, std::size_t... Index2>
constexpr StaticStringConcatHelper(
const Private::StaticString<N1> &s1,
const Private::StaticString<N - N1 + 1> &s2,
IndexSequence<Index1...>,
IndexSequence<Index2...>
) : raw{ s1[Index1]..., s2[Index2]... } {}
};
template<int Value, int N = getIntLength(Value) + 1>
class StaticIntStringHelper {
public:
constexpr StaticIntStringHelper () : StaticIntStringHelper(MakeIndexSequence<Value >= 0 ? N - 1 : N - 2>{}) {}
RawStaticString<N> raw;
private:
template<std::size_t... Index, typename Int = int, typename std::enable_if<Int(Value) >= 0, int>::type* = nullptr>
constexpr StaticIntStringHelper (const IndexSequence<Index...> &) :
raw{ ('0' + Value / pow10(N - Index - 2) % 10 )..., '\0' } {}
template<std::size_t... Index, typename Int = int, typename std::enable_if<Int(Value) < 0, int>::type* = nullptr>
constexpr StaticIntStringHelper (const IndexSequence<Index...> &) :
raw{ '-', ('0' + abs(Value) / pow10(N - Index - 3) % 10 )..., '\0' } {}
};
};
// -----------------------------------------------------------------------------
template<std::size_t N>
constexpr Private::StaticString<N> StaticString (const RawStaticString<N> &raw) {
return Private::StaticString<N>(raw);
}
template<std::size_t N1, std::size_t N2>
constexpr Private::StaticString<N1 + N2 - 1> operator+ (
const Private::StaticString<N1> &s1,
const Private::StaticString<N2> &s2
) {
return StaticString(Private::StaticStringConcatHelper<N1 + N2 - 1>(s1, s2).raw);
}
template<std::size_t N1, std::size_t N2>
constexpr Private::StaticString<N1 + N2 - 1> operator+ (
const Private::StaticString<N1> &s1,
const RawStaticString<N2> &s2
) {
return StaticString(Private::StaticStringConcatHelper<N1 + N2 - 1>(s1, StaticString(s2)).raw);
}
template<std::size_t N1, std::size_t N2>
constexpr Private::StaticString<N1 + N2 - 1> operator+ (
const RawStaticString<N2> &s1,
const Private::StaticString<N1> &s2
) {
return StaticString(Private::StaticStringConcatHelper<N1 + N2 - 1>(StaticString(s1), s2).raw);
}
// -----------------------------------------------------------------------------
template<int Value = 0>
constexpr Private::StaticString<getIntLength(Value) + 1> StaticIntString () {
return StaticString(Private::StaticIntStringHelper<Value>().raw);
}
// -----------------------------------------------------------------------------
LINPHONE_END_NAMESPACE
#endif // ifndef _L_STATIC_STRING_H_
......@@ -21,6 +21,7 @@
#include "linphone/utils/algorithm.h"
#include "linphone/utils/utils.h"
#include "linphone/utils/static-string.h"
#include "chat/chat-message/chat-message-p.h"
#include "chat/chat-room/chat-room-p.h"
......@@ -94,9 +95,10 @@ MainDb::MainDb (const shared_ptr<Core> &core) : AbstractDb(*new MainDbPrivate),
#ifdef SOCI_ENABLED
// -----------------------------------------------------------------------------
// Soci backend.
// Event filter tools.
// -----------------------------------------------------------------------------
// Some tools to build filters at compile time.
template<typename T>
struct EnumToSql {
T first;
......@@ -110,17 +112,61 @@ static constexpr const char *mapEnumToSql (const EnumToSql<T> enumToSql[], size_
);
}
// Update me event-log-enums values are changed!
static constexpr EnumToSql<MainDb::Filter> eventFilterToSql[] = {
{ MainDb::ConferenceCallFilter, "3, 4" },
{ MainDb::ConferenceChatMessageFilter, "5" },
{ MainDb::ConferenceInfoFilter, "1, 2, 6, 7, 8, 9, 10, 11, 12" },
{ MainDb::ConferenceInfoNoDeviceFilter, "1, 2, 6, 7, 8, 9, 12" }
template<EventLog::Type ...Type>
struct SqlEventFilterBuilder {};
template<EventLog::Type Type, EventLog::Type... List>
struct SqlEventFilterBuilder<Type, List...> {
static constexpr Private::StaticString<1 + getIntLength(int(Type)) + sums((1 + getIntLength(int(List)))...)> get () {
return StaticIntString<int(Type)>() + "," + SqlEventFilterBuilder<List...>::get();
}
};
template<EventLog::Type Type>
struct SqlEventFilterBuilder<Type> {
static constexpr Private::StaticString<1 + getIntLength(int(Type))> get () {
return StaticIntString<int(Type)>();
}
};
static constexpr const char *mapEventFilterToSql (MainDb::Filter filter) {
// -----------------------------------------------------------------------------
// Event filters.
// -----------------------------------------------------------------------------
namespace {
constexpr auto ConferenceCallFilter = SqlEventFilterBuilder<
EventLog::Type::ConferenceCallStart,
EventLog::Type::ConferenceCallEnd
>::get();
constexpr auto ConferenceChatMessageFilter = SqlEventFilterBuilder<EventLog::Type::ConferenceChatMessage>::get();
constexpr auto ConferenceInfoNoDeviceFilter = SqlEventFilterBuilder<
EventLog::Type::ConferenceCreated,
EventLog::Type::ConferenceTerminated,
EventLog::Type::ConferenceParticipantAdded,
EventLog::Type::ConferenceParticipantRemoved,
EventLog::Type::ConferenceParticipantSetAdmin,
EventLog::Type::ConferenceParticipantUnsetAdmin,
EventLog::Type::ConferenceSubjectChanged
>::get();
constexpr auto ConferenceInfoFilter = ConferenceInfoNoDeviceFilter + "," + SqlEventFilterBuilder<
EventLog::Type::ConferenceParticipantDeviceAdded,
EventLog::Type::ConferenceParticipantDeviceRemoved
>::get();
constexpr EnumToSql<MainDb::Filter> EventFilterToSql[] = {
{ MainDb::ConferenceCallFilter, ConferenceCallFilter },
{ MainDb::ConferenceChatMessageFilter, ConferenceChatMessageFilter },
{ MainDb::ConferenceInfoNoDeviceFilter, ConferenceInfoNoDeviceFilter },
{ MainDb::ConferenceInfoFilter, ConferenceInfoFilter }
};
}
static const char *mapEventFilterToSql (MainDb::Filter filter) {
return mapEnumToSql(
eventFilterToSql, sizeof eventFilterToSql / sizeof eventFilterToSql[0], filter
EventFilterToSql, sizeof EventFilterToSql / sizeof EventFilterToSql[0], filter
);
}
......
Markdown is supported
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