diff --git a/include/linphone/utils/general.h b/include/linphone/utils/general.h index 5a4c3b15f..021bc7062 100644 --- a/include/linphone/utils/general.h +++ b/include/linphone/utils/general.h @@ -114,6 +114,8 @@ std::unique_ptr makeUnique(Args && ...args) { return std::unique_ptr(new T(std::forward(args)...)); } +#define L_AUTO_RETURN(VALUE) -> decltype(VALUE) { return VALUE; } + // ----------------------------------------------------------------------------- // Class tools. // ----------------------------------------------------------------------------- @@ -259,17 +261,13 @@ namespace Private { template struct ResolveMemberFunctionOverload { template - 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 struct ResolveConstMemberFunctionOverload { template - 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 @@ -278,9 +276,7 @@ namespace Private { using ResolveConstMemberFunctionOverload::operator(); template - 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 using resolveOverload = Private::ResolveOverload; +// ----------------------------------------------------------------------------- +// 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 +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 +constexpr int sums (T i, Args... args) { + return i + sums(args...); +} + // ----------------------------------------------------------------------------- // Wrapper public. // ----------------------------------------------------------------------------- diff --git a/include/linphone/utils/static-string.h b/include/linphone/utils/static-string.h new file mode 100644 index 000000000..222095ce7 --- /dev/null +++ b/include/linphone/utils/static-string.h @@ -0,0 +1,166 @@ +/* + * 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 +struct IndexSequence { + using Type = IndexSequence; +}; + +namespace Private { + template + struct ConcatIndexSequenceImpl; + + template + struct ConcatIndexSequenceImpl, IndexSequence> : + IndexSequence {}; + + template + struct MakeIndexSequenceImpl : ConcatIndexSequenceImpl< + typename MakeIndexSequenceImpl::Type, + typename MakeIndexSequenceImpl::Type + > {}; + + template<> + struct MakeIndexSequenceImpl<0> : IndexSequence<> {}; + + template<> + struct MakeIndexSequenceImpl<1> : IndexSequence<0> {}; +} + +template +using MakeIndexSequence = typename Private::MakeIndexSequenceImpl::Type; + +// ============================================================================= + +// See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4121.pdf +template +using RawStaticString = const char [N]; + +namespace Private { + template> + struct StaticString; + + template + struct StaticString> { + constexpr StaticString (const RawStaticString &inRaw) : raw{ (inRaw[Index])... } {} + + constexpr char operator[] (std::size_t i) const { + return raw[i]; + } + + constexpr operator const char * () const { + return raw; + } + + RawStaticString raw; + }; + + template + class StaticStringConcatHelper { + public: + template + constexpr StaticStringConcatHelper( + const Private::StaticString &s1, + const Private::StaticString &s2 + ) : StaticStringConcatHelper(s1, s2, MakeIndexSequence{}, MakeIndexSequence{}) {} + + RawStaticString raw; + + private: + template + constexpr StaticStringConcatHelper( + const Private::StaticString &s1, + const Private::StaticString &s2, + IndexSequence, + IndexSequence + ) : raw{ s1[Index1]..., s2[Index2]... } {} + }; + + template + class StaticIntStringHelper { + public: + constexpr StaticIntStringHelper () : StaticIntStringHelper(MakeIndexSequence= 0 ? N - 1 : N - 2>{}) {} + + RawStaticString raw; + + private: + template= 0, int>::type* = nullptr> + constexpr StaticIntStringHelper (const IndexSequence &) : + raw{ ('0' + Value / pow10(N - Index - 2) % 10 )..., '\0' } {} + + template::type* = nullptr> + constexpr StaticIntStringHelper (const IndexSequence &) : + raw{ '-', ('0' + abs(Value) / pow10(N - Index - 3) % 10 )..., '\0' } {} + }; +}; + +// ----------------------------------------------------------------------------- + +template +constexpr Private::StaticString StaticString (const RawStaticString &raw) { + return Private::StaticString(raw); +} + +template +constexpr Private::StaticString operator+ ( + const Private::StaticString &s1, + const Private::StaticString &s2 +) { + return StaticString(Private::StaticStringConcatHelper(s1, s2).raw); +} + +template +constexpr Private::StaticString operator+ ( + const Private::StaticString &s1, + const RawStaticString &s2 +) { + return StaticString(Private::StaticStringConcatHelper(s1, StaticString(s2)).raw); +} + +template +constexpr Private::StaticString operator+ ( + const RawStaticString &s1, + const Private::StaticString &s2 +) { + return StaticString(Private::StaticStringConcatHelper(StaticString(s1), s2).raw); +} + +// ----------------------------------------------------------------------------- + +template +constexpr Private::StaticString StaticIntString () { + return StaticString(Private::StaticIntStringHelper().raw); +} + +// ----------------------------------------------------------------------------- + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_STATIC_STRING_H_ diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp index 11186d646..0502ab1be 100644 --- a/src/db/main-db.cpp +++ b/src/db/main-db.cpp @@ -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) : AbstractDb(*new MainDbPrivate), #ifdef SOCI_ENABLED // ----------------------------------------------------------------------------- -// Soci backend. +// Event filter tools. // ----------------------------------------------------------------------------- +// Some tools to build filters at compile time. template struct EnumToSql { T first; @@ -110,17 +112,61 @@ static constexpr const char *mapEnumToSql (const EnumToSql enumToSql[], size_ ); } -// Update me event-log-enums values are changed! -static constexpr EnumToSql 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 +struct SqlEventFilterBuilder {}; + +template +struct SqlEventFilterBuilder { + static constexpr Private::StaticString<1 + getIntLength(int(Type)) + sums((1 + getIntLength(int(List)))...)> get () { + return StaticIntString() + "," + SqlEventFilterBuilder::get(); + } }; -static constexpr const char *mapEventFilterToSql (MainDb::Filter filter) { +template +struct SqlEventFilterBuilder { + static constexpr Private::StaticString<1 + getIntLength(int(Type))> get () { + return StaticIntString(); + } +}; + +// ----------------------------------------------------------------------------- +// Event filters. +// ----------------------------------------------------------------------------- + +namespace { + constexpr auto ConferenceCallFilter = SqlEventFilterBuilder< + EventLog::Type::ConferenceCallStart, + EventLog::Type::ConferenceCallEnd + >::get(); + + constexpr auto ConferenceChatMessageFilter = SqlEventFilterBuilder::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 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 ); }