diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 422c8b1f3..29d437147 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,6 +32,9 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES db/abstract/abstract-db-p.h db/abstract/abstract-db.h db/events-db.h + db/provider/db-session-p.h + db/provider/db-session-provider.h + db/provider/db-session.h enums.h event/call-event.h event/event.h @@ -56,6 +59,8 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES cpim/parser/cpim-parser.cpp db/abstract/abstract-db.cpp db/events-db.cpp + db/provider/db-session-provider.cpp + db/provider/db-session.cpp event/call-event.cpp event/event.cpp event/message-event.cpp diff --git a/src/db/abstract/abstract-db-p.h b/src/db/abstract/abstract-db-p.h index a3ef0e11d..51dbd2ffe 100644 --- a/src/db/abstract/abstract-db-p.h +++ b/src/db/abstract/abstract-db-p.h @@ -19,11 +19,8 @@ #ifndef _ABSTRACT_DB_P_H_ #define _ABSTRACT_DB_P_H_ -#ifdef SOCI_ENABLED - #include -#endif // ifdef SOCI_ENABLED - #include "abstract-db.h" +#include "db/provider/db-session.h" #include "object/object-p.h" // ============================================================================= @@ -32,13 +29,10 @@ LINPHONE_BEGIN_NAMESPACE class AbstractDbPrivate : public ObjectPrivate { public: - #ifdef SOCI_ENABLED - soci::session session; - #endif // ifndef SOCI_ENABLED + DbSession dbSession; private: AbstractDb::Backend backend; - bool isConnected = false; L_DECLARE_PUBLIC(AbstractDb); }; diff --git a/src/db/abstract/abstract-db.cpp b/src/db/abstract/abstract-db.cpp index 3235f0ec3..63e2fcef4 100644 --- a/src/db/abstract/abstract-db.cpp +++ b/src/db/abstract/abstract-db.cpp @@ -17,43 +17,34 @@ */ #include "abstract-db-p.h" +#include "db/provider/db-session-provider.h" #include "logger/logger.h" #include "abstract-db.h" -using namespace std; - // ============================================================================= +using namespace std; + LINPHONE_BEGIN_NAMESPACE AbstractDb::AbstractDb (AbstractDbPrivate &p) : Object(*new AbstractDbPrivate) {} -bool AbstractDb::connect (Backend backend, const std::string ¶meters) { - #ifdef SOCI_ENABLED - L_D(AbstractDb); - try { - if (d->isConnected) { - d->session.close(); - d->isConnected = false; - } +bool AbstractDb::connect (Backend backend, const string ¶meters) { + L_D(AbstractDb); - d->session.open(backend == Mysql ? "mysql" : "sqlite3", parameters); - init(); - } catch (const exception &e) { - return false; - } + d->dbSession = DbSessionProvider::getInstance()->getSession( + (backend == Mysql ? "mysql://" : "sqlite3://") + parameters + ); - return true; - #else - lWarning() << "Cannot use AbstractDb. Soci is not enabled."; - return false; - #endif // ifndef SOCI_ENABLED + if (d->dbSession) + init(); + return d->dbSession; } bool AbstractDb::isConnected () const { L_D(const AbstractDb); - return d->isConnected; + return d->dbSession; } AbstractDb::Backend AbstractDb::getBackend () const { diff --git a/src/db/events-db.cpp b/src/db/events-db.cpp index bf207d85a..8a949c0e8 100644 --- a/src/db/events-db.cpp +++ b/src/db/events-db.cpp @@ -20,6 +20,11 @@ #include "events-db.h" +// TODO: Remove me. +#ifdef SOCI_ENABLED + #undef SOCI_ENABLED +#endif + // ============================================================================= LINPHONE_BEGIN_NAMESPACE @@ -61,10 +66,10 @@ void EventsDb::init () { d->session << "CREATE TABLE IF NOT EXISTS dialog (" - " local_sip_address_id BIGINT UNSIGNED NOT NULL," // Sip address used to communicate. - " remote_sip_address_id BIGINT UNSIGNED NOT NULL," // Server (for conference) or user sip address. - " creation_timestamp TIMESTAMP NOT NULL," // Dialog creation date. - " last_update_timestamp TIMESTAMP NOT NULL," // Last event timestamp (call, message...). + " local_sip_address_id BIGINT UNSIGNED NOT NULL," // Sip address used to communicate. + " remote_sip_address_id BIGINT UNSIGNED NOT NULL," // Server (for conference) or user sip address. + " creation_timestamp TIMESTAMP NOT NULL," // Dialog creation date. + " last_update_timestamp TIMESTAMP NOT NULL," // Last event timestamp (call, message...). " FOREIGN KEY (local_sip_address_id)" " REFERENCES sip_address(id)" " ON DELETE CASCADE," @@ -79,7 +84,7 @@ void EventsDb::init () { " dialog_id BIGINT UNSIGNED NOT NULL," " status_id TINYINT UNSIGNED NOT NULL," " direction_id TINYINT UNSIGNED NOT NULL," - " imdn_message_id VARCHAR(255) NOT NULL," // See: https://tools.ietf.org/html/rfc5438#section-6.3 + " imdn_message_id VARCHAR(255) NOT NULL," // See: https://tools.ietf.org/html/rfc5438#section-6.3 " content_type VARCHAR(255) NOT NULL," " is_secured BOOLEAN NOT NULL," " app_data VARCHAR(2048)," diff --git a/src/db/provider/db-session-p.h b/src/db/provider/db-session-p.h new file mode 100644 index 000000000..597ceaa44 --- /dev/null +++ b/src/db/provider/db-session-p.h @@ -0,0 +1,54 @@ +/* + * db-session-p.h + * Copyright (C) 2017 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 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _DB_SESSION_P_H_ +#define _DB_SESSION_P_H_ + +#ifdef SOCI_ENABLED + #include +#endif // ifdef SOCI_ENABLED + +#include "db-session.h" +#include "object/clonable-object-p.h" + +// ============================================================================= + +#ifdef SOCI_ENABLED + namespace soci { + class session; + } +#endif // ifdef SOCI_ENABLED + +LINPHONE_BEGIN_NAMESPACE + +class DbSessionPrivate : public ClonableObjectPrivate { + friend class DbSessionProvider; + +private: + bool isValid = false; + + #ifdef SOCI_ENABLED + std::shared_ptr session; + #endif // ifndef SOCI_ENABLED + + L_DECLARE_PUBLIC(DbSession); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _DB_SESSION_P_H_ diff --git a/src/db/provider/db-session-provider.cpp b/src/db/provider/db-session-provider.cpp new file mode 100644 index 000000000..04c8bb98e --- /dev/null +++ b/src/db/provider/db-session-provider.cpp @@ -0,0 +1,83 @@ +/* + * db-session-provider.cpp + * Copyright (C) 2017 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 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifdef SOCI_ENABLED + #include + + #include +#endif // ifdef SOCI_ENABLED + +#include "db-session-p.h" +#include "object/object-p.h" + +#include "db-session-provider.h" + +#define CLEAN_COUNTER_MAX 1000 + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +class DbSessionProviderPrivate : public ObjectPrivate { +public: + #ifdef SOCI_ENABLED + typedef pair, DbSessionPrivate *> InternalSession; + unordered_map sessions; + #endif // ifdef SOCI_ENABLED + + int cleanCounter = 0; +}; + +DbSessionProvider::DbSessionProvider () : Singleton(*new DbSessionProviderPrivate) {} + +DbSession DbSessionProvider::getSession (const string &uri) { + DbSession session; + + #ifdef SOCI_ENABLED + L_D(DbSessionProvider); + try { + shared_ptr sociSession = d->sessions[uri].first.lock(); + if (!sociSession) { // Create new session. + sociSession = make_shared(uri); + DbSessionPrivate *p = session.getPrivate(); + p->session = sociSession; + p->isValid = true; + d->sessions[uri] = make_pair(sociSession, p); + } else // Share session. + session.setRef(*d->sessions[uri].second); + } catch (const exception &) {} + + // Remove invalid weak ptrs. + if (++d->cleanCounter >= CLEAN_COUNTER_MAX) { + d->cleanCounter = 0; + + for (auto it = d->sessions.begin(), itEnd = d->sessions.end(); it != itEnd;) { + if (it->second.first.expired()) + it = d->sessions.erase(it); + else + ++it; + } + } + #endif // ifndef SOCI_ENABLED + + return session; +} + +LINPHONE_END_NAMESPACE diff --git a/src/db/provider/db-session-provider.h b/src/db/provider/db-session-provider.h new file mode 100644 index 000000000..50542d5eb --- /dev/null +++ b/src/db/provider/db-session-provider.h @@ -0,0 +1,48 @@ +/* + * db-session-provider.h + * Copyright (C) 2017 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 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _DB_SESSION_PROVIDER_H_ +#define _DB_SESSION_PROVIDER_H_ + +#include + +#include "db-session.h" +#include "object/singleton.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class DbSessionProviderPrivate; + +class DbSessionProvider : public Singleton { + friend class Singleton; + +public: + DbSession getSession (const std::string &uri); + +private: + DbSessionProvider (); + + L_DECLARE_PRIVATE(DbSessionProvider); + L_DISABLE_COPY(DbSessionProvider); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _DB_SESSION_PROVIDER_H_ diff --git a/src/db/provider/db-session.cpp b/src/db/provider/db-session.cpp new file mode 100644 index 000000000..ac1f85d52 --- /dev/null +++ b/src/db/provider/db-session.cpp @@ -0,0 +1,36 @@ +/* + * db-session.cpp + * Copyright (C) 2017 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 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "db-session-p.h" + +#include "db-session.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +L_USE_DEFAULT_SHARE_IMPL(DbSession, ClonableObject); + +DbSession::operator bool () const { + L_D(const DbSession); + return d->isValid; +} + +LINPHONE_END_NAMESPACE diff --git a/src/db/provider/db-session.h b/src/db/provider/db-session.h new file mode 100644 index 000000000..35eb6fe59 --- /dev/null +++ b/src/db/provider/db-session.h @@ -0,0 +1,49 @@ +/* + * db-session.h + * Copyright (C) 2017 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 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _DB_SESSION_H_ +#define _DB_SESSION_H_ + +#include + +#include "object/clonable-object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class DbSessionPrivate; + +class DbSession : public ClonableObject { + friend class DbSessionProvider; + +public: + DbSession (); + DbSession (const DbSession &src); + + DbSession &operator= (const DbSession &src); + + operator bool () const; + +private: + L_DECLARE_PRIVATE(DbSession); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _DB_SESSION_H_ diff --git a/src/event/call-event.cpp b/src/event/call-event.cpp index 3837e9f9f..bc17b4e2c 100644 --- a/src/event/call-event.cpp +++ b/src/event/call-event.cpp @@ -41,6 +41,16 @@ CallEvent::CallEvent (Type type, const shared_ptr &call) : Event(*new Call CallEvent::CallEvent (const CallEvent &src) : CallEvent(src.getType(), src.getCall()) {} +CallEvent &CallEvent::operator= (const CallEvent &src) { + L_D(CallEvent); + if (this != &src) { + Event::operator=(src); + d->call = src.getPrivate()->call; + } + + return *this; +} + shared_ptr CallEvent::getCall () const { L_D(const CallEvent); return d->call; diff --git a/src/event/call-event.h b/src/event/call-event.h index fa2577aea..e56d25dfc 100644 --- a/src/event/call-event.h +++ b/src/event/call-event.h @@ -35,6 +35,8 @@ public: CallEvent (Type type, const std::shared_ptr &message); CallEvent (const CallEvent &src); + CallEvent &operator= (const CallEvent &src); + std::shared_ptr getCall () const; private: diff --git a/src/event/event.cpp b/src/event/event.cpp index af505a417..824240425 100644 --- a/src/event/event.cpp +++ b/src/event/event.cpp @@ -24,15 +24,24 @@ LINPHONE_BEGIN_NAMESPACE +// ----------------------------------------------------------------------------- + Event::Event () : ClonableObject(*new EventPrivate) {} Event::Event (const Event &) : ClonableObject(*new EventPrivate) {} -Event::Event (EventPrivate &p, Type type) : ClonableObject(p) { +Event::Event (EventPrivate &p, Type type) : ClonableObject(*new EventPrivate) { L_D(Event); d->type = type; } +Event &Event::operator= (const Event &src) { + L_D(Event); + if (this != &src) + d->type = src.getPrivate()->type; + return *this; +} + Event::Type Event::getType () const { L_D(const Event); return d->type; diff --git a/src/event/event.h b/src/event/event.h index f0aa80010..17deb379f 100644 --- a/src/event/event.h +++ b/src/event/event.h @@ -40,6 +40,8 @@ public: Event (const Event &src); virtual ~Event () = default; + Event &operator= (const Event &src); + Type getType () const; protected: diff --git a/src/event/message-event.cpp b/src/event/message-event.cpp index 84c140526..49e74f3b7 100644 --- a/src/event/message-event.cpp +++ b/src/event/message-event.cpp @@ -41,6 +41,16 @@ MessageEvent::MessageEvent (const shared_ptr &message) : Event(*new Mes MessageEvent::MessageEvent (const MessageEvent &src) : MessageEvent(src.getMessage()) {} +MessageEvent &MessageEvent::operator= (const MessageEvent &src) { + L_D(MessageEvent); + if (this != &src) { + Event::operator=(src); + d->message = src.getPrivate()->message; + } + + return *this; +} + shared_ptr MessageEvent::getMessage () const { L_D(const MessageEvent); return d->message; diff --git a/src/event/message-event.h b/src/event/message-event.h index 5d46cb604..9edff75a9 100644 --- a/src/event/message-event.h +++ b/src/event/message-event.h @@ -35,6 +35,8 @@ public: MessageEvent (const std::shared_ptr &message); MessageEvent (const MessageEvent &src); + MessageEvent &operator= (const MessageEvent &src); + std::shared_ptr getMessage () const; private: diff --git a/src/object/clonable-object-p.h b/src/object/clonable-object-p.h index 94c3b4491..8c099be7b 100644 --- a/src/object/clonable-object-p.h +++ b/src/object/clonable-object-p.h @@ -19,22 +19,27 @@ #ifndef _CLONABLE_OBJECT_P_H_ #define _CLONABLE_OBJECT_P_H_ +#include + #include "utils/general.h" // ============================================================================= LINPHONE_BEGIN_NAMESPACE -class ClonableObject; - class ClonableObjectPrivate { public: virtual ~ClonableObjectPrivate () = default; protected: - ClonableObject *mPublic = nullptr; + std::unordered_map *mPublic = nullptr; private: + void ref (); + void unref (); + + int nRefs = 0; + L_DECLARE_PUBLIC(ClonableObject); }; diff --git a/src/object/clonable-object.cpp b/src/object/clonable-object.cpp index 2b50da650..32c36a2ae 100644 --- a/src/object/clonable-object.cpp +++ b/src/object/clonable-object.cpp @@ -20,16 +20,67 @@ #include "clonable-object.h" -LINPHONE_BEGIN_NAMESPACE - // ============================================================================= +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// TODO: Use atomic counter? + +void ClonableObjectPrivate::ref () { + ++nRefs; +} + +void ClonableObjectPrivate::unref () { + if (--nRefs == 0) { + delete mPublic; + delete this; + } +} + +// ----------------------------------------------------------------------------- + ClonableObject::ClonableObject (ClonableObjectPrivate &p) : mPrivate(&p) { - mPrivate->mPublic = this; + // Q-pointer must be empty. It's a constructor that takes a new private data. + L_ASSERT(!mPrivate->mPublic); + + mPrivate->mPublic = new remove_pointermPublic)>::type; + (*mPrivate->mPublic)[mPrivate] = this; + mPrivate->ref(); +} + +ClonableObject::ClonableObject (const ClonableObjectPrivate &p) { + // Cannot access to Q-pointer. It's a copy constructor from private data. + L_ASSERT(!mPrivate); + + setRef(p); } ClonableObject::~ClonableObject () { - delete mPrivate; + mPrivate->mPublic->erase(mPrivate); + mPrivate->unref(); +} + +void ClonableObject::setRef (const ClonableObjectPrivate &p) { + // Q-pointer must exist. + L_ASSERT(mPrivate); + L_ASSERT(mPrivate->mPublic); + + // Nothing, same reference. + if (&p == mPrivate) + return; + + // Unref previous private data. + if (mPrivate) { + mPrivate->mPublic->erase(mPrivate); + mPrivate->unref(); + } + + // Add and reference new private data. + mPrivate = const_cast(&p); + (*mPrivate->mPublic)[mPrivate] = this; + mPrivate->ref(); } LINPHONE_END_NAMESPACE diff --git a/src/object/clonable-object.h b/src/object/clonable-object.h index fdca68b99..490c5bc71 100644 --- a/src/object/clonable-object.h +++ b/src/object/clonable-object.h @@ -25,15 +25,20 @@ LINPHONE_BEGIN_NAMESPACE -class ClonableObjectPrivate; - class LINPHONE_PUBLIC ClonableObject { public: virtual ~ClonableObject (); protected: + // Use a new ClonableObjectPrivate without owner. explicit ClonableObject (ClonableObjectPrivate &p); + // If you want share an existing ClonableObjectPrivate, call this function. + explicit ClonableObject (const ClonableObjectPrivate &p); + + // Change the ClonableObjectPrivate, it can be shared. + void setRef (const ClonableObjectPrivate &p); + ClonableObjectPrivate *mPrivate = nullptr; private: diff --git a/src/object/object-p.h b/src/object/object-p.h index 83d7612fc..ca9111eac 100644 --- a/src/object/object-p.h +++ b/src/object/object-p.h @@ -25,8 +25,6 @@ LINPHONE_BEGIN_NAMESPACE -class Object; - class ObjectPrivate { public: virtual ~ObjectPrivate () = default; diff --git a/src/object/object.h b/src/object/object.h index 54ed08d28..d3cc22808 100644 --- a/src/object/object.h +++ b/src/object/object.h @@ -25,8 +25,6 @@ LINPHONE_BEGIN_NAMESPACE -class ObjectPrivate; - class LINPHONE_PUBLIC Object { public: virtual ~Object (); diff --git a/src/utils/general.h b/src/utils/general.h index b91bf5af0..7f46799b8 100644 --- a/src/utils/general.h +++ b/src/utils/general.h @@ -47,6 +47,14 @@ LINPHONE_BEGIN_NAMESPACE // ----------------------------------------------------------------------------- +void l_assert (const char *condition, const char *file, int line); + +#ifdef DEBUG + #define L_ASSERT(CONDITION) static_cast(false && (CONDITION)) +#else + #define L_ASSERT(CONDITION) ((CONDITION) ? static_cast(0) : l_assert(#CONDITION, __FILE__, __LINE__)) +#endif + #define L_DECLARE_PRIVATE(CLASS) \ inline CLASS ## Private * getPrivate() { \ return reinterpret_cast(mPrivate); \ @@ -56,12 +64,41 @@ LINPHONE_BEGIN_NAMESPACE } \ friend class CLASS ## Private; +class ClonableObject; +class ClonableObjectPrivate; +class Object; +class ObjectPrivate; + +template +inline ClonableObject *getPublicHelper (T *object, ClonableObjectPrivate *context) { + auto it = object->find(context); + L_ASSERT(it != object->end()); + return it->second; +} + +template +inline const ClonableObject *getPublicHelper (const T *object, const ClonableObjectPrivate *context) { + auto it = object->find(context); + L_ASSERT(it != object->cend()); + return it->second; +} + +template +inline Object *getPublicHelper (T *object, ObjectPrivate *) { + return object; +} + +template +inline const Object *getPublicHelper (const T *object, const ObjectPrivate *) { + return object; +} + #define L_DECLARE_PUBLIC(CLASS) \ - inline CLASS * getPublic() { \ - return static_cast(mPublic); \ + inline CLASS * getPublic () { \ + return static_cast(getPublicHelper(mPublic, this)); \ } \ - inline const CLASS *getPublic() const { \ - return static_cast(mPublic); \ + inline const CLASS *getPublic () const { \ + return static_cast(getPublicHelper(mPublic, this)); \ } \ friend class CLASS; @@ -72,13 +109,14 @@ LINPHONE_BEGIN_NAMESPACE #define L_D(CLASS) CLASS ## Private * const d = getPrivate(); #define L_Q(CLASS) CLASS * const q = getPublic(); -void l_assert (const char *condition, const char *file, int line); - -#ifdef DEBUG - #define L_ASSERT(CONDITION) static_cast(false && (CONDITION)) -#else - #define L_ASSERT(CONDITION) ((CONDITION) ? static_cast(0) : l_assert(#CONDITION, __FILE__, __LINE__)) -#endif +#define L_USE_DEFAULT_SHARE_IMPL(CLASS, PARENT_CLASS) \ + CLASS::CLASS () : PARENT_CLASS(*new CLASS ## Private) {} \ + CLASS::CLASS (const CLASS &src) : ClonableObject(*src.getPrivate()) {} \ + CLASS &CLASS::operator= (const CLASS &src) { \ + if (this != &src) \ + setRef(*src.getPrivate()); \ + return *this; \ + } LINPHONE_END_NAMESPACE diff --git a/src/utils/utils.h b/src/utils/utils.h index ceede0cda..e64dc4e7e 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -29,15 +29,15 @@ LINPHONE_BEGIN_NAMESPACE namespace Utils { - LINPHONE_PUBLIC bool iequals (const std::string &a, const std::string &b); + LINPHONE_PUBLIC bool iequals (const std::string &a, const std::string &b); - LINPHONE_PUBLIC std::vector split (const std::string &str, const std::string &delimiter); + LINPHONE_PUBLIC std::vector split (const std::string &str, const std::string &delimiter); - LINPHONE_PUBLIC inline std::vector split (const std::string &str, char delimiter) { - return split(str, std::string(1, delimiter)); - } + LINPHONE_PUBLIC inline std::vector split (const std::string &str, char delimiter) { + return split(str, std::string(1, delimiter)); + } - LINPHONE_PUBLIC int stoi (const std::string &str, size_t *idx = 0, int base = 10); + LINPHONE_PUBLIC int stoi (const std::string &str, size_t *idx = 0, int base = 10); } LINPHONE_END_NAMESPACE