--- /dev/null
+BMW AG
+Aleksandar Kanchev <kanchev@itestra.com>
+Philip Rauwolf <rauwolf@itestra.com>
+Johannes Schanda <schanda@itestra.com>
--- /dev/null
+abs_top_builddir=@abs_top_builddir@
+abs_top_srcdir=@abs_top_srcdir@
+prefix=
+exec_prefix=
+
+Name: Common API C++ D-Bus Middleware
+Description: GENIVI Common API C++ D-Bus Middleware (uninstalled copy)
+Version: @PACKAGE_VERSION@
+Requires: CommonAPI dbus-1
+Libs: ${abs_top_builddir}/libCommonAPI-DBus.la
+Cflags: -I${abs_top_srcdir}/src
\ No newline at end of file
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Common API C++ D-Bus Middleware
+Description: GENIVI Common API C++ D-Bus Middleware
+Version: @PACKAGE_VERSION@
+Requires: CommonAPI dbus-1
+Libs: -L${libdir} -lCommonAPI-DBus
+Cflags: -I${includedir}/CommonAPI-@PACKAGE_VERSION@
\ No newline at end of file
--- /dev/null
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
--- /dev/null
+ACLOCAL_AMFLAGS = -I m4
+
+EXTRA_DIST =
+MOSTLYCLEANFILES =
+
+AM_CPPFLAGS = \
+ ${COMMONAPI_CFLAGS} \
+ ${DBUS_CFLAGS} \
+ -I$(top_srcdir)/src
+
+LDADD = \
+ ${COMMONAPI_LIBS} \
+ ${DBUS_LIBS}
+
+lib_LTLIBRARIES =
+lib_LIBRARIES =
+
+# ------------------------------------------------------------------------------
+lib_LTLIBRARIES += libmurmurhash-internal.la
+
+libmurmurhash_internal_la_SOURCES = \
+ src/murmurhash/MurmurHash3.h \
+ src/murmurhash/MurmurHash3.cpp
+
+# ------------------------------------------------------------------------------
+lib_LTLIBRARIES += libCommonAPI-DBus.la
+
+libCommonAPI_DBus_la_SOURCES = \
+ src/CommonAPI/DBus/DBusConnection.cpp \
+ src/CommonAPI/DBus/DBusDaemonProxy.cpp \
+ src/CommonAPI/DBus/DBusError.cpp \
+ src/CommonAPI/DBus/DBusFunctionalHash.cpp \
+ src/CommonAPI/DBus/DBusInputStream.cpp \
+ src/CommonAPI/DBus/DBusMessage.cpp \
+ src/CommonAPI/DBus/DBusObjectManager.cpp \
+ src/CommonAPI/DBus/DBusOutputStream.cpp \
+ src/CommonAPI/DBus/DBusProxy.cpp \
+ src/CommonAPI/DBus/DBusFactory.cpp \
+ src/CommonAPI/DBus/DBusRuntime.cpp \
+ src/CommonAPI/DBus/DBusServiceRegistry.cpp \
+ src/CommonAPI/DBus/DBusServiceStatusEvent.cpp \
+ src/CommonAPI/DBus/DBusStubAdapter.cpp
+
+libCommonAPI_DBus_la_LIBADD = \
+ libmurmurhash-internal.la \
+ ${COMMONAPI_LIBS}
+
+CommonAPI_DBus_includedir=$(includedir)/CommonAPI-${VERSION}/CommonAPI/DBus
+CommonAPI_DBus_include_HEADERS = \
+ src/CommonAPI/DBus/DBusAttribute.h \
+ src/CommonAPI/DBus/DBusConnection.h \
+ src/CommonAPI/DBus/DBusDaemonProxy.h \
+ src/CommonAPI/DBus/DBusError.h \
+ src/CommonAPI/DBus/DBusEvent.h \
+ src/CommonAPI/DBus/DBusFunctionalHash.h \
+ src/CommonAPI/DBus/DBusHelper.h \
+ src/CommonAPI/DBus/DBusInputStream.h \
+ src/CommonAPI/DBus/DBusMessage.h \
+ src/CommonAPI/DBus/DBusMultiEvent.h \
+ src/CommonAPI/DBus/DBusObjectManager.h \
+ src/CommonAPI/DBus/DBusOutputStream.h \
+ src/CommonAPI/DBus/DBusProxy.h \
+ src/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.h \
+ src/CommonAPI/DBus/DBusProxyConnection.h \
+ src/CommonAPI/DBus/DBusFactory.h \
+ src/CommonAPI/DBus/DBusProxyHelper.h \
+ src/CommonAPI/DBus/DBusRuntime.h \
+ src/CommonAPI/DBus/DBusSerializableArguments.h \
+ src/CommonAPI/DBus/DBusServiceRegistry.h \
+ src/CommonAPI/DBus/DBusServiceStatusEvent.h \
+ src/CommonAPI/DBus/DBusStubAdapter.h \
+ src/CommonAPI/DBus/DBusStubAdapterHelper.h \
+ src/CommonAPI/DBus/DBusUtils.h
+
+pkgconfigdir = ${libdir}/pkgconfig
+pkgconfig_DATA = CommonAPI-DBus.pc
+
+# ------------------------------------------------------------------------------
+if ENABLE_TESTS
+
+TestInterfaceSources = \
+ src/test/commonapi/tests/DerivedTypeCollection.cpp \
+ src/test/commonapi/tests/TestInterfaceDBusProxy.cpp \
+ src/test/commonapi/tests/TestInterfaceDBusStubAdapter.cpp \
+ src/test/commonapi/tests/TestInterfaceStubDefault.cpp
+
+check_PROGRAMS = \
+ DBusCommunicationTest \
+ DBusMultipleConnectionTest \
+ DBusDaemonProxyTest \
+ DBusInputStreamTest \
+ DBusOutputStreamTest \
+ DBusRuntimeTest \
+ DBusFactoryTest \
+ DBusProxyTest \
+ DBusVariantTest \
+ DBusBenchmarkingTest
+
+TESTS = ${check_PROGRAMS}
+
+DBusBenchmarkingTest_SOURCES = src/test/DBusBenchmarkingTest.cpp
+DBusBenchmarkingTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
+DBusBenchmarkingTest_CXXFLAGS = ${GTEST_CXXFLAGS}
+DBusBenchmarkingTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la
+
+DBusCommunicationTest_SOURCES = \
+ src/test/DBusCommunicationTest.cpp \
+ ${TestInterfaceSources}
+DBusCommunicationTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
+DBusCommunicationTest_CXXFLAGS = ${GTEST_CXXFLAGS}
+DBusCommunicationTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la
+
+DBusDaemonProxyTest_SOURCES = src/test/DBusDaemonProxyTest.cpp
+DBusDaemonProxyTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
+DBusDaemonProxyTest_CXXFLAGS = ${GTEST_CXXFLAGS}
+DBusDaemonProxyTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la
+
+DBusInputStreamTest_SOURCES = src/test/DBusInputStreamTest.cpp
+DBusInputStreamTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
+DBusInputStreamTest_CXXFLAGS = ${GTEST_CXXFLAGS}
+DBusInputStreamTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la
+
+DBusOutputStreamTest_SOURCES = src/test/DBusOutputStreamTest.cpp
+DBusOutputStreamTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
+DBusOutputStreamTest_CXXFLAGS = ${GTEST_CXXFLAGS}
+DBusOutputStreamTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la
+
+DBusFactoryTest_SOURCES = \
+ src/test/DBusFactoryTest.cpp \
+ ${TestInterfaceSources}
+DBusFactoryTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
+DBusFactoryTest_CXXFLAGS = ${GTEST_CXXFLAGS}
+DBusFactoryTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la
+
+DBusRuntimeTest_SOURCES = src/test/DBusRuntimeTest.cpp
+DBusRuntimeTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
+DBusRuntimeTest_CXXFLAGS = ${GTEST_CXXFLAGS}
+DBusRuntimeTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la
+
+#DBusStubAdapterTest_SOURCES = src/test/DBusStubAdapterTest.cpp
+#DBusStubAdapterTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
+#DBusStubAdapterTest_CXXFLAGS = ${GTEST_CXXFLAGS}
+#DBusStubAdapterTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la
+
+DBusMultipleConnectionTest_SOURCES = src/test/DBusMultipleConnectionTest.cpp \
+ ${TestInterfaceSources}
+DBusMultipleConnectionTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
+DBusMultipleConnectionTest_CXXFLAGS = ${GTEST_CXXFLAGS}
+DBusMultipleConnectionTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la
+
+DBusProxyTest_SOURCES = src/test/DBusProxyTest.cpp
+DBusProxyTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
+DBusProxyTest_CXXFLAGS = ${GTEST_CXXFLAGS}
+DBusProxyTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la
+
+DBusVariantTest_SOURCES = src/test/DBusVariantTest.cpp
+DBusVariantTest_CPPFLAGS = ${AM_CPPFLAGS} ${GTEST_CPPFLAGS}
+DBusVariantTest_CXXFLAGS = ${GTEST_CXXFLAGS}
+DBusVariantTest_LDADD = ${LDADD} ${GTEST_LIBS} libCommonAPI-DBus.la
+
+endif
+
+
+# ------------------------------------------------------------------------------
+# Doxygen
+include $(top_srcdir)/aminclude.am
+EXTRA_DIST += doxygen.cfg
+MOSTLYCLEANFILES += ${DX_CLEANFILES}
+
+# ------------------------------------------------------------------------------
+MAINTAINERCLEANFILES = \
+ Makefile.in \
+ aclocal.m4 \
+ configure
+
+clean-local:
+ -rm -rf src-gen
+
+maintainer-clean-local:
+ -rm -rf build-aux
+ -rm -f config.h.in*
+ -rm -f m4/libtool*.m4
+ -rm -f m4/lt*.m4
--- /dev/null
+* Move Version checking to the ServiceRegistry:
+ Currently, ensuring the interface-version based compatibility of the local proxy and
+ a given remote service would be done asynchronously within the proxy right after its creation.
+ The check should be moved to the service registry, so that a proxy only needs to ask
+ for the locally cached version information of the remote service.
+ According to the current CommonAPI Spec, it is required that a proxy remains "unavailable" when
+ it's counterpart has an incompatible interface version.
+ Feasibility of and alternatives to this approach remain to be determined.
+
+* Performance:
+ Check especially message dispatching! Is it possible to do the dispatching without copying
+ the interface name and object path strings?
+ Check (de)serialization, improve where possible.
+
+* Implementation of Variants.
+
+* Dedicated Test of multiple connect/disconnect cycles
+
+* Life Cycle of connections: Disconnect/Destroy with ProxyFactory, how to do this otherwise?
+
+* DBusProxyHelper.h:
+ // TODO: Must implement available checks on method calls, and wait for valid avalable status in sync case
+ /*
+ * XXX DBusProxy declares a private DBusReadonlyAttribute variable, which
+ * cuases a circular dependency. As a workaround the DBusProxy must be
+ * forward declared and set as default parameter to the template attribute
+ * classes.
+ *
+ * Since DBus*Attribute use the DBusProxyHelper, we have to use the
+ * DBusProxy class as a template typename.
+ */
+
+* DBusMultiEvent.h:
+ /*
+ * XXX DBusProxy declares a private DBusReadonlyAttribute variable, which
+ * cuases a circular dependency. As a workaround the DBusProxy must be
+ * forward declared and set as default parameter to the template attribute
+ * classes.
+ *
+ * Since DBus*Attribute use the DBusProxyHelper, we have to use the
+ * DBusProxy class as a template typename.
+ */
+ //TODO: if rehashing occurs, then all iterators are invalidated.
+ //TODO: rework with pointers, since this is D-Bus only
+ typedef typename ListenersMap::iterator Subscription;
+
+* DBusAttribute.h:
+ /*
+ * XXX DBusProxy declares a private DBusReadonlyAttribute variable, which
+ * causes a circular dependency. As a workaround the DBusProxy must be
+ * forward declared and set as default parameter to the template attribute
+ * classes.
+ */
+
+* DBusServiceRegistry.h:
+ isServiceInstanceAlive: //TODO Fallback for services not in dbus object manager
+
+* DBus Generator: implizite Array-Deklaration via "[]" (z.B. UInt32[] in Methoden-Aufruf) unterstützen!
+
+
+
+
+Future development (2.1):
+
+* Request Name for DBusStubAdapter:
+ The D-Bus specification states that a single D-Bus connection might own multiple names.
+ We have to make sure that when a register request comes from the CommonAPI StubAdapter
+ Factory that we make sure that the name is already owned by our DBusConnection.
+ Probably we'll have to keep a list of all owned names and request a new one on registration
+ if required.
+
+* Check static/dynamic loading of libraries, make it work.
+
+* Doxygen in CommonAPI source code.
+
+* Main Loop Integration
+ - Per Factory or on Runtime level?
+ - Which functions are needed?
+ - Example with Glib on CommonAPI base (not D-Bus specific)
+ - Christian Linke has some ideas
+
+- Handling of D-Bus properties!! Sollte auf Franca attributes gemapped sein (Grund: Interoperabilität)
+
+* getValue on attributes is inconsisten with other methods, CallStatus should be in signature not return
\ No newline at end of file
--- /dev/null
+# Copyright (c) 2009 Oren Ben-Kiki <oren@ben-kiki.org>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+#
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_prog_doxygen.html
+# ===========================================================================
+#
+
+## --------------------------------- ##
+## Format-independent Doxygen rules. ##
+## --------------------------------- ##
+
+if DX_COND_doc
+
+## ------------------------------- ##
+## Rules specific for HTML output. ##
+## ------------------------------- ##
+
+if DX_COND_html
+
+DX_CLEAN_HTML = @DX_DOCDIR@/html
+
+endif # DX_COND_html
+
+## ------------------------------ ##
+## Rules specific for CHM output. ##
+## ------------------------------ ##
+
+if DX_COND_chm
+
+DX_CLEAN_CHM = @DX_DOCDIR@/chm
+
+if DX_COND_chi
+
+DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi
+
+endif # DX_COND_chi
+
+endif # DX_COND_chm
+
+## ------------------------------ ##
+## Rules specific for MAN output. ##
+## ------------------------------ ##
+
+if DX_COND_man
+
+DX_CLEAN_MAN = @DX_DOCDIR@/man
+
+endif # DX_COND_man
+
+## ------------------------------ ##
+## Rules specific for RTF output. ##
+## ------------------------------ ##
+
+if DX_COND_rtf
+
+DX_CLEAN_RTF = @DX_DOCDIR@/rtf
+
+endif # DX_COND_rtf
+
+## ------------------------------ ##
+## Rules specific for XML output. ##
+## ------------------------------ ##
+
+if DX_COND_xml
+
+DX_CLEAN_XML = @DX_DOCDIR@/xml
+
+endif # DX_COND_xml
+
+## ----------------------------- ##
+## Rules specific for PS output. ##
+## ----------------------------- ##
+
+if DX_COND_ps
+
+DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps
+
+DX_PS_GOAL = doxygen-ps
+
+doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps
+
+@DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag
+ cd @DX_DOCDIR@/latex; \
+ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
+ $(DX_LATEX) refman.tex; \
+ $(MAKEINDEX_PATH) refman.idx; \
+ $(DX_LATEX) refman.tex; \
+ countdown=5; \
+ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
+ refman.log > /dev/null 2>&1 \
+ && test $$countdown -gt 0; do \
+ $(DX_LATEX) refman.tex; \
+ countdown=`expr $$countdown - 1`; \
+ done; \
+ $(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi
+
+endif # DX_COND_ps
+
+## ------------------------------ ##
+## Rules specific for PDF output. ##
+## ------------------------------ ##
+
+if DX_COND_pdf
+
+DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf
+
+DX_PDF_GOAL = doxygen-pdf
+
+doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf
+
+@DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag
+ cd @DX_DOCDIR@/latex; \
+ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
+ $(DX_PDFLATEX) refman.tex; \
+ $(DX_MAKEINDEX) refman.idx; \
+ $(DX_PDFLATEX) refman.tex; \
+ countdown=5; \
+ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
+ refman.log > /dev/null 2>&1 \
+ && test $$countdown -gt 0; do \
+ $(DX_PDFLATEX) refman.tex; \
+ countdown=`expr $$countdown - 1`; \
+ done; \
+ mv refman.pdf ../@PACKAGE@.pdf
+
+endif # DX_COND_pdf
+
+## ------------------------------------------------- ##
+## Rules specific for LaTeX (shared for PS and PDF). ##
+## ------------------------------------------------- ##
+
+if DX_COND_latex
+
+DX_CLEAN_LATEX = @DX_DOCDIR@/latex
+
+endif # DX_COND_latex
+
+.PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL)
+
+.INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
+
+doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag
+
+doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
+
+@DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS)
+ rm -rf @DX_DOCDIR@
+ $(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG)
+
+DX_CLEANFILES = \
+ @DX_DOCDIR@/@PACKAGE@.tag \
+ -r \
+ $(DX_CLEAN_HTML) \
+ $(DX_CLEAN_CHM) \
+ $(DX_CLEAN_CHI) \
+ $(DX_CLEAN_MAN) \
+ $(DX_CLEAN_RTF) \
+ $(DX_CLEAN_XML) \
+ $(DX_CLEAN_PS) \
+ $(DX_CLEAN_PDF) \
+ $(DX_CLEAN_LATEX)
+
+endif # DX_COND_doc
\ No newline at end of file
--- /dev/null
+AC_PREREQ(2.61)
+AC_INIT([GENIVI Common API DBus C++ Library],
+ [0.7],
+ [],
+ [CommonAPI-DBus])
+
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_AUX_DIR([build-aux])
+AC_CONFIG_HEADERS([build-aux/config.h])
+AC_CONFIG_FILES([
+ Makefile
+ CommonAPI-DBus.pc
+ CommonAPI-DBus-uninstalled.pc])
+
+AC_CANONICAL_SYSTEM
+
+AM_INIT_AUTOMAKE([foreign 1.11 silent-rules subdir-objects color-tests -Wall -Werror])
+AM_SILENT_RULES
+AM_MAINTAINER_MODE
+
+AC_PROG_CXX
+AC_LANG([C++])
+AX_CXX_COMPILE_STDCXX_11([noext])
+
+AC_ARG_VAR([GTEST_CONFIG], [The exact path of Google Test's 'gtest-config' script.])
+
+LT_PREREQ(2.2)
+LT_INIT
+
+PKG_PROG_PKG_CONFIG
+PKG_CHECK_MODULES(COMMONAPI, [CommonAPI >= 0.7])
+PKG_CHECK_MODULES(DBUS, [dbus-1 >= 1.4.6])
+
+GTEST_MIN_VERSION="1.6.0"
+GTEST_URL="http://code.google.com/p/googletest"
+
+
+AC_ARG_VAR([GTEST_CONFIG], [The exact path of Google Test's 'gtest-config' script.])
+AC_ARG_VAR([GTEST_CPPFLAGS], [C-like preprocessor flags for Google Test.])
+AC_ARG_VAR([GTEST_CXXFLAGS], [C++ compile flags for Google Test.])
+AC_ARG_VAR([GTEST_LDFLAGS], [Linker path and option flags for Google Test.])
+AC_ARG_VAR([GTEST_LIBS], [Library linking flags for Google Test.])
+AC_ARG_VAR([GTEST_VERSION], [The available version of Google Test.])
+
+AS_IF([test -f "${GTEST_CONFIG}"],
+ [AS_IF([${GTEST_CONFIG} --min-version=${GTEST_MIN_VERSION}],
+ [],
+ [AC_MSG_ERROR([dnl
+ Found Google Test Version ${GTEST_VERSION}. However ${GTEST_MIN_VERSION} is
+ required. Please refer to ${GTEST_URL} for a more recent version.])])
+ [GTEST_CPPFLAGS=`${GTEST_CONFIG} --cppflags`]
+ [GTEST_CXXFLAGS=`${GTEST_CONFIG} --cxxflags`]
+ [GTEST_LDFLAGS=`${GTEST_CONFIG} --ldflags`]
+ [GTEST_LIBS=`${GTEST_CONFIG} --libs`]
+ [GTEST_VERSION=`${GTEST_CONFIG} --version`]
+ ]
+ []
+)
+
+AM_CONDITIONAL(ENABLE_TESTS, [test -f "${GTEST_CONFIG}"])
+
+
+# Doxygen support
+DX_HTML_FEATURE(ON)
+DX_CHM_FEATURE(OFF)
+DX_CHI_FEATURE(OFF)
+DX_MAN_FEATURE(OFF)
+DX_RTF_FEATURE(OFF)
+DX_XML_FEATURE(OFF)
+DX_PDF_FEATURE(OFF)
+DX_PS_FEATURE(OFF)
+DX_INIT_DOXYGEN(${PACKAGE_NAME}, doxygen.cfg, doc)
+
+AC_MSG_RESULT([
+ $PACKAGE_NAME v$VERSION
+
+ enable docs: ${ENABLE_DOCS}
+
+ COMMONAPI_CFLAGS: ${COMMONAPI_CFLAGS}
+ COMMONAPI_LIBS: ${COMMONAPI_LIBS}
+
+ DBUS_CFLAGS: ${DBUS_CFLAGS}
+ DBUS_LIBS: ${DBUS_LIBS}
+
+ GTEST_CONFIG: ${GTEST_CONFIG}
+ GTEST_CPPFLAGS: ${GTEST_CPPFLAGS}
+ GTEST_CXXFLAGS: ${GTEST_CXXFLAGS}
+ GTEST_LDFLAGS: ${GTEST_LDFLAGS}
+ GTEST_LIBS: ${GTEST_LIBS}
+ GTEST_VERSION: ${GTEST_VERSION}
+
+ prefix: ${prefix}
+ CXXFLAGS: ${CXXFLAGS}
+ LDFLAGS: ${LDFLAGS}
+])
+
+AC_OUTPUT
\ No newline at end of file
--- /dev/null
+From 467a2e307462b02865b35397c572b6048c2934e2 Mon Sep 17 00:00:00 2001
+From: Aleksandar Kanchev <kanchev@itestra.com>
+Date: Mon, 9 Jul 2012 18:09:04 +0200
+Subject: [PATCH] DBusMessage: add support for custom marshaling
+
+Add functions to support querying and manipulating the message body and
+signature. This is useful for code generators, which can generate custom
+marshaling functions based on a given IDL. Those functions tend to be
+optimized and faster than the generic iterator based marshaling.
+---
+ dbus/dbus-message.c | 143 +++++++++++++++++++++++++++++++++++----------------
+ dbus/dbus-message.h | 13 +++++
+ dbus/dbus-string.c | 16 ++++++
+ dbus/dbus-string.h | 4 ++
+ 4 files changed, 132 insertions(+), 44 deletions(-)
+
+diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
+index 24ef5ac..fbacfba 100644
+--- a/dbus/dbus-message.c
++++ b/dbus/dbus-message.c
+@@ -356,50 +356,6 @@ set_or_delete_string_field (DBusMessage *message,
+ &value);
+ }
+
+-#if 0
+-/* Probably we don't need to use this */
+-/**
+- * Sets the signature of the message, i.e. the arguments in the
+- * message payload. The signature includes only "in" arguments for
+- * #DBUS_MESSAGE_TYPE_METHOD_CALL and only "out" arguments for
+- * #DBUS_MESSAGE_TYPE_METHOD_RETURN, so is slightly different from
+- * what you might expect (it does not include the signature of the
+- * entire C++-style method).
+- *
+- * The signature is a string made up of type codes such as
+- * #DBUS_TYPE_INT32. The string is terminated with nul (nul is also
+- * the value of #DBUS_TYPE_INVALID). The macros such as
+- * #DBUS_TYPE_INT32 evaluate to integers; to assemble a signature you
+- * may find it useful to use the string forms, such as
+- * #DBUS_TYPE_INT32_AS_STRING.
+- *
+- * An "unset" or #NULL signature is considered the same as an empty
+- * signature. In fact dbus_message_get_signature() will never return
+- * #NULL.
+- *
+- * @param message the message
+- * @param signature the type signature or #NULL to unset
+- * @returns #FALSE if no memory
+- */
+-static dbus_bool_t
+-_dbus_message_set_signature (DBusMessage *message,
+- const char *signature)
+-{
+- _dbus_return_val_if_fail (message != NULL, FALSE);
+- _dbus_return_val_if_fail (!message->locked, FALSE);
+- _dbus_return_val_if_fail (signature == NULL ||
+- _dbus_check_is_valid_signature (signature));
+- /* can't delete the signature if you have a message body */
+- _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 ||
+- signature != NULL);
+-
+- return set_or_delete_string_field (message,
+- DBUS_HEADER_FIELD_SIGNATURE,
+- DBUS_TYPE_SIGNATURE,
+- signature);
+-}
+-#endif
+-
+ /* Message Cache
+ *
+ * We cache some DBusMessage to reduce the overhead of allocating
+@@ -3370,6 +3326,47 @@ dbus_message_get_sender (DBusMessage *message)
+ }
+
+ /**
++ * Sets the signature of the message, i.e. the arguments in the
++ * message payload. The signature includes only "in" arguments for
++ * #DBUS_MESSAGE_TYPE_METHOD_CALL and only "out" arguments for
++ * #DBUS_MESSAGE_TYPE_METHOD_RETURN, so is slightly different from
++ * what you might expect (it does not include the signature of the
++ * entire C++-style method).
++ *
++ * The signature is a string made up of type codes such as
++ * #DBUS_TYPE_INT32. The string is terminated with nul (nul is also
++ * the value of #DBUS_TYPE_INVALID). The macros such as
++ * #DBUS_TYPE_INT32 evaluate to integers; to assemble a signature you
++ * may find it useful to use the string forms, such as
++ * #DBUS_TYPE_INT32_AS_STRING.
++ *
++ * An "unset" or #NULL signature is considered the same as an empty
++ * signature. In fact dbus_message_get_signature() will never return
++ * #NULL.
++ *
++ * @param message the message
++ * @param signature the type signature or #NULL to unset
++ * @returns #FALSE if no memory
++ */
++dbus_bool_t
++dbus_message_set_signature (DBusMessage *message,
++ const char *signature)
++{
++ _dbus_return_val_if_fail (message != NULL, FALSE);
++ _dbus_return_val_if_fail (!message->locked, FALSE);
++ _dbus_return_val_if_fail (signature == NULL ||
++ _dbus_check_is_valid_signature (signature), FALSE);
++ /* can't delete the signature if you have a message body */
++ _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 ||
++ signature != NULL, FALSE);
++
++ return set_or_delete_string_field (message,
++ DBUS_HEADER_FIELD_SIGNATURE,
++ DBUS_TYPE_SIGNATURE,
++ signature);
++}
++
++/**
+ * Gets the type signature of the message, i.e. the arguments in the
+ * message payload. The signature includes only "in" arguments for
+ * #DBUS_MESSAGE_TYPE_METHOD_CALL and only "out" arguments for
+@@ -4519,6 +4516,64 @@ dbus_message_type_to_string (int type)
+ }
+
+ /**
++ * Returns pointer to the buffer used to store the message body.
++ *
++ * @param message the message
++ * @return pointer to the message body memory
++ */
++char*
++dbus_message_get_body (DBusMessage *message) {
++ _dbus_return_val_if_fail (message != NULL, NULL);
++
++ return _dbus_string_get_data(&(message->body));
++}
++
++/**
++ * Adjust the length of the message body buffer. The memory will be reallocated
++ * if the new length is bigger than the already allocated size.
++ *
++ * @see dbus_message_get_body_allocated
++ * @param message the message
++ * @param length the new length of the body
++ * @return #TRUE if successful
++ */
++dbus_bool_t
++dbus_message_set_body_length (DBusMessage *message,
++ int length) {
++ _dbus_return_val_if_fail (message != NULL, FALSE);
++ _dbus_return_val_if_fail (length >= 0, FALSE);
++
++ return _dbus_string_set_length(&(message->body), length);
++}
++
++/**
++ * Gets the length of the message body buffer.
++ *
++ * @param message the message
++ * @param length the new length of the body
++ * @return the length of the body buffer
++ */
++int
++dbus_message_get_body_length (DBusMessage *message) {
++ _dbus_return_val_if_fail (message != NULL, 0);
++
++ return _dbus_string_get_length(&(message->body));
++}
++
++/**
++ * Gets the allocated memory size used to hold the message body.
++ *
++ * @param message the message
++ * @return size of the allocated message body memory
++ */
++int
++dbus_message_get_body_allocated (DBusMessage *message) {
++ _dbus_return_val_if_fail (message != NULL, 0);
++
++ return _dbus_string_get_allocated(&(message->body));
++}
++
++/**
+ * Turn a DBusMessage into the marshalled form as described in the D-Bus
+ * specification.
+ *
+diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h
+index 5500492..55388ac 100644
+--- a/dbus/dbus-message.h
++++ b/dbus/dbus-message.h
+@@ -138,6 +138,9 @@ dbus_bool_t dbus_message_set_sender (DBusMessage *message,
+ DBUS_EXPORT
+ const char* dbus_message_get_sender (DBusMessage *message);
+ DBUS_EXPORT
++dbus_bool_t dbus_message_set_signature (DBusMessage *message,
++ const char *signature);
++DBUS_EXPORT
+ const char* dbus_message_get_signature (DBusMessage *message);
+ DBUS_EXPORT
+ void dbus_message_set_no_reply (DBusMessage *message,
+@@ -264,6 +267,16 @@ void dbus_message_iter_abandon_container (DBusMessageIter *iter,
+ DBusMessageIter *sub);
+
+ DBUS_EXPORT
++char* dbus_message_get_body (DBusMessage *message);
++DBUS_EXPORT
++dbus_bool_t dbus_message_set_body_length (DBusMessage *message,
++ int length);
++DBUS_EXPORT
++int dbus_message_get_body_length (DBusMessage *message);
++DBUS_EXPORT
++int dbus_message_get_body_allocated (DBusMessage *message);
++
++DBUS_EXPORT
+ void dbus_message_lock (DBusMessage *message);
+
+ DBUS_EXPORT
+diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c
+index e2eb93b..d8628ba 100644
+--- a/dbus/dbus-string.c
++++ b/dbus/dbus-string.c
+@@ -848,6 +848,22 @@ _dbus_string_get_length (const DBusString *str)
+ }
+ #endif /* !_dbus_string_get_length */
+
++/* Only have the function if we don't have the macro */
++#ifndef _dbus_string_get_allocated
++/**
++ * Gets the allocated length of a string (not including nul termination).
++ *
++ * @returns the allocated length.
++ */
++int
++_dbus_string_get_allocated(const DBusString *str)
++{
++ DBUS_CONST_STRING_PREAMBLE (str);
++
++ return real->allocated;
++}
++#endif /* !_dbus_string_get_allocated */
++
+ /**
+ * Makes a string longer by the given number of bytes. Checks whether
+ * adding additional_length to the current length would overflow an
+diff --git a/dbus/dbus-string.h b/dbus/dbus-string.h
+index 2f1ed31..490aea6 100644
+--- a/dbus/dbus-string.h
++++ b/dbus/dbus-string.h
+@@ -62,6 +62,7 @@ struct DBusString
+ */
+ #define _dbus_string_get_data(s) ((char*)(((DBusString*)(s))->dummy1))
+ #define _dbus_string_get_length(s) (((DBusString*)(s))->dummy2)
++#define _dbus_string_get_allocated(s) (((DBusString*)(s))->dummy3 - _DBUS_STRING_ALLOCATION_PADDING)
+ #define _dbus_string_set_byte(s, i, b) ((((unsigned char*)(((DBusString*)(s))->dummy1))[(i)]) = (unsigned char) (b))
+ #define _dbus_string_get_byte(s, i) (((const unsigned char*)(((DBusString*)(s))->dummy1))[(i)])
+ #define _dbus_string_get_const_data(s) ((const char*)(((DBusString*)(s))->dummy1))
+@@ -131,6 +132,9 @@ void _dbus_string_copy_to_buffer_with_nul (const DBusString *str,
+ #ifndef _dbus_string_get_length
+ int _dbus_string_get_length (const DBusString *str);
+ #endif /* !_dbus_string_get_length */
++#ifndef _dbus_string_get_allocated
++int _dbus_string_get_allocated (const DBusString *str);
++#endif /* !_dbus_string_get_allocated */
+
+ dbus_bool_t _dbus_string_lengthen (DBusString *str,
+ int additional_length);
+--
+1.7.10.2
+
--- /dev/null
+From 762a0ceb1ff6b4c69eced23902fbc404870f21ca Mon Sep 17 00:00:00 2001
+From: Philip Rauwolf <rauwolf@itestra.de>
+Date: Fri, 3 Aug 2012 16:34:59 +0200
+Subject: [PATCH] Disabled all data checks in DBUS
+
+---
+ dbus/dbus-message.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
+index 5e570bd..9883e70 100644
+--- a/dbus/dbus-message.c
++++ b/dbus/dbus-message.c
+@@ -3960,7 +3960,7 @@ load_message (DBusMessageLoader *loader,
+ DBusValidationMode mode;
+ dbus_uint32_t n_unix_fds = 0;
+
+- mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
++ mode = DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY;
+
+ oom = FALSE;
+
+--
+1.7.10.4
+
--- /dev/null
+# Doxyfile 1.8.1.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME = $(PROJECT)-$(VERSION)
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = $(DOCDIR)
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH = $(SRCDIR)
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this
+# tag. The format is ext=language, where ext is a file extension, and language
+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
+# comments according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you
+# can mix doxygen, HTML, and XML commands with Markdown formatting.
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 0
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = $(SRCDIR)
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = $(GENERATE_HTML)
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# style sheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
+# entries shown in the various tree structured indices initially; the user
+# can expand and collapse entries dynamically later on. Doxygen will expand
+# the tree to such a level that at most the specified number of entries are
+# visible (unless a fully collapsed tree already exceeds this amount).
+# So setting the number of entries 1 will produce a full collapsed tree by
+# default. 0 is a special value representing an infinite number of entries
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = $(GENERATE_HTMLHELP)
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE = ../$(PROJECT).chm
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION = $(HHC_PATH)
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = $(GENERATE_CHI)
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = YES
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you may also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to
+# the MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax.
+# However, it is strongly recommended to install a local
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = $(GENERATE_LATEX)
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME =
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME =
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = YES
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = $(PAPER_SIZE)
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = $(GENERATE_PDF)
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = YES
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = $(GENERATE_RTF)
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = YES
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = $(GENERATE_MAN)
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = $(GENERATE_XML)
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH = .
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = _DOXYGEN
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED = EASY_TYPE \
+ EASY_DESTRUCTOR \
+ EASY_METHOD
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. For each
+# tag file the location of the external documentation should be added. The
+# format of a tag file without this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths
+# or URLs. Note that each tag file must have a unique name (where the name does
+# NOT include the path). If a tag file is not located in the directory in which
+# doxygen is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE = $(DOCDIR)/$(PROJECT).tag
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/false
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = $(HAVE_DOT)
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside
+# the class node. If there are many fields or methods and many nodes the
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
+# threshold limits the number of items for each type to make the size more
+# managable. Set this to 0 for no limit. Note that the threshold may be
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH = $(DOT_PATH)
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<profiles version="1">
+<profile kind="CodeFormatterProfile" name="C++ Itestra" version="1">
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.lineSplit" value="120"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_member_access" value="0"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_constructor_initializer_list" value="82"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_exception_specification" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_exception_specification" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.comment.min_distance_between_code_and_line_comment" value="1"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.tabulation.size" value="4"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_enumerator_list" value="48"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_declarator_list" value="16"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_empty_lines" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.join_wrapped_lines" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation" value="48"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration" value="82"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_block" value="end_of_line"/>
+<setting id="org.eclipse.cdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.continuation_indentation" value="4"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_expression_list" value="0"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_conditional_expression" value="80"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_access_specifier_extra_spaces" value="0"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer" value="4"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_compact_if" value="0"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_assignment" value="16"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_conditional_expression_chain" value="18"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_exception_specification" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration" value="80"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_exception_specification" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_statements_compare_to_body" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_binary_expression" value="16"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_statements_compare_to_block" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.tabulation.char" value="space"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_colon_in_constructor_initializer_list" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
+<setting id="org.eclipse.cdt.core.formatter.compact_else_if" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_overloaded_left_shift_chain" value="16"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indentation.size" value="4"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration" value="end_of_line"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments" value="do not insert"/>
+</profile>
+</profiles>
\ No newline at end of file
--- /dev/null
+# ============================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+# AX_CXX_COMPILE_STDCXX_11([ext|noext])
+#
+# DESCRIPTION
+#
+# Check for baseline language coverage in the compiler for the C++11
+# standard; if necessary, add switches to CXXFLAGS to enable support.
+# Errors out if no mode that supports C++11 baseline syntax can be found.
+# The argument, if specified, indicates whether you insist on an extended
+# mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. -std=c++11).
+# If neither is specified, you get whatever works, with preference for an
+# extended mode.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
+# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 1
+
+m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [
+ template <typename T>
+ struct check
+ {
+ static_assert(sizeof(int) <= sizeof(T), "not big enough");
+ };
+
+ typedef check<check<bool>> right_angle_brackets;
+
+ int a;
+ decltype(a) b;
+
+ typedef check<int> check_type;
+ check_type c;
+ check_type&& cr = static_cast<check_type&&>(c);
+])
+
+AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl
+ m4_if([$1], [], [],
+ [$1], [ext], [],
+ [$1], [noext], [],
+ [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl
+ AC_LANG_ASSERT([C++])dnl
+ ac_success=no
+ AC_CACHE_CHECK(whether $CXX supports C++11 features by default,
+ ax_cv_cxx_compile_cxx11,
+ [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+ [ax_cv_cxx_compile_cxx11=yes],
+ [ax_cv_cxx_compile_cxx11=no])])
+ if test x$ax_cv_cxx_compile_cxx11 = xyes; then
+ ac_success=yes
+ fi
+
+ m4_if([$1], [noext], [], [dnl
+ if test x$ac_success = xno; then
+ for switch in -std=gnu++11 -std=gnu++0x; do
+ cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
+ AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
+ $cachevar,
+ [ac_save_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS $switch"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+ [eval $cachevar=yes],
+ [eval $cachevar=no])
+ CXXFLAGS="$ac_save_CXXFLAGS"])
+ if eval test x\$$cachevar = xyes; then
+ CXXFLAGS="$CXXFLAGS $switch"
+ ac_success=yes
+ break
+ fi
+ done
+ fi])
+
+ m4_if([$1], [ext], [], [dnl
+ if test x$ac_success = xno; then
+ for switch in -std=c++11 -std=c++0x; do
+ cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
+ AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
+ $cachevar,
+ [ac_save_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS $switch"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+ [eval $cachevar=yes],
+ [eval $cachevar=no])
+ CXXFLAGS="$ac_save_CXXFLAGS"])
+ if eval test x\$$cachevar = xyes; then
+ CXXFLAGS="$CXXFLAGS $switch"
+ ac_success=yes
+ break
+ fi
+ done
+ fi])
+
+ if test x$ac_success = xno; then
+ AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.])
+ fi
+])
--- /dev/null
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_prog_doxygen.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# DX_INIT_DOXYGEN(PROJECT-NAME, DOXYFILE-PATH, [OUTPUT-DIR])
+# DX_DOXYGEN_FEATURE(ON|OFF)
+# DX_DOT_FEATURE(ON|OFF)
+# DX_HTML_FEATURE(ON|OFF)
+# DX_CHM_FEATURE(ON|OFF)
+# DX_CHI_FEATURE(ON|OFF)
+# DX_MAN_FEATURE(ON|OFF)
+# DX_RTF_FEATURE(ON|OFF)
+# DX_XML_FEATURE(ON|OFF)
+# DX_PDF_FEATURE(ON|OFF)
+# DX_PS_FEATURE(ON|OFF)
+#
+# DESCRIPTION
+#
+# The DX_*_FEATURE macros control the default setting for the given
+# Doxygen feature. Supported features are 'DOXYGEN' itself, 'DOT' for
+# generating graphics, 'HTML' for plain HTML, 'CHM' for compressed HTML
+# help (for MS users), 'CHI' for generating a seperate .chi file by the
+# .chm file, and 'MAN', 'RTF', 'XML', 'PDF' and 'PS' for the appropriate
+# output formats. The environment variable DOXYGEN_PAPER_SIZE may be
+# specified to override the default 'a4wide' paper size.
+#
+# By default, HTML, PDF and PS documentation is generated as this seems to
+# be the most popular and portable combination. MAN pages created by
+# Doxygen are usually problematic, though by picking an appropriate subset
+# and doing some massaging they might be better than nothing. CHM and RTF
+# are specific for MS (note that you can't generate both HTML and CHM at
+# the same time). The XML is rather useless unless you apply specialized
+# post-processing to it.
+#
+# The macros mainly control the default state of the feature. The use can
+# override the default by specifying --enable or --disable. The macros
+# ensure that contradictory flags are not given (e.g.,
+# --enable-doxygen-html and --enable-doxygen-chm,
+# --enable-doxygen-anything with --disable-doxygen, etc.) Finally, each
+# feature will be automatically disabled (with a warning) if the required
+# programs are missing.
+#
+# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN
+# with the following parameters: a one-word name for the project for use
+# as a filename base etc., an optional configuration file name (the
+# default is 'Doxyfile', the same as Doxygen's default), and an optional
+# output directory name (the default is 'doxygen-doc').
+#
+# Automake Support
+#
+# The following is a template aminclude.am file for use with Automake.
+# Make targets and variables values are controlled by the various
+# DX_COND_* conditionals set by autoconf.
+#
+# The provided targets are:
+#
+# doxygen-doc: Generate all doxygen documentation.
+#
+# doxygen-run: Run doxygen, which will generate some of the
+# documentation (HTML, CHM, CHI, MAN, RTF, XML)
+# but will not do the post processing required
+# for the rest of it (PS, PDF, and some MAN).
+#
+# doxygen-man: Rename some doxygen generated man pages.
+#
+# doxygen-ps: Generate doxygen PostScript documentation.
+#
+# doxygen-pdf: Generate doxygen PDF documentation.
+#
+# Note that by default these are not integrated into the automake targets.
+# If doxygen is used to generate man pages, you can achieve this
+# integration by setting man3_MANS to the list of man pages generated and
+# then adding the dependency:
+#
+# $(man3_MANS): doxygen-doc
+#
+# This will cause make to run doxygen and generate all the documentation.
+#
+# The following variable is intended for use in Makefile.am:
+#
+# DX_CLEANFILES = everything to clean.
+#
+# Then add this variable to MOSTLYCLEANFILES.
+#
+# ----- begin aminclude.am -------------------------------------
+#
+# ## --------------------------------- ##
+# ## Format-independent Doxygen rules. ##
+# ## --------------------------------- ##
+#
+# if DX_COND_doc
+#
+# ## ------------------------------- ##
+# ## Rules specific for HTML output. ##
+# ## ------------------------------- ##
+#
+# if DX_COND_html
+#
+# DX_CLEAN_HTML = @DX_DOCDIR@/html
+#
+# endif DX_COND_html
+#
+# ## ------------------------------ ##
+# ## Rules specific for CHM output. ##
+# ## ------------------------------ ##
+#
+# if DX_COND_chm
+#
+# DX_CLEAN_CHM = @DX_DOCDIR@/chm
+#
+# if DX_COND_chi
+#
+# DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi
+#
+# endif DX_COND_chi
+#
+# endif DX_COND_chm
+#
+# ## ------------------------------ ##
+# ## Rules specific for MAN output. ##
+# ## ------------------------------ ##
+#
+# if DX_COND_man
+#
+# DX_CLEAN_MAN = @DX_DOCDIR@/man
+#
+# endif DX_COND_man
+#
+# ## ------------------------------ ##
+# ## Rules specific for RTF output. ##
+# ## ------------------------------ ##
+#
+# if DX_COND_rtf
+#
+# DX_CLEAN_RTF = @DX_DOCDIR@/rtf
+#
+# endif DX_COND_rtf
+#
+# ## ------------------------------ ##
+# ## Rules specific for XML output. ##
+# ## ------------------------------ ##
+#
+# if DX_COND_xml
+#
+# DX_CLEAN_XML = @DX_DOCDIR@/xml
+#
+# endif DX_COND_xml
+#
+# ## ----------------------------- ##
+# ## Rules specific for PS output. ##
+# ## ----------------------------- ##
+#
+# if DX_COND_ps
+#
+# DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps
+#
+# DX_PS_GOAL = doxygen-ps
+#
+# doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps
+#
+# @DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag
+# cd @DX_DOCDIR@/latex; \
+# rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
+# $(DX_LATEX) refman.tex; \
+# $(MAKEINDEX_PATH) refman.idx; \
+# $(DX_LATEX) refman.tex; \
+# countdown=5; \
+# while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
+# refman.log > /dev/null 2>&1 \
+# && test $$countdown -gt 0; do \
+# $(DX_LATEX) refman.tex; \
+# countdown=`expr $$countdown - 1`; \
+# done; \
+# $(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi
+#
+# endif DX_COND_ps
+#
+# ## ------------------------------ ##
+# ## Rules specific for PDF output. ##
+# ## ------------------------------ ##
+#
+# if DX_COND_pdf
+#
+# DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf
+#
+# DX_PDF_GOAL = doxygen-pdf
+#
+# doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf
+#
+# @DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag
+# cd @DX_DOCDIR@/latex; \
+# rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
+# $(DX_PDFLATEX) refman.tex; \
+# $(DX_MAKEINDEX) refman.idx; \
+# $(DX_PDFLATEX) refman.tex; \
+# countdown=5; \
+# while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
+# refman.log > /dev/null 2>&1 \
+# && test $$countdown -gt 0; do \
+# $(DX_PDFLATEX) refman.tex; \
+# countdown=`expr $$countdown - 1`; \
+# done; \
+# mv refman.pdf ../@PACKAGE@.pdf
+#
+# endif DX_COND_pdf
+#
+# ## ------------------------------------------------- ##
+# ## Rules specific for LaTeX (shared for PS and PDF). ##
+# ## ------------------------------------------------- ##
+#
+# if DX_COND_latex
+#
+# DX_CLEAN_LATEX = @DX_DOCDIR@/latex
+#
+# endif DX_COND_latex
+#
+# .PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL)
+#
+# .INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
+#
+# doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag
+#
+# doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
+#
+# @DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS)
+# rm -rf @DX_DOCDIR@
+# $(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG)
+#
+# DX_CLEANFILES = \
+# @DX_DOCDIR@/@PACKAGE@.tag \
+# -r \
+# $(DX_CLEAN_HTML) \
+# $(DX_CLEAN_CHM) \
+# $(DX_CLEAN_CHI) \
+# $(DX_CLEAN_MAN) \
+# $(DX_CLEAN_RTF) \
+# $(DX_CLEAN_XML) \
+# $(DX_CLEAN_PS) \
+# $(DX_CLEAN_PDF) \
+# $(DX_CLEAN_LATEX)
+#
+# endif DX_COND_doc
+#
+# ----- end aminclude.am ---------------------------------------
+#
+# LICENSE
+#
+# Copyright (c) 2009 Oren Ben-Kiki <oren@ben-kiki.org>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 12
+
+## ----------##
+## Defaults. ##
+## ----------##
+
+DX_ENV=""
+AC_DEFUN([DX_FEATURE_doc], ON)
+AC_DEFUN([DX_FEATURE_dot], OFF)
+AC_DEFUN([DX_FEATURE_man], OFF)
+AC_DEFUN([DX_FEATURE_html], ON)
+AC_DEFUN([DX_FEATURE_chm], OFF)
+AC_DEFUN([DX_FEATURE_chi], OFF)
+AC_DEFUN([DX_FEATURE_rtf], OFF)
+AC_DEFUN([DX_FEATURE_xml], OFF)
+AC_DEFUN([DX_FEATURE_pdf], ON)
+AC_DEFUN([DX_FEATURE_ps], ON)
+
+## --------------- ##
+## Private macros. ##
+## --------------- ##
+
+# DX_ENV_APPEND(VARIABLE, VALUE)
+# ------------------------------
+# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen.
+AC_DEFUN([DX_ENV_APPEND], [AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])])
+
+# DX_DIRNAME_EXPR
+# ---------------
+# Expand into a shell expression prints the directory part of a path.
+AC_DEFUN([DX_DIRNAME_EXPR],
+ [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']])
+
+# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF)
+# -------------------------------------
+# Expands according to the M4 (static) status of the feature.
+AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])])
+
+# DX_REQUIRE_PROG(VARIABLE, PROGRAM)
+# ----------------------------------
+# Require the specified program to be found for the DX_CURRENT_FEATURE to work.
+AC_DEFUN([DX_REQUIRE_PROG], [
+AC_PATH_TOOL([$1], [$2])
+if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then
+ AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
+ AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
+fi
+])
+
+# DX_TEST_FEATURE(FEATURE)
+# ------------------------
+# Expand to a shell expression testing whether the feature is active.
+AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1])
+
+# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE)
+# -------------------------------------------------
+# Verify that a required features has the right state before trying to turn on
+# the DX_CURRENT_FEATURE.
+AC_DEFUN([DX_CHECK_DEPEND], [
+test "$DX_FLAG_$1" = "$2" \
+|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1,
+ requires, contradicts) doxygen-DX_CURRENT_FEATURE])
+])
+
+# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE)
+# ----------------------------------------------------------
+# Turn off the DX_CURRENT_FEATURE if the required feature is off.
+AC_DEFUN([DX_CLEAR_DEPEND], [
+test "$DX_FLAG_$1" = "$2" || AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
+])
+
+# DX_FEATURE_ARG(FEATURE, DESCRIPTION,
+# CHECK_DEPEND, CLEAR_DEPEND,
+# REQUIRE, DO-IF-ON, DO-IF-OFF)
+# --------------------------------------------
+# Parse the command-line option controlling a feature. CHECK_DEPEND is called
+# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND),
+# otherwise CLEAR_DEPEND is called to turn off the default state if a required
+# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional
+# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and
+# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature.
+AC_DEFUN([DX_ARG_ABLE], [
+ AC_DEFUN([DX_CURRENT_FEATURE], [$1])
+ AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2])
+ AC_ARG_ENABLE(doxygen-$1,
+ [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1],
+ [--enable-doxygen-$1]),
+ DX_IF_FEATURE([$1], [don't $2], [$2]))],
+ [
+case "$enableval" in
+#(
+y|Y|yes|Yes|YES)
+ AC_SUBST([DX_FLAG_$1], 1)
+ $3
+;; #(
+n|N|no|No|NO)
+ AC_SUBST([DX_FLAG_$1], 0)
+;; #(
+*)
+ AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1])
+;;
+esac
+], [
+AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)])
+$4
+])
+if DX_TEST_FEATURE([$1]); then
+ $5
+ :
+fi
+AM_CONDITIONAL(DX_COND_$1, DX_TEST_FEATURE([$1]))
+if DX_TEST_FEATURE([$1]); then
+ $6
+ :
+else
+ $7
+ :
+fi
+])
+
+## -------------- ##
+## Public macros. ##
+## -------------- ##
+
+# DX_XXX_FEATURE(DEFAULT_STATE)
+# -----------------------------
+AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])])
+AC_DEFUN([DX_DOT_FEATURE], [AC_DEFUN([DX_FEATURE_dot], [$1])])
+AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])])
+AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])])
+AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])])
+AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])])
+AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])])
+AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
+AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
+AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])])
+AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])])
+
+# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR])
+# ---------------------------------------------------------
+# PROJECT also serves as the base name for the documentation files.
+# The default CONFIG-FILE is "Doxyfile" and OUTPUT-DOC-DIR is "doxygen-doc".
+AC_DEFUN([DX_INIT_DOXYGEN], [
+
+# Files:
+AC_SUBST([DX_PROJECT], [$1])
+AC_SUBST([DX_CONFIG], [ifelse([$2], [], Doxyfile, [$2])])
+AC_SUBST([DX_DOCDIR], [ifelse([$3], [], doxygen-doc, [$3])])
+
+# Environment variables used inside doxygen.cfg:
+DX_ENV_APPEND(SRCDIR, $srcdir)
+DX_ENV_APPEND(PROJECT, $DX_PROJECT)
+DX_ENV_APPEND(DOCDIR, $DX_DOCDIR)
+DX_ENV_APPEND(VERSION, $PACKAGE_VERSION)
+
+# Doxygen itself:
+DX_ARG_ABLE(doc, [generate any doxygen documentation],
+ [],
+ [],
+ [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen)
+ DX_REQUIRE_PROG([DX_PERL], perl)],
+ [DX_ENV_APPEND(PERL_PATH, $DX_PERL)])
+
+# Dot for graphics:
+DX_ARG_ABLE(dot, [generate graphics for doxygen documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_DOT], dot)],
+ [DX_ENV_APPEND(HAVE_DOT, YES)
+ DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])],
+ [DX_ENV_APPEND(HAVE_DOT, NO)])
+
+# Man pages generation:
+DX_ARG_ABLE(man, [generate doxygen manual pages],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_MAN, YES)],
+ [DX_ENV_APPEND(GENERATE_MAN, NO)])
+
+# RTF file generation:
+DX_ARG_ABLE(rtf, [generate doxygen RTF documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_RTF, YES)],
+ [DX_ENV_APPEND(GENERATE_RTF, NO)])
+
+# XML file generation:
+DX_ARG_ABLE(xml, [generate doxygen XML documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_XML, YES)],
+ [DX_ENV_APPEND(GENERATE_XML, NO)])
+
+# (Compressed) HTML help generation:
+DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_HHC], hhc)],
+ [DX_ENV_APPEND(HHC_PATH, $DX_HHC)
+ DX_ENV_APPEND(GENERATE_HTML, YES)
+ DX_ENV_APPEND(GENERATE_HTMLHELP, YES)],
+ [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)])
+
+# Seperate CHI file generation.
+DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file],
+ [DX_CHECK_DEPEND(chm, 1)],
+ [DX_CLEAR_DEPEND(chm, 1)],
+ [],
+ [DX_ENV_APPEND(GENERATE_CHI, YES)],
+ [DX_ENV_APPEND(GENERATE_CHI, NO)])
+
+# Plain HTML pages generation:
+DX_ARG_ABLE(html, [generate doxygen plain HTML documentation],
+ [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)],
+ [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)],
+ [],
+ [DX_ENV_APPEND(GENERATE_HTML, YES)],
+ [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)])
+
+# PostScript file generation:
+DX_ARG_ABLE(ps, [generate doxygen PostScript documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_LATEX], latex)
+ DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
+ DX_REQUIRE_PROG([DX_DVIPS], dvips)
+ DX_REQUIRE_PROG([DX_EGREP], egrep)])
+
+# PDF file generation:
+DX_ARG_ABLE(pdf, [generate doxygen PDF documentation],
+ [DX_CHECK_DEPEND(doc, 1)],
+ [DX_CLEAR_DEPEND(doc, 1)],
+ [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex)
+ DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
+ DX_REQUIRE_PROG([DX_EGREP], egrep)])
+
+# LaTeX generation for PS and/or PDF:
+AM_CONDITIONAL(DX_COND_latex, DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf))
+if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then
+ DX_ENV_APPEND(GENERATE_LATEX, YES)
+else
+ DX_ENV_APPEND(GENERATE_LATEX, NO)
+fi
+
+# Paper size for PS and/or PDF:
+AC_ARG_VAR(DOXYGEN_PAPER_SIZE,
+ [a4wide (default), a4, letter, legal or executive])
+case "$DOXYGEN_PAPER_SIZE" in
+#(
+"")
+ AC_SUBST(DOXYGEN_PAPER_SIZE, "")
+;; #(
+a4wide|a4|letter|legal|executive)
+ DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE)
+;; #(
+*)
+ AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE'])
+;;
+esac
+
+#For debugging:
+#echo DX_FLAG_doc=$DX_FLAG_doc
+#echo DX_FLAG_dot=$DX_FLAG_dot
+#echo DX_FLAG_man=$DX_FLAG_man
+#echo DX_FLAG_html=$DX_FLAG_html
+#echo DX_FLAG_chm=$DX_FLAG_chm
+#echo DX_FLAG_chi=$DX_FLAG_chi
+#echo DX_FLAG_rtf=$DX_FLAG_rtf
+#echo DX_FLAG_xml=$DX_FLAG_xml
+#echo DX_FLAG_pdf=$DX_FLAG_pdf
+#echo DX_FLAG_ps=$DX_FLAG_ps
+#echo DX_ENV=$DX_ENV
+])
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_DBUS_DBUS_ATTRIBUTE_H_
+#define COMMONAPI_DBUS_DBUS_ATTRIBUTE_H_
+
+#include "DBusProxyHelper.h"
+#include "DBusEvent.h"
+
+#include <cassert>
+
+namespace CommonAPI {
+namespace DBus {
+
+
+class DBusProxy;
+
+
+template <typename _AttributeType, typename _DBusProxyType = DBusProxy>
+class DBusReadonlyAttribute: public _AttributeType {
+ public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+
+ DBusReadonlyAttribute(_DBusProxyType& dbusProxy, const char* getMethodName):
+ dbusProxy_(dbusProxy),
+ getMethodName_(getMethodName) {
+ assert(getMethodName);
+ }
+
+ CallStatus getValue(ValueType& value) const {
+ CallStatus callStatus;
+ DBusProxyHelper<DBusSerializableArguments<>,
+ DBusSerializableArguments<ValueType> >::callMethodWithReply(dbusProxy_, getMethodName_, "", callStatus, value);
+ return callStatus;
+ }
+
+ std::future<CallStatus> getValueAsync(AttributeAsyncCallback attributeAsyncCallback) {
+ return DBusProxyHelper<DBusSerializableArguments<>,
+ DBusSerializableArguments<ValueType> >::callMethodAsync(dbusProxy_, getMethodName_, "", std::move(attributeAsyncCallback));
+ }
+
+ protected:
+ _DBusProxyType& dbusProxy_;
+ const char* getMethodName_;
+};
+
+
+template <typename _AttributeType, typename _DBusProxyType = DBusProxy>
+class DBusAttribute: public DBusReadonlyAttribute<_AttributeType> {
+ public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+
+ DBusAttribute(_DBusProxyType& dbusProxy, const char* setMethodName, const char* setMethodSignature, const char* getMethodName):
+ DBusReadonlyAttribute<_AttributeType>(dbusProxy, getMethodName),
+ setMethodName_(setMethodName),
+ setMethodSignature_(setMethodSignature) {
+ assert(setMethodName);
+ assert(setMethodSignature);
+ }
+
+ void setValue(const ValueType& requestValue, CallStatus& callStatus, ValueType& responseValue) {
+ DBusProxyHelper<DBusSerializableArguments<ValueType>,
+ DBusSerializableArguments<ValueType> >::callMethodWithReply(
+ this->dbusProxy_,
+ setMethodName_,
+ setMethodSignature_,
+ requestValue,
+ callStatus,
+ responseValue);
+ }
+
+ std::future<CallStatus> setValueAsync(const ValueType& requestValue, AttributeAsyncCallback attributeAsyncCallback) {
+ return DBusProxyHelper<DBusSerializableArguments<ValueType>,
+ DBusSerializableArguments<ValueType> >::callMethodAsync(
+ this->dbusProxy_,
+ setMethodName_,
+ setMethodSignature_,
+ requestValue,
+ attributeAsyncCallback);
+ }
+
+ protected:
+ const char* setMethodName_;
+ const char* setMethodSignature_;
+};
+
+
+template <typename _AttributeType, typename _DBusProxyType = DBusProxy>
+class DBusObservableAttribute: public _AttributeType {
+ public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+ typedef typename _AttributeType::ChangedEvent ChangedEvent;
+
+ template <typename... _AttributeTypeArguments>
+ DBusObservableAttribute(_DBusProxyType& dbusProxy, const char* changedEventName, _AttributeTypeArguments... arguments):
+ _AttributeType(dbusProxy, arguments...),
+ changedEvent_(dbusProxy, changedEventName, this->setMethodSignature_) {
+ }
+
+ ChangedEvent& getChangedEvent() {
+ return changedEvent_;
+ }
+
+ protected:
+ DBusEvent<ChangedEvent> changedEvent_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_ATTRIBUTE_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "DBusConnection.h"
+#include "DBusInputStream.h"
+
+#include <sstream>
+#include <cassert>
+#include <future>
+
+#include <iostream>
+
+namespace CommonAPI {
+namespace DBus {
+
+
+DBusObjectPathVTable DBusConnection::libdbusObjectPathVTable_ = {
+ NULL, // no need to handle unregister callbacks
+ &DBusConnection::onLibdbusObjectPathMessageThunk
+};
+
+void DBusConnection::dispatch() {
+ while (!stopDispatching_ && readWriteDispatch(10)) {
+ }
+}
+
+DBusConnection::DBusConnection(BusType busType) :
+ busType_(busType),
+ libdbusConnection_(NULL),
+ isLibdbusSignalFilterAdded_(false),
+ stopDispatching_(false) {
+ dbus_threads_init_default();
+}
+
+DBusConnection::DBusConnection(::DBusConnection* libDbusConnection) :
+ busType_(WRAPPED),
+ libdbusConnection_(libDbusConnection),
+ isLibdbusSignalFilterAdded_(false),
+ stopDispatching_(false) {
+ dbus_threads_init_default();
+}
+
+DBusConnection::~DBusConnection() {
+ if (isConnected()) {
+ disconnect();
+ }
+ dispatchThread_.join();
+}
+
+bool DBusConnection::connect() {
+ DBusError dbusError;
+ return connect(dbusError);
+}
+
+bool DBusConnection::connect(DBusError& dbusError) {
+ assert(!dbusError);
+
+ if (isConnected())
+ return true;
+
+ const ::DBusBusType libdbusType = static_cast<DBusBusType>(busType_);
+
+ libdbusConnection_ = dbus_bus_get_private(libdbusType, &dbusError.libdbusError_);
+ if (dbusError)
+ return false;
+
+ assert(libdbusConnection_);
+ dbus_connection_set_exit_on_disconnect(libdbusConnection_, false);
+
+ dbusConnectionStatusEvent_.notifyListeners(AvailabilityStatus::AVAILABLE);
+
+ initLibdbusObjectPathHandlerAfterConnect();
+
+ initLibdbusSignalFilterAfterConnect();
+
+ dispatchThread_ = std::thread(std::bind(&DBusConnection::dispatch, this));
+
+ return true;
+}
+
+void DBusConnection::disconnect() {
+ if (isConnected()) {
+ stopDispatching_ = true;
+ if (!dbusSignalMatchRulesMap_.empty()) {
+ dbus_connection_remove_filter(libdbusConnection_, &onLibdbusSignalFilterThunk, this);
+ }
+
+ dbus_connection_close(libdbusConnection_);
+ dbus_connection_unref(libdbusConnection_);
+ libdbusConnection_ = NULL;
+
+ dbusConnectionStatusEvent_.notifyListeners(AvailabilityStatus::NOT_AVAILABLE);
+ }
+}
+
+bool DBusConnection::isConnected() const {
+ return (libdbusConnection_ != NULL);
+}
+
+DBusConnectionStatusEvent& DBusConnection::getConnectionStatusEvent() {
+ return dbusConnectionStatusEvent_;
+}
+
+const std::shared_ptr<DBusServiceRegistry>& DBusConnection::getDBusServiceRegistry() {
+ if (!dbusServiceRegistry_) {
+ dbusServiceRegistry_ = std::make_shared<DBusServiceRegistry>(this->shared_from_this());
+ }
+
+ return dbusServiceRegistry_;
+}
+
+const std::shared_ptr<DBusDaemonProxy>& DBusConnection::getDBusDaemonProxy() {
+ if (!dbusDaemonProxy_) {
+ dbusDaemonProxy_ = std::make_shared<DBusDaemonProxy>(this->shared_from_this());
+ }
+
+ return dbusDaemonProxy_;
+}
+
+const std::shared_ptr<DBusObjectManager>& DBusConnection::getDBusObjectManager() {
+ if (!dbusObjectManager_) {
+ dbusObjectManager_ = std::make_shared<DBusObjectManager>(this->shared_from_this());
+ }
+
+ return dbusObjectManager_;
+}
+
+bool DBusConnection::requestServiceNameAndBlock(const std::string& serviceName) const {
+ DBusError dbusError;
+ const int libdbusStatus = dbus_bus_request_name(libdbusConnection_,
+ serviceName.c_str(),
+ DBUS_NAME_FLAG_DO_NOT_QUEUE,
+ &dbusError.libdbusError_);
+ const bool isServiceNameAcquired = (libdbusStatus == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+
+ return isServiceNameAcquired;
+}
+
+bool DBusConnection::releaseServiceName(const std::string& serviceName) const {
+ DBusError dbusError;
+ const int libdbusStatus = dbus_bus_release_name(libdbusConnection_,
+ serviceName.c_str(),
+ &dbusError.libdbusError_);
+ const bool isServiceNameReleased = (libdbusStatus == DBUS_RELEASE_NAME_REPLY_RELEASED);
+
+ return isServiceNameReleased;
+}
+
+bool DBusConnection::sendDBusMessage(const DBusMessage& dbusMessage, uint32_t* allocatedSerial) const {
+ assert(dbusMessage);
+ assert(isConnected());
+
+ dbus_uint32_t* libdbusSerial = static_cast<dbus_uint32_t*>(allocatedSerial);
+ const bool result = dbus_connection_send(libdbusConnection_, dbusMessage.libdbusMessage_, libdbusSerial);
+
+ return result;
+}
+
+void DBusConnection::onLibdbusPendingCallNotifyThunk(::DBusPendingCall* libdbusPendingCall, void *userData) {
+ assert(userData);
+ assert(libdbusPendingCall);
+
+ auto dbusMessageReplyAsyncHandler = reinterpret_cast<DBusMessageReplyAsyncHandler*>(userData);
+
+ ::DBusMessage* libdbusMessage = dbus_pending_call_steal_reply(
+ libdbusPendingCall);
+ const bool increaseLibdbusMessageReferenceCount = false;
+ DBusMessage dbusMessage(libdbusMessage, increaseLibdbusMessageReferenceCount);
+
+ dbusMessageReplyAsyncHandler->onDBusMessageReply(CallStatus::SUCCESS, dbusMessage);
+
+ // libdbus calls the Cleanup method below
+ dbus_pending_call_unref(libdbusPendingCall);
+}
+
+void DBusConnection::onLibdbusDataCleanup(void* userData) {
+ auto dbusMessageReplyAsyncHandler = reinterpret_cast<DBusMessageReplyAsyncHandler*>(userData);
+ delete dbusMessageReplyAsyncHandler;
+}
+
+std::future<CallStatus> DBusConnection::sendDBusMessageWithReplyAsync(
+ const DBusMessage& dbusMessage,
+ std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler,
+ int timeoutMilliseconds) const {
+
+ assert(dbusMessage);
+ assert(isConnected());
+
+ DBusPendingCall* libdbusPendingCall;
+ dbus_bool_t libdbusSuccess;
+
+ libdbusSuccess = dbus_connection_send_with_reply(
+ libdbusConnection_,
+ dbusMessage.libdbusMessage_,
+ &libdbusPendingCall,
+ timeoutMilliseconds);
+
+ if (!libdbusSuccess || !libdbusPendingCall) {
+ dbusMessageReplyAsyncHandler->onDBusMessageReply(CallStatus::CONNECTION_FAILED, dbusMessage);
+ return dbusMessageReplyAsyncHandler->getFuture();
+ }
+
+ libdbusSuccess = dbus_pending_call_set_notify(
+ libdbusPendingCall,
+ onLibdbusPendingCallNotifyThunk,
+ dbusMessageReplyAsyncHandler.get(),
+ onLibdbusDataCleanup);
+
+ if (!libdbusSuccess) {
+ dbusMessageReplyAsyncHandler->onDBusMessageReply(CallStatus::OUT_OF_MEMORY, dbusMessage);
+ dbus_pending_call_unref(libdbusPendingCall);
+ return dbusMessageReplyAsyncHandler->getFuture();
+ }
+
+ return dbusMessageReplyAsyncHandler.release()->getFuture();
+}
+
+
+DBusMessage DBusConnection::sendDBusMessageWithReplyAndBlock(const DBusMessage& dbusMessage,
+ DBusError& dbusError,
+ int timeoutMilliseconds) const {
+ assert(dbusMessage);
+ assert(!dbusError);
+ assert(isConnected());
+
+ ::DBusMessage* libdbusMessageReply = dbus_connection_send_with_reply_and_block(libdbusConnection_,
+ dbusMessage.libdbusMessage_,
+ timeoutMilliseconds,
+ &dbusError.libdbusError_);
+ if (dbusError)
+ return DBusMessage();
+
+ const bool increaseLibdbusMessageReferenceCount = false;
+ return DBusMessage(libdbusMessageReply, increaseLibdbusMessageReferenceCount);
+}
+
+
+bool DBusConnection::readWriteDispatch(int timeoutMilliseconds) {
+ if(isConnected()) {
+ const dbus_bool_t libdbusSuccess = dbus_connection_read_write_dispatch(libdbusConnection_,
+ timeoutMilliseconds);
+ return libdbusSuccess;
+ }
+ return false;
+}
+
+DBusProxyConnection::DBusSignalHandlerToken DBusConnection::addSignalMemberHandler(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName,
+ const std::string& interfaceMemberSignature,
+ DBusSignalHandler* dbusSignalHandler) {
+ DBusSignalHandlerPath dbusSignalHandlerPath(
+ objectPath,
+ interfaceName,
+ interfaceMemberName,
+ interfaceMemberSignature);
+ const bool isFirstSignalMemberHandler = dbusSignalHandlerTable_.find(dbusSignalHandlerPath) == dbusSignalHandlerTable_.end();
+
+ dbusSignalHandlerTable_.insert(DBusSignalHandlerTable::value_type(dbusSignalHandlerPath, dbusSignalHandler));
+
+ if (isFirstSignalMemberHandler)
+ addLibdbusSignalMatchRule(objectPath, interfaceName, interfaceMemberName);
+
+ return dbusSignalHandlerPath;
+}
+
+void DBusConnection::removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken) {
+ auto equalRangeIteratorPair = dbusSignalHandlerTable_.equal_range(dbusSignalHandlerToken);
+
+ // the range can't be empty!
+ assert(equalRangeIteratorPair.first != equalRangeIteratorPair.second);
+
+ // advance to the next element
+ equalRangeIteratorPair.first++;
+
+ // check if the first element was the only element
+ const bool isLastSignalMemberHandler = equalRangeIteratorPair.first == equalRangeIteratorPair.second;
+
+ if (isLastSignalMemberHandler) {
+ const std::string& objectPath = std::get<0>(dbusSignalHandlerToken);
+ const std::string& interfaceName = std::get<1>(dbusSignalHandlerToken);
+ const std::string& interfaceMemberName = std::get<2>(dbusSignalHandlerToken);
+
+ removeLibdbusSignalMatchRule(objectPath, interfaceName, interfaceMemberName);
+ }
+
+ dbusSignalHandlerTable_.erase(dbusSignalHandlerToken);
+}
+
+void DBusConnection::registerObjectPath(const std::string& objectPath) {
+ assert(!objectPath.empty());
+ assert(objectPath[0] == '/');
+
+ auto handlerIterator = libdbusRegisteredObjectPaths_.find(objectPath);
+ const bool foundRegisteredObjectPathHandler = handlerIterator != libdbusRegisteredObjectPaths_.end();
+
+ if (foundRegisteredObjectPathHandler) {
+ uint32_t& referenceCount = handlerIterator->second;
+
+ referenceCount++;
+
+ return;
+ }
+
+ libdbusRegisteredObjectPaths_.insert(LibdbusRegisteredObjectPathHandlersTable::value_type(objectPath, 1));
+
+ if (isConnected()) {
+ DBusError dbusError;
+ const dbus_bool_t libdbusSuccess = dbus_connection_try_register_object_path(libdbusConnection_,
+ objectPath.c_str(),
+ &libdbusObjectPathVTable_,
+ this,
+ &dbusError.libdbusError_);
+ assert(libdbusSuccess);
+ assert(!dbusError);
+ }
+}
+
+void DBusConnection::unregisterObjectPath(const std::string& objectPath) {
+ assert(!objectPath.empty());
+ assert(objectPath[0] == '/');
+
+ auto handlerIterator = libdbusRegisteredObjectPaths_.find(objectPath);
+ const bool foundRegisteredObjectPathHandler = handlerIterator != libdbusRegisteredObjectPaths_.end();
+
+ assert(foundRegisteredObjectPathHandler);
+
+ uint32_t& referenceCount = handlerIterator->second;
+ if (referenceCount > 1) {
+ referenceCount--;
+ return;
+ }
+
+ libdbusRegisteredObjectPaths_.erase(handlerIterator);
+
+ if (isConnected()) {
+ dbus_bool_t libdbusSuccess = dbus_connection_unregister_object_path(libdbusConnection_,
+ objectPath.c_str());
+ assert(libdbusSuccess);
+ }
+}
+
+void DBusConnection::addLibdbusSignalMatchRule(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName) {
+ DBusSignalMatchRuleTuple dbusSignalMatchRuleTuple(objectPath, interfaceName, interfaceMemberName);
+ auto matchRuleIterator = dbusSignalMatchRulesMap_.find(dbusSignalMatchRuleTuple);
+ const bool matchRuleFound = matchRuleIterator != dbusSignalMatchRulesMap_.end();
+
+ if (matchRuleFound) {
+ uint32_t& matchRuleReferenceCount = matchRuleIterator->second.first;
+ matchRuleReferenceCount++;
+ return;
+ }
+
+ const bool isFirstMatchRule = dbusSignalMatchRulesMap_.empty();
+
+ // generate D-Bus match rule string
+ std::ostringstream matchRuleStringStream;
+
+ matchRuleStringStream << "type='signal'";
+ matchRuleStringStream << ",path='" << objectPath << "'";
+ matchRuleStringStream << ",interface='" << interfaceName << "'";
+ matchRuleStringStream << ",member='" << interfaceMemberName << "'";
+
+ // add the match rule string to the map with reference count set to 1
+ std::string matchRuleString = matchRuleStringStream.str();
+ auto success = dbusSignalMatchRulesMap_.insert(
+ DBusSignalMatchRulesMap::value_type(dbusSignalMatchRuleTuple,
+ DBusSignalMatchRuleMapping(1, matchRuleString)));
+ assert(success.second);
+
+ // if not connected the filter and the rules will be added as soon as the connection is established
+ if (isConnected()) {
+ // add the libdbus message signal filter
+ if (isFirstMatchRule) {
+ const dbus_bool_t libdbusSuccess = dbus_connection_add_filter(libdbusConnection_,
+ &onLibdbusSignalFilterThunk,
+ this,
+ NULL);
+ assert(libdbusSuccess);
+ }
+
+ // finally add the match rule
+ DBusError dbusError;
+ dbus_bus_add_match(libdbusConnection_, matchRuleString.c_str(), &dbusError.libdbusError_);
+ assert(!dbusError);
+ }
+}
+
+void DBusConnection::removeLibdbusSignalMatchRule(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName) {
+ DBusSignalMatchRuleTuple dbusSignalMatchRuleTuple(objectPath, interfaceName, interfaceMemberName);
+ auto matchRuleIterator = dbusSignalMatchRulesMap_.find(dbusSignalMatchRuleTuple);
+ const bool matchRuleFound = matchRuleIterator != dbusSignalMatchRulesMap_.end();
+
+ assert(matchRuleFound);
+
+ uint32_t& matchRuleReferenceCount = matchRuleIterator->second.first;
+ if (matchRuleReferenceCount > 1) {
+ matchRuleReferenceCount--;
+ return;
+ }
+
+ const std::string& matchRuleString = matchRuleIterator->second.second;
+ DBusError dbusError;
+ dbus_bus_remove_match(libdbusConnection_, matchRuleString.c_str(), &dbusError.libdbusError_);
+ assert(!dbusError);
+
+ dbusSignalMatchRulesMap_.erase(matchRuleIterator);
+
+ const bool isLastMatchRule = dbusSignalMatchRulesMap_.empty();
+ if (isLastMatchRule)
+ dbus_connection_remove_filter(libdbusConnection_, &onLibdbusSignalFilterThunk, this);
+}
+
+void DBusConnection::initLibdbusObjectPathHandlerAfterConnect() {
+ assert(isConnected());
+
+ // nothing to do if there aren't any registered object path handlers
+ if (libdbusRegisteredObjectPaths_.empty())
+ return;
+
+ DBusError dbusError;
+ dbus_bool_t libdbusSuccess;
+
+ for ( auto handlerIterator = libdbusRegisteredObjectPaths_.begin();
+ handlerIterator != libdbusRegisteredObjectPaths_.end();
+ handlerIterator++) {
+ const std::string& objectPath = handlerIterator->first;
+
+ dbusError.clear();
+
+ libdbusSuccess = dbus_connection_try_register_object_path(libdbusConnection_,
+ objectPath.c_str(),
+ &libdbusObjectPathVTable_,
+ this,
+ &dbusError.libdbusError_);
+ assert(libdbusSuccess);
+ assert(!dbusError);
+ }
+}
+
+void DBusConnection::initLibdbusSignalFilterAfterConnect() {
+ assert(isConnected());
+
+ // nothing to do if there aren't any signal match rules
+ if (dbusSignalMatchRulesMap_.empty())
+ return;
+
+ // first we add the libdbus message signal filter
+ const dbus_bool_t libdbusSuccess = dbus_connection_add_filter(libdbusConnection_,
+ &onLibdbusSignalFilterThunk,
+ this,
+ NULL);
+ assert(libdbusSuccess);
+
+ // then we upload all match rules to the dbus-daemon
+ DBusError dbusError;
+ for (auto iterator = dbusSignalMatchRulesMap_.begin(); iterator != dbusSignalMatchRulesMap_.end(); iterator++) {
+ const std::string& matchRuleString = iterator->second.second;
+
+ dbusError.clear();
+ dbus_bus_add_match(libdbusConnection_, matchRuleString.c_str(), &dbusError.libdbusError_);
+ assert(!dbusError);
+ }
+}
+
+::DBusHandlerResult DBusConnection::onLibdbusObjectPathMessage(::DBusMessage* libdbusMessage) const {
+ assert(libdbusMessage);
+
+ // handle only method call messages
+ if (dbus_message_get_type(libdbusMessage) != DBUS_MESSAGE_TYPE_METHOD_CALL) {
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ bool isDBusMessageHandled = dbusObjectManager_->handleMessage(DBusMessage(libdbusMessage));
+ return isDBusMessageHandled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+::DBusHandlerResult DBusConnection::onLibdbusSignalFilter(::DBusMessage* libdbusMessage) {
+ assert(libdbusMessage);
+
+ // handle only signal messages
+ if (dbus_message_get_type(libdbusMessage) != DBUS_MESSAGE_TYPE_SIGNAL)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ const char* objectPath = dbus_message_get_path(libdbusMessage);
+ const char* interfaceName = dbus_message_get_interface(libdbusMessage);
+ const char* interfaceMemberName = dbus_message_get_member(libdbusMessage);
+ const char* interfaceMemberSignature = dbus_message_get_signature(libdbusMessage);
+
+ assert(objectPath);
+ assert(interfaceName);
+ assert(interfaceMemberName);
+ assert(interfaceMemberSignature);
+
+ DBusSignalHandlerPath dbusSignalHandlerPath(objectPath, interfaceName, interfaceMemberName, interfaceMemberSignature);
+ auto equalRangeIteratorPair = dbusSignalHandlerTable_.equal_range(dbusSignalHandlerPath);
+
+ if (equalRangeIteratorPair.first != equalRangeIteratorPair.second) {
+ DBusMessage dbusMessage(libdbusMessage);
+
+ while (equalRangeIteratorPair.first != equalRangeIteratorPair.second) {
+ DBusSignalHandler* dbusSignalHandler = equalRangeIteratorPair.first->second;
+ const SubscriptionStatus dbusSignalHandlerSubscriptionStatus = dbusSignalHandler->onSignalDBusMessage(dbusMessage);
+
+ if (dbusSignalHandlerSubscriptionStatus == SubscriptionStatus::CANCEL) {
+ auto dbusSignalHandlerSubscription = equalRangeIteratorPair.first;
+ equalRangeIteratorPair.first++;
+ dbusSignalHandlerTable_.erase(dbusSignalHandlerSubscription);
+ } else
+ equalRangeIteratorPair.first++;
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+::DBusHandlerResult DBusConnection::onLibdbusSignalFilterThunk(::DBusConnection* libdbusConnection,
+ ::DBusMessage* libdbusMessage,
+ void* userData) {
+ assert(libdbusConnection);
+ assert(libdbusMessage);
+ assert(userData);
+
+ DBusConnection* dbusConnection = reinterpret_cast<DBusConnection*>(userData);
+
+ assert(dbusConnection->libdbusConnection_ == libdbusConnection);
+
+ return dbusConnection->onLibdbusSignalFilter(libdbusMessage);
+}
+
+::DBusHandlerResult DBusConnection::onLibdbusObjectPathMessageThunk(::DBusConnection* libdbusConnection,
+ ::DBusMessage* libdbusMessage,
+ void* userData) {
+ assert(libdbusConnection);
+ assert(libdbusMessage);
+ assert(userData);
+
+ const DBusConnection* dbusConnection = reinterpret_cast<DBusConnection*>(userData);
+
+ assert(dbusConnection->libdbusConnection_ == libdbusConnection);
+
+ return dbusConnection->onLibdbusObjectPathMessage(libdbusMessage);
+}
+
+} // namespace DBus
+} // namespace CommonAPI
+
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_DBUS_DBUS_CONNECTION_H_
+#define COMMONAPI_DBUS_DBUS_CONNECTION_H_
+
+#include "DBusProxyConnection.h"
+#include "DBusDaemonProxy.h"
+#include "DBusServiceRegistry.h"
+#include "DBusObjectManager.h"
+
+#include <dbus/dbus.h>
+
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusConnection;
+class DBusObjectManager;
+
+class DBusConnectionStatusEvent: public Event<AvailabilityStatus> {
+ friend class DBusConnection;
+};
+
+
+class DBusConnection: public DBusProxyConnection, public std::enable_shared_from_this<DBusConnection> {
+ public:
+ enum BusType {
+ SESSION = DBUS_BUS_SESSION,
+ SYSTEM = DBUS_BUS_SYSTEM,
+ STARTER = DBUS_BUS_STARTER,
+ WRAPPED
+ };
+
+ inline static std::shared_ptr<DBusConnection> getBus(const BusType& busType);
+ inline static std::shared_ptr<DBusConnection> wrapLibDBus(::DBusConnection* libDbusConnection);
+ inline static std::shared_ptr<DBusConnection> getSessionBus();
+ inline static std::shared_ptr<DBusConnection> getSystemBus();
+ inline static std::shared_ptr<DBusConnection> getStarterBus();
+
+ DBusConnection(const DBusConnection&) = delete;
+ DBusConnection(::DBusConnection* libDbusConnection);
+
+ DBusConnection& operator=(const DBusConnection&) = delete;
+ virtual ~DBusConnection();
+
+ BusType getBusType() const;
+
+ bool connect();
+ bool connect(DBusError& dbusError);
+ void disconnect();
+
+ virtual bool isConnected() const;
+
+ virtual DBusConnectionStatusEvent& getConnectionStatusEvent();
+
+ virtual bool requestServiceNameAndBlock(const std::string& serviceName) const;
+ virtual bool releaseServiceName(const std::string& serviceName) const;
+
+ bool sendDBusMessage(const DBusMessage& dbusMessage, uint32_t* allocatedSerial = NULL) const;
+
+ static const int kDefaultSendTimeoutMs = 100 * 1000;
+
+ std::future<CallStatus> sendDBusMessageWithReplyAsync(
+ const DBusMessage& dbusMessage,
+ std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler,
+ int timeoutMilliseconds = kDefaultSendTimeoutMs) const;
+
+ DBusMessage sendDBusMessageWithReplyAndBlock(const DBusMessage& dbusMessage,
+ DBusError& dbusError,
+ int timeoutMilliseconds = kDefaultSendTimeoutMs) const;
+
+ DBusSignalHandlerToken addSignalMemberHandler(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName,
+ const std::string& interfaceMemberSignature,
+ DBusSignalHandler* dbusSignalHandler);
+
+ void registerObjectPath(const std::string& objectPath);
+ void unregisterObjectPath(const std::string& objectPath);
+
+ void removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken);
+
+ bool readWriteDispatch(int timeoutMilliseconds = -1);
+
+ virtual const std::shared_ptr<DBusDaemonProxy>& getDBusDaemonProxy();
+ virtual const std::shared_ptr<DBusServiceRegistry>& getDBusServiceRegistry();
+ virtual const std::shared_ptr<DBusObjectManager>& getDBusObjectManager();
+
+ private:
+ void dispatch();
+
+ std::thread dispatchThread_;
+ bool stopDispatching_;
+
+ DBusConnection(BusType busType);
+
+ void addLibdbusSignalMatchRule(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName);
+
+ void removeLibdbusSignalMatchRule(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName);
+
+ void initLibdbusObjectPathHandlerAfterConnect();
+
+ void initLibdbusSignalFilterAfterConnect();
+
+ ::DBusHandlerResult onLibdbusObjectPathMessage(::DBusMessage* libdbusMessage) const;
+
+ ::DBusHandlerResult onLibdbusSignalFilter(::DBusMessage* libdbusMessage);
+
+ static void onLibdbusPendingCallNotifyThunk(::DBusPendingCall* libdbusPendingCall, void *userData);
+ static void onLibdbusDataCleanup(void* userData);
+
+ static ::DBusHandlerResult onLibdbusObjectPathMessageThunk(::DBusConnection* libdbusConnection,
+ ::DBusMessage* libdbusMessage,
+ void* userData);
+
+ static ::DBusHandlerResult onLibdbusSignalFilterThunk(::DBusConnection* libdbusConnection,
+ ::DBusMessage* libdbusMessage,
+ void* userData);
+
+ BusType busType_;
+
+ ::DBusConnection* libdbusConnection_;
+
+ std::shared_ptr<DBusDaemonProxy> dbusDaemonProxy_;
+ std::shared_ptr<DBusServiceRegistry> dbusServiceRegistry_;
+ std::shared_ptr<DBusObjectManager> dbusObjectManager_;
+
+ DBusConnectionStatusEvent dbusConnectionStatusEvent_;
+
+ typedef std::tuple<std::string, std::string, std::string> DBusSignalMatchRuleTuple;
+ typedef std::pair<uint32_t, std::string> DBusSignalMatchRuleMapping;
+ typedef std::unordered_map<DBusSignalMatchRuleTuple, DBusSignalMatchRuleMapping> DBusSignalMatchRulesMap;
+ DBusSignalMatchRulesMap dbusSignalMatchRulesMap_;
+
+ bool isLibdbusSignalFilterAdded_;
+
+ DBusSignalHandlerTable dbusSignalHandlerTable_;
+
+ // referenceCount, objectPath
+ typedef std::unordered_map<std::string, uint32_t> LibdbusRegisteredObjectPathHandlersTable;
+ LibdbusRegisteredObjectPathHandlersTable libdbusRegisteredObjectPaths_;
+
+ static DBusObjectPathVTable libdbusObjectPathVTable_;
+};
+
+std::shared_ptr<DBusConnection> DBusConnection::getBus(const BusType& busType) {
+ return std::shared_ptr<DBusConnection>(new DBusConnection(busType));
+}
+
+std::shared_ptr<DBusConnection> DBusConnection::wrapLibDBus(::DBusConnection* libDbusConnection) {
+ return std::shared_ptr<DBusConnection>(new DBusConnection(libDbusConnection));
+}
+
+std::shared_ptr<DBusConnection> DBusConnection::getSessionBus() {
+ return getBus(BusType::SESSION);
+}
+
+std::shared_ptr<DBusConnection> DBusConnection::getSystemBus() {
+ return getBus(BusType::SYSTEM);
+}
+
+std::shared_ptr<DBusConnection> DBusConnection::getStarterBus() {
+ return getBus(BusType::STARTER);
+}
+
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_CONNECTION_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public\r
+ * License, v. 2.0. If a copy of the MPL was not distributed with this\r
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\r
+#include "DBusDaemonProxy.h"\r
+#include "DBusProxyHelper.h"\r
+#include <iostream>\r
+\r
+\r
+namespace CommonAPI {\r
+namespace DBus {\r
+\r
+DBusDaemonProxy::DBusDaemonProxy(const std::shared_ptr<DBusProxyConnection>& connection):\r
+ DBusProxy("org.freedesktop.DBus", "/org/freedesktop/DBus", getInterfaceName(), connection, true),\r
+ nameOwnerChangedEvent_(*this, "NameOwnerChanged", "sss") {\r
+}\r
+\r
+const char* DBusDaemonProxy::getInterfaceName() const {\r
+ return "org.freedesktop.DBus";\r
+}\r
+\r
+DBusDaemonProxy::NameOwnerChangedEvent& DBusDaemonProxy::getNameOwnerChangedEvent() {\r
+ return nameOwnerChangedEvent_;\r
+}\r
+\r
+void DBusDaemonProxy::listNames(CommonAPI::CallStatus& callStatus, std::vector<std::string>& busNames) const {\r
+ DBusMessage dbusMethodCall = createMethodCall("ListNames", "");\r
+\r
+ DBusError dbusError;\r
+ DBusMessage dbusMessageReply = getDBusConnection()->sendDBusMessageWithReplyAndBlock(\r
+ dbusMethodCall,\r
+ dbusError);\r
+\r
+ if (dbusError || !dbusMessageReply.isMethodReturnType()) {\r
+ callStatus = CallStatus::REMOTE_ERROR;\r
+ return;\r
+ }\r
+\r
+ DBusInputStream inputStream(dbusMessageReply);\r
+ const bool success = DBusSerializableArguments<std::vector<std::string>>::deserialize(inputStream, busNames);\r
+ if (!success) {\r
+ callStatus = CallStatus::REMOTE_ERROR;\r
+ return;\r
+ }\r
+ callStatus = CallStatus::SUCCESS;\r
+\r
+}\r
+\r
+std::future<CallStatus> DBusDaemonProxy::listNamesAsync(ListNamesAsyncCallback listNamesAsyncCallback) const {\r
+ DBusMessage dbusMessage = createMethodCall("ListNames", "");\r
+\r
+ return getDBusConnection()->sendDBusMessageWithReplyAsync(\r
+ dbusMessage,\r
+ DBusProxyAsyncCallbackHandler<std::vector<std::string>>::create(listNamesAsyncCallback));\r
+}\r
+\r
+void DBusDaemonProxy::nameHasOwner(const std::string& busName, CommonAPI::CallStatus& callStatus, bool& hasOwner) const {\r
+\r
+ DBusMessage dbusMethodCall = createMethodCall("NameHasOwner", "s");\r
+\r
+ DBusOutputStream outputStream(dbusMethodCall);\r
+ bool success = DBusSerializableArguments<std::string>::serialize(outputStream, busName);\r
+ if (!success) {\r
+ callStatus = CallStatus::OUT_OF_MEMORY;\r
+ return;\r
+ }\r
+ outputStream.flush();\r
+\r
+ DBusError dbusError;\r
+ DBusMessage dbusMessageReply = getDBusConnection()->sendDBusMessageWithReplyAndBlock(\r
+ dbusMethodCall,\r
+ dbusError);\r
+ if (dbusError || !dbusMessageReply.isMethodReturnType()) {\r
+ callStatus = CallStatus::REMOTE_ERROR;\r
+ return;\r
+ }\r
+\r
+ DBusInputStream inputStream(dbusMessageReply);\r
+ success = DBusSerializableArguments<bool>::deserialize(inputStream, hasOwner);\r
+ if (!success) {\r
+ callStatus = CallStatus::REMOTE_ERROR;\r
+ return;\r
+ }\r
+ callStatus = CallStatus::SUCCESS;\r
+\r
+}\r
+\r
+std::future<CallStatus> DBusDaemonProxy::nameHasOwnerAsync(const std::string& busName, NameHasOwnerAsyncCallback nameHasOwnerAsyncCallback) const {\r
+\r
+ DBusMessage dbusMessage = createMethodCall("NameHasOwner", "s");\r
+\r
+ DBusOutputStream outputStream(dbusMessage);\r
+ const bool success = DBusSerializableArguments<std::string>::serialize(outputStream, busName);\r
+ if (!success) {\r
+ std::promise<CallStatus> promise;\r
+ promise.set_value(CallStatus::OUT_OF_MEMORY);\r
+ return promise.get_future();\r
+ }\r
+ outputStream.flush();\r
+\r
+ return getDBusConnection()->sendDBusMessageWithReplyAsync(\r
+ dbusMessage,\r
+ DBusProxyAsyncCallbackHandler<bool>::create(nameHasOwnerAsyncCallback));\r
+\r
+}\r
+\r
+void DBusDaemonProxy::getOwnVersion(uint16_t& ownVersionMajor, uint16_t& ownVersionMinor) const {\r
+}\r
+\r
+} // namespace DBus\r
+} // namespace CommonAPI\r
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public\r
+ * License, v. 2.0. If a copy of the MPL was not distributed with this\r
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\r
+#ifndef COMMONAPI_DBUS_DBUS_DAEMON_PROXY_H_\r
+#define COMMONAPI_DBUS_DBUS_DAEMON_PROXY_H_\r
+\r
+#include "DBusProxy.h"\r
+#include "DBusEvent.h"\r
+\r
+#include "DBusServiceStatusEvent.h"\r
+\r
+#include <string>\r
+#include <vector>\r
+\r
+namespace CommonAPI {\r
+namespace DBus {\r
+\r
+class DBusServiceStatusEvent;\r
+\r
+class DBusDaemonProxy: public DBusProxy {\r
+\r
+ public:\r
+ typedef Event<std::string, std::string, std::string> NameOwnerChangedEvent;\r
+ typedef std::function<void(const CommonAPI::CallStatus&, std::vector<std::string>)> ListNamesAsyncCallback;\r
+ typedef std::function<void(const CommonAPI::CallStatus&, bool)> NameHasOwnerAsyncCallback;\r
+\r
+\r
+ DBusDaemonProxy(const std::shared_ptr<DBusProxyConnection>& connection);\r
+\r
+ const char* getInterfaceName() const;\r
+\r
+ NameOwnerChangedEvent& getNameOwnerChangedEvent();\r
+\r
+ void listNames(CommonAPI::CallStatus& callStatus, std::vector<std::string>& busNames) const;\r
+ std::future<CallStatus> listNamesAsync(ListNamesAsyncCallback listNamesAsyncCallback) const;\r
+\r
+ void nameHasOwner(const std::string& busName, CommonAPI::CallStatus& callStatus, bool& hasOwner) const;\r
+ std::future<CallStatus> nameHasOwnerAsync(const std::string& busName, NameHasOwnerAsyncCallback nameHasOwnerAsyncCallback) const;\r
+\r
+ protected:\r
+ void getOwnVersion(uint16_t& ownVersionMajor, uint16_t& ownVersionMinor) const;\r
+\r
+ private:\r
+ DBusEvent<NameOwnerChangedEvent> nameOwnerChangedEvent_;\r
+\r
+};\r
+\r
+} // namespace DBus\r
+} // namespace CommonAPI\r
+\r
+#endif // COMMONAPI_DBUS_DBUS_DAEMON_PROXY_H_\r
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "DBusError.h"
+
+#include <cassert>
+#include <cstring>
+
+namespace CommonAPI {
+namespace DBus {
+
+
+DBusError::DBusError() {
+ dbus_error_init(&libdbusError_);
+}
+
+DBusError::~DBusError() {
+ dbus_error_free(&libdbusError_);
+}
+
+DBusError::operator bool() const {
+ return dbus_error_is_set(&libdbusError_);
+}
+
+void DBusError::clear() {
+ dbus_error_free(&libdbusError_);
+}
+
+std::string DBusError::getName() const {
+ assert(*this);
+
+ return std::string(libdbusError_.name);
+}
+
+std::string DBusError::getMessage() const {
+ assert(*this);
+
+ return std::string(libdbusError_.message);
+}
+
+} // namespace DBus
+} // namespace CommonAPI
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_DBUS_DBUS_ERROR_H_
+#define COMMONAPI_DBUS_DBUS_ERROR_H_
+
+#include <string>
+#include <dbus/dbus.h>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusConnection;
+
+
+class DBusError {
+ public:
+ DBusError();
+ ~DBusError();
+
+ operator bool() const;
+
+ void clear();
+
+ std::string getName() const;
+ std::string getMessage() const;
+
+ private:
+ ::DBusError libdbusError_;
+
+ friend class DBusConnection;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_ERROR_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_DBUS_DBUS_EVENT_H_
+#define COMMONAPI_DBUS_DBUS_EVENT_H_
+
+#include "DBusProxyConnection.h"
+#include "DBusMessage.h"
+#include "DBusSerializableArguments.h"
+
+#include <CommonAPI/Event.h>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusProxy;
+
+
+template <typename _EventType, typename _DBusProxy = DBusProxy>
+class DBusEvent: public _EventType, public DBusProxyConnection::DBusSignalHandler {
+ public:
+ typedef typename _EventType::ArgumentsTuple ArgumentsTuple;
+ typedef typename _EventType::CancellableListener CancellableListener;
+
+ DBusEvent(_DBusProxy& dbusProxy, const char* eventName, const char* eventSignature):
+ dbusProxy_(dbusProxy),
+ eventName_(eventName),
+ eventSignature_(eventSignature) {
+ assert(eventName);
+ assert(eventSignature);
+ }
+
+ virtual ~DBusEvent() {
+ if (this->hasListeners())
+ dbusProxy_.removeSignalMemberHandler(subscription_);
+ }
+
+ virtual SubscriptionStatus onSignalDBusMessage(const DBusMessage& dbusMessage) {
+ return unpackArgumentsAndHandleSignalDBusMessage(dbusMessage, ArgumentsTuple());
+ }
+
+ protected:
+ virtual void onFirstListenerAdded(const CancellableListener&) {
+ subscription_ = dbusProxy_.addSignalMemberHandler(eventName_, eventSignature_, this);
+ }
+
+ virtual void onLastListenerRemoved(const CancellableListener&) {
+ dbusProxy_.removeSignalMemberHandler(subscription_);
+ }
+
+ private:
+ template <typename ... _Arguments>
+ inline SubscriptionStatus unpackArgumentsAndHandleSignalDBusMessage(const DBusMessage& dbusMessage, std::tuple<_Arguments...> argTuple) {
+ return handleSignalDBusMessage(dbusMessage, std::move(argTuple), typename make_sequence<sizeof...(_Arguments)>::type());
+ }
+
+ template <typename ... _Arguments, int... _ArgIndices>
+ inline SubscriptionStatus handleSignalDBusMessage(const DBusMessage& dbusMessage, std::tuple<_Arguments...> argTuple, index_sequence<_ArgIndices...>) {
+ DBusInputStream dbusInputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_Arguments...>::deserialize(dbusInputStream, std::get<_ArgIndices>(argTuple)...);
+ // Continue subscription if deserialization failed
+ return success ? this->notifyListeners(std::get<_ArgIndices>(argTuple)...) : SubscriptionStatus::RETAIN;
+ }
+
+ _DBusProxy& dbusProxy_;
+ const char* eventName_;
+ const char* eventSignature_;
+ DBusProxyConnection::DBusSignalHandlerToken subscription_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_EVENT_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public\r
+ * License, v. 2.0. If a copy of the MPL was not distributed with this\r
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\r
+#include "DBusProxy.h"\r
+#include "DBusConnection.h"\r
+#include "DBusFactory.h"\r
+#include "DBusServiceRegistry.h"\r
+#include "DBusUtils.h"\r
+\r
+#include <algorithm>\r
+#include <cassert>\r
+#include <iostream>\r
+#include <sstream>\r
+#include <unordered_map>\r
+#include <vector>\r
+\r
+namespace CommonAPI {\r
+namespace DBus {\r
+\r
+std::unordered_map<std::string, DBusProxyFactoryFunction>* registeredProxyFactoryFunctions_;\r
+std::unordered_map<std::string, DBusAdapterFactoryFunction>* registeredAdapterFactoryFunctions_;\r
+\r
+\r
+void DBusFactory::registerProxyFactoryMethod(std::string interfaceName, DBusProxyFactoryFunction proxyFactoryMethod) {\r
+ if(!registeredProxyFactoryFunctions_) {\r
+ registeredProxyFactoryFunctions_ = new std::unordered_map<std::string, DBusProxyFactoryFunction>();\r
+ }\r
+ registeredProxyFactoryFunctions_->insert({interfaceName, proxyFactoryMethod});\r
+}\r
+\r
+void DBusFactory::registerAdapterFactoryMethod(std::string interfaceName, DBusAdapterFactoryFunction adapterFactoryMethod) {\r
+ if(!registeredAdapterFactoryFunctions_) {\r
+ registeredAdapterFactoryFunctions_ = new std::unordered_map<std::string, DBusAdapterFactoryFunction>();\r
+ }\r
+ registeredAdapterFactoryFunctions_->insert({interfaceName, adapterFactoryMethod});\r
+}\r
+\r
+\r
+\r
+DBusFactory::DBusFactory(std::shared_ptr<Runtime> runtime, const MiddlewareInfo* middlewareInfo) :\r
+ CommonAPI::Factory(runtime, middlewareInfo),\r
+ dbusConnection_(CommonAPI::DBus::DBusConnection::getSessionBus()),\r
+ acquiredConnectionName_("") {\r
+ dbusConnection_->connect();\r
+}\r
+\r
+DBusFactory::~DBusFactory() {\r
+}\r
+\r
+\r
+std::vector<std::string> DBusFactory::getAvailableServiceInstances(const std::string& serviceInterfaceName,\r
+ const std::string& serviceDomainName) {\r
+ return dbusConnection_->getDBusServiceRegistry()->getAvailableServiceInstances(serviceInterfaceName, serviceDomainName);\r
+}\r
+\r
+\r
+bool DBusFactory::isServiceInstanceAlive(const std::string& serviceInstanceId,\r
+ const std::string& serviceInterfaceName,\r
+ const std::string& serviceDomainName) {\r
+\r
+ return dbusConnection_->getDBusServiceRegistry()->isServiceInstanceAlive(serviceInstanceId, serviceInterfaceName, serviceDomainName);\r
+}\r
+\r
+std::shared_ptr<Proxy> DBusFactory::createProxy(const char* interfaceName, const std::string& participantId, const std::string& domain) {\r
+ std::string connectionName;\r
+ std::string objectPath;\r
+\r
+ findFallbackInstanceIdMapping(participantId, connectionName, objectPath);\r
+\r
+ if(!registeredProxyFactoryFunctions_) {\r
+ registeredProxyFactoryFunctions_ = new std::unordered_map<std::string, DBusProxyFactoryFunction> {};\r
+ }\r
+\r
+ for (auto it = registeredProxyFactoryFunctions_->begin(); it != registeredProxyFactoryFunctions_->end(); ++it) {\r
+ if(it->first == interfaceName) {\r
+ return (it->second)(connectionName.c_str(), objectPath.c_str(), dbusConnection_);\r
+ }\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+std::shared_ptr<StubAdapter> DBusFactory::createAdapter(std::shared_ptr<StubBase> stubBase, const char* interfaceName, const std::string& participantId, const std::string& domain) {\r
+ assert(dbusConnection_->isConnected());\r
+\r
+ std::string connectionName;\r
+ std::string objectPath;\r
+ findFallbackInstanceIdMapping(participantId, connectionName, objectPath);\r
+\r
+ if(acquiredConnectionName_ == "") {\r
+ dbusConnection_->requestServiceNameAndBlock(connectionName);\r
+ acquiredConnectionName_ = connectionName;\r
+ } else if (acquiredConnectionName_ != connectionName) {\r
+ return NULL;\r
+ }\r
+\r
+ if(!registeredAdapterFactoryFunctions_) {\r
+ registeredAdapterFactoryFunctions_ = new std::unordered_map<std::string, DBusAdapterFactoryFunction> {};\r
+ }\r
+\r
+ for (auto it = registeredAdapterFactoryFunctions_->begin(); it != registeredAdapterFactoryFunctions_->end(); ++it) {\r
+ if(it->first == interfaceName) {\r
+ std::shared_ptr<DBusStubAdapter> dbusStubAdapter = (it->second)(connectionName.c_str(), objectPath.c_str(), dbusConnection_, stubBase);\r
+ dbusStubAdapter->init();\r
+ return dbusStubAdapter;\r
+ }\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+\r
+} // namespace DBus\r
+} // namespace CommonAPI\r
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public\r
+ * License, v. 2.0. If a copy of the MPL was not distributed with this\r
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\r
+#ifndef COMMONAPI_DBUS_DBUS_FACTORY_H_\r
+#define COMMONAPI_DBUS_DBUS_FACTORY_H_\r
+\r
+#include <thread>\r
+\r
+#include <CommonAPI/Factory.h>\r
+\r
+#include "CommonAPI/DBus/DBusStubAdapter.h"\r
+#include "DBusConnection.h"\r
+\r
+namespace CommonAPI {\r
+namespace DBus {\r
+\r
+typedef std::shared_ptr<DBusProxy> (*DBusProxyFactoryFunction) (const char* busName, const char* objectPath, std::shared_ptr<DBusProxyConnection> dbusProxyConnection);\r
+typedef std::shared_ptr<DBusStubAdapter> (*DBusAdapterFactoryFunction) (std::string busName, std::string objectPath, std::shared_ptr<DBusProxyConnection> dbusProxyConnection, std::shared_ptr<StubBase> stubBase);\r
+\r
+class DBusFactory: public Factory {\r
+ public:\r
+ DBusFactory(std::shared_ptr<Runtime> runtime, const MiddlewareInfo* middlewareInfo);\r
+ virtual ~DBusFactory();\r
+\r
+ static void registerProxyFactoryMethod(std::string interfaceName, DBusProxyFactoryFunction proxyFactoryFunction);\r
+ static void registerAdapterFactoryMethod(std::string interfaceName, DBusAdapterFactoryFunction adapterFactoryMethod);\r
+\r
+ virtual std::vector<std::string> getAvailableServiceInstances(const std::string& serviceInterfaceName, const std::string& serviceDomainName = "local");\r
+\r
+ virtual bool isServiceInstanceAlive(const std::string& serviceInstanceID, const std::string& serviceInterfaceName, const std::string& serviceDomainName = "local");\r
+\r
+ virtual std::shared_ptr<Proxy> createProxy(const char* interfaceName, const std::string& participantId, const std::string& domain);\r
+\r
+ virtual std::shared_ptr<StubAdapter> createAdapter(std::shared_ptr<StubBase> stubBase, const char* interfaceName, const std::string& participantId, const std::string& domain);\r
+\r
+ private:\r
+ std::shared_ptr<CommonAPI::DBus::DBusConnection> dbusConnection_;\r
+ std::string acquiredConnectionName_;\r
+};\r
+\r
+} // namespace DBus\r
+} // namespace CommonAPI\r
+\r
+#endif // COMMONAPI_DBUS_DBUS_FACTORY_H_\r
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "DBusFunctionalHash.h"
+
+#include <murmurhash/MurmurHash3.h>
+
+#include <cassert>
+#include <cstring>
+
+
+/*
+ * @see http://code.google.com/p/smhasher/
+ */
+#define SMHASHER_SEED_VALUE 0xc70f6907UL
+
+
+namespace std {
+
+size_t hash< pair<const char*, const char*> >::operator()(const pair<const char*, const char*>& t) const {
+ const char* a = t.first;
+ const char* b = t.second;
+
+ assert(a);
+ assert(b);
+
+ uint32_t seed = static_cast<uint32_t>(SMHASHER_SEED_VALUE);
+ MurmurHash3_x86_32(a, strlen(a), seed, &seed);
+ MurmurHash3_x86_32(b, strlen(b), seed, &seed);
+
+ return static_cast<size_t>(seed);
+}
+
+
+size_t hash< pair<string, string> >::operator()(const pair<string, string>& t) const {
+ const string& a = t.first;
+ const string& b = t.second;
+
+ uint32_t seed = static_cast<uint32_t>(SMHASHER_SEED_VALUE);
+ MurmurHash3_x86_32(a.c_str(), a.length(), seed, &seed);
+ MurmurHash3_x86_32(b.c_str(), b.length(), seed, &seed);
+
+ return static_cast<size_t>(seed);
+}
+
+
+size_t hash< tuple<string, string, string> >::operator()(const tuple<string, string, string>& t) const {
+ const string& a = get<0>(t);
+ const string& b = get<1>(t);
+ const string& c = get<2>(t);
+
+ uint32_t seed = static_cast<uint32_t>(SMHASHER_SEED_VALUE);
+ MurmurHash3_x86_32(a.c_str(), a.length(), seed, &seed);
+ MurmurHash3_x86_32(b.c_str(), b.length(), seed, &seed);
+ MurmurHash3_x86_32(c.c_str(), c.length(), seed, &seed);
+
+ return static_cast<size_t>(seed);
+}
+
+
+size_t hash< tuple<string, string, string, string> >::operator()(const tuple<string, string, string, string>& t) const {
+ const string& a = get<0>(t);
+ const string& b = get<1>(t);
+ const string& c = get<2>(t);
+ const string& d = get<3>(t);
+
+ uint32_t seed = static_cast<uint32_t>(SMHASHER_SEED_VALUE);
+ MurmurHash3_x86_32(a.c_str(), a.length(), seed, &seed);
+ MurmurHash3_x86_32(b.c_str(), b.length(), seed, &seed);
+ MurmurHash3_x86_32(c.c_str(), c.length(), seed, &seed);
+ MurmurHash3_x86_32(d.c_str(), d.length(), seed, &seed);
+
+ return static_cast<size_t>(seed);
+}
+
+
+bool equal_to< pair<const char*, const char*> >::operator()(const pair<const char*, const char*>& a,
+ const pair<const char*, const char*>& b) const {
+ if (a.first == b.first && a.second == b.second)
+ return true;
+
+ return !strcmp(a.first, b.first) && !strcmp(a.second, b.second);
+}
+
+} // namespace std
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_DBUS_DBUS_FUNCTIONAL_HASH_H_
+#define COMMONAPI_DBUS_DBUS_FUNCTIONAL_HASH_H_
+
+#include <functional>
+#include <string>
+#include <tuple>
+
+namespace std {
+
+template<>
+struct hash< pair<const char*, const char*> >:
+ public unary_function< pair<const char*, const char*>, size_t > {
+
+ size_t operator()(const pair<const char*, const char*>& t) const;
+};
+
+
+template<>
+struct hash< pair<string, string> >:
+ public unary_function< pair<string, string>, size_t > {
+
+ size_t operator()(const pair<string, string>& t) const;
+};
+
+
+template<>
+struct hash< tuple<string, string, string> >:
+ public unary_function< tuple<string, string, string>, size_t > {
+
+ size_t operator()(const tuple<string, string, string>& t) const;
+};
+
+
+template<>
+struct hash< tuple<string, string, string, string> >:
+ public std::unary_function< tuple<string, string, string, string>, size_t > {
+
+ size_t operator()(const tuple<string, string, string, string>& t) const;
+};
+
+
+template<>
+struct equal_to< pair<const char*, const char*> >: public binary_function< pair<const char*, const char*>,
+ pair<const char*, const char*>,
+ bool> {
+
+ bool operator()(const pair<const char*, const char*>& a, const pair<const char*, const char*>& b) const;
+};
+
+} // namespace std
+
+#endif // COMMONAPI_DBUS_DBUS_FUNCTIONAL_HASH_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_DBUS_DBUS_HELPER_H_
+#define COMMONAPI_DBUS_DBUS_HELPER_H_
+
+namespace CommonAPI {
+namespace DBus {
+
+template <int ...>
+struct index_sequence {};
+
+
+template <int N, int ...S>
+struct make_sequence : make_sequence<N-1, N-1, S...> {};
+
+template <int ...S>
+struct make_sequence<0, S...> {
+ typedef index_sequence<S...> type;
+};
+
+
+template <int N, int _Offset, int ...S>
+struct make_sequence_range : make_sequence_range<N-1, _Offset, N-1+_Offset, S...> {};
+
+template <int _Offset, int ...S>
+struct make_sequence_range<0, _Offset, S...> {
+ typedef index_sequence<S...> type;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_HELPER_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "DBusInputStream.h"
+
+namespace CommonAPI {
+namespace DBus {
+
+DBusInputStream::DBusInputStream(const CommonAPI::DBus::DBusMessage& message) :
+ message_(message),
+ dataBegin_(message.getBodyData()),
+ currentDataPosition_(0),
+ dataLength_(message.getBodyLength()),
+ exception_(nullptr) {
+}
+
+DBusInputStream::~DBusInputStream() {
+}
+
+const CommonAPI::DBus::DBusError& DBusInputStream::getError() const {
+ return *exception_;
+}
+
+bool DBusInputStream::isErrorSet() const {
+ return exception_ != nullptr;
+}
+
+void DBusInputStream::clearError() {
+ exception_ = nullptr;
+}
+
+void DBusInputStream::alignToBoundary(const size_t alignBoundary) {
+ const unsigned int alignMask = alignBoundary - 1;
+ currentDataPosition_ = (currentDataPosition_ + alignMask) & (~alignMask);
+}
+
+char* DBusInputStream::readRawData(const size_t numBytesToRead) {
+ assert((currentDataPosition_ + numBytesToRead) <= dataLength_);
+
+ char* dataPtr = (char*) (dataBegin_ + currentDataPosition_);
+ currentDataPosition_ += numBytesToRead;
+ return dataPtr;
+}
+
+template <>
+DBusInputStream& DBusInputStream::readBasicTypeValue<float>(float& val) {
+ if (sizeof(val) > 1)
+ alignToBoundary(sizeof(double));
+
+ val = (float)(*(reinterpret_cast<double*>(readRawData(sizeof(double)))));
+ return *this;
+}
+
+InputStream& DBusInputStream::readValue(bool& boolValue) {
+ alignToBoundary(4);
+ return readBasicTypeValue(boolValue);
+}
+
+InputStream& DBusInputStream::readValue(int8_t& int8Value) { return readBasicTypeValue(int8Value); }
+InputStream& DBusInputStream::readValue(int16_t& int16Value) { return readBasicTypeValue(int16Value); }
+InputStream& DBusInputStream::readValue(int32_t& int32Value) { return readBasicTypeValue(int32Value); }
+InputStream& DBusInputStream::readValue(int64_t& int64Value) { return readBasicTypeValue(int64Value); }
+
+InputStream& DBusInputStream::readValue(uint8_t& uint8Value) { return readBasicTypeValue(uint8Value); }
+InputStream& DBusInputStream::readValue(uint16_t& uint16Value) { return readBasicTypeValue(uint16Value); }
+InputStream& DBusInputStream::readValue(uint32_t& uint32Value) { return readBasicTypeValue(uint32Value); }
+InputStream& DBusInputStream::readValue(uint64_t& uint64Value) { return readBasicTypeValue(uint64Value); }
+
+InputStream& DBusInputStream::readValue(float& floatValue) { return readBasicTypeValue(floatValue); }
+InputStream& DBusInputStream::readValue(double& doubleValue) { return readBasicTypeValue(doubleValue); }
+
+InputStream& DBusInputStream::readValue(std::string& stringValue) {
+ uint32_t lengthOfString;
+ readValue(lengthOfString);
+
+ // length field does not include terminating 0-byte, therefore length of data to read is +1
+ char* dataPtr = readRawData(lengthOfString + 1);
+
+ // The string contained in a DBus-message is required to be 0-terminated, therefore the following line works
+ stringValue = dataPtr;
+
+ return *this;
+}
+
+InputStream& DBusInputStream::readValue(ByteBuffer& byteBufferValue) {
+ *this >> byteBufferValue;
+ return *this;
+}
+
+InputStream& DBusInputStream::readEnumValue(int8_t& int8BackingTypeValue) { return readValue(int8BackingTypeValue); }
+InputStream& DBusInputStream::readEnumValue(int16_t& int16BackingTypeValue) { return readValue(int16BackingTypeValue); }
+InputStream& DBusInputStream::readEnumValue(int32_t& int32BackingTypeValue) { return readValue(int32BackingTypeValue); }
+InputStream& DBusInputStream::readEnumValue(int64_t& int64BackingTypeValue) { return readValue(int64BackingTypeValue); }
+InputStream& DBusInputStream::readEnumValue(uint8_t& uint8BackingTypeValue) { return readValue(uint8BackingTypeValue); }
+InputStream& DBusInputStream::readEnumValue(uint16_t& uint16BackingTypeValue) { return readValue(uint16BackingTypeValue); }
+InputStream& DBusInputStream::readEnumValue(uint32_t& uint32BackingTypeValue) { return readValue(uint32BackingTypeValue); }
+InputStream& DBusInputStream::readEnumValue(uint64_t& uint64BackingTypeValue) { return readValue(uint64BackingTypeValue); }
+
+InputStream& DBusInputStream::readVersionValue(Version& versionValue) {
+ alignToBoundary(8);
+ readValue(versionValue.Major);
+ readValue(versionValue.Minor);
+ return *this;
+}
+
+void DBusInputStream::beginReadSerializableStruct(const SerializableStruct& serializableStruct) {
+ alignToBoundary(8);
+}
+
+void DBusInputStream::endReadSerializableStruct(const SerializableStruct& serializableStruct) { }
+
+
+void DBusInputStream::beginReadBoolVector() {
+ beginReadGenericVector();
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+void DBusInputStream::beginReadInt8Vector() {
+ beginReadGenericVector();
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+void DBusInputStream::beginReadInt16Vector() {
+ beginReadGenericVector();
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+void DBusInputStream::beginReadInt32Vector() {
+ beginReadGenericVector();
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+void DBusInputStream::beginReadInt64Vector() {
+ beginReadGenericVector();
+ alignToBoundary(8);
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+void DBusInputStream::beginReadUInt8Vector() {
+ beginReadGenericVector();
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+void DBusInputStream::beginReadUInt16Vector() {
+ beginReadGenericVector();
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+void DBusInputStream::beginReadUInt32Vector() {
+ beginReadGenericVector();
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+void DBusInputStream::beginReadUInt64Vector() {
+ beginReadGenericVector();
+ alignToBoundary(8);
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+void DBusInputStream::beginReadFloatVector() {
+ beginReadGenericVector();
+ alignToBoundary(8);
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+void DBusInputStream::beginReadDoubleVector() {
+ beginReadGenericVector();
+ alignToBoundary(8);
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+void DBusInputStream::beginReadStringVector() {
+ beginReadGenericVector();
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+void DBusInputStream::beginReadByteBufferVector() {
+ beginReadGenericVector();
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+void DBusInputStream::beginReadVersionVector() {
+ beginReadGenericVector();
+ alignToBoundary(8);
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+void DBusInputStream::beginReadVectorOfSerializableStructs() {
+ beginReadGenericVector();
+ alignToBoundary(8);
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+void DBusInputStream::beginReadVectorOfVectors() {
+ beginReadGenericVector();
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+void DBusInputStream::beginReadVectorOfMaps() {
+ beginReadGenericVector();
+ alignToBoundary(8);
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+bool DBusInputStream::hasMoreVectorElements() {
+ return bytesToRead_.top() > currentDataPosition_ - savedStreamPositions_.top();
+}
+
+void DBusInputStream::endReadVector() {
+ bytesToRead_.pop();
+ savedStreamPositions_.pop();
+}
+
+void DBusInputStream::beginReadMap() {
+ uint32_t vectorByteSize;
+ readBasicTypeValue(vectorByteSize);
+ bytesToRead_.push(vectorByteSize);
+ alignToBoundary(8);
+ savedStreamPositions_.push(currentDataPosition_);
+}
+
+bool DBusInputStream::hasMoreMapElements() {
+ return bytesToRead_.top() > currentDataPosition_ - savedStreamPositions_.top();
+}
+
+void DBusInputStream::endReadMap() {
+ bytesToRead_.pop();
+ savedStreamPositions_.pop();
+}
+
+
+} // namespace DBus
+} // namespace CommonAPI
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_DBUS_DBUS_INPUT_STREAM_H_
+#define COMMONAPI_DBUS_DBUS_INPUT_STREAM_H_
+
+#include "DBusError.h"
+#include "DBusMessage.h"
+
+#include <CommonAPI/InputStream.h>
+
+#include <stdint.h>
+#include <cassert>
+#include <string>
+#include <vector>
+#include <stack>
+
+namespace CommonAPI {
+namespace DBus {
+
+/**
+ * Used to mark the position of a pointer within an array of bytes.
+ */
+typedef uint32_t position_t;
+
+/**
+ * @class DBusInputMessageStream
+ *
+ * Used to deserialize and read data from a #DBusMessage. For all data types that can be read from a #DBusMessage, a ">>"-operator should be defined to handle the reading
+ * (this operator is predefined for all basic data types and for vectors).
+ */
+class DBusInputStream: public InputStream {
+ public:
+ virtual bool hasError() const { return isErrorSet(); }
+
+ virtual InputStream& readValue(bool& boolValue);
+
+ virtual InputStream& readValue(int8_t& int8Value);
+ virtual InputStream& readValue(int16_t& int16Value);
+ virtual InputStream& readValue(int32_t& int32Value);
+ virtual InputStream& readValue(int64_t& int64Value);
+
+ virtual InputStream& readValue(uint8_t& uint8Value);
+ virtual InputStream& readValue(uint16_t& uint16Value);
+ virtual InputStream& readValue(uint32_t& uint32Value);
+ virtual InputStream& readValue(uint64_t& uint64Value);
+
+ virtual InputStream& readValue(float& floatValue);
+ virtual InputStream& readValue(double& doubleValue);
+
+ virtual InputStream& readValue(std::string& stringValue);
+ virtual InputStream& readValue(ByteBuffer& byteBufferValue);
+
+ virtual InputStream& readEnumValue(int8_t& int8BackingTypeValue);
+ virtual InputStream& readEnumValue(int16_t& int16BackingTypeValue);
+ virtual InputStream& readEnumValue(int32_t& int32BackingTypeValue);
+ virtual InputStream& readEnumValue(int64_t& int64BackingTypeValue);
+ virtual InputStream& readEnumValue(uint8_t& uint8BackingTypeValue);
+ virtual InputStream& readEnumValue(uint16_t& uint16BackingTypeValue);
+ virtual InputStream& readEnumValue(uint32_t& uint32BackingTypeValue);
+ virtual InputStream& readEnumValue(uint64_t& uint64BackingTypeValue);
+
+ virtual InputStream& readVersionValue(Version& versionValue);
+
+ virtual void beginReadSerializableStruct(const SerializableStruct& serializableStruct);
+ virtual void endReadSerializableStruct(const SerializableStruct& serializableStruct);
+
+ virtual void beginReadBoolVector();
+ virtual void beginReadInt8Vector();
+ virtual void beginReadInt16Vector();
+ virtual void beginReadInt32Vector();
+ virtual void beginReadInt64Vector();
+ virtual void beginReadUInt8Vector();
+ virtual void beginReadUInt16Vector();
+ virtual void beginReadUInt32Vector();
+ virtual void beginReadUInt64Vector();
+ virtual void beginReadFloatVector();
+ virtual void beginReadDoubleVector();
+ virtual void beginReadStringVector();
+ virtual void beginReadByteBufferVector();
+ virtual void beginReadVersionVector();
+ virtual void beginReadVectorOfSerializableStructs();
+ virtual void beginReadVectorOfVectors();
+ virtual void beginReadVectorOfMaps();
+
+ virtual bool hasMoreVectorElements();
+ virtual void endReadVector();
+
+ virtual void beginReadMap();
+ virtual bool hasMoreMapElements();
+ virtual void endReadMap();
+
+
+ /**
+ * Creates a #DBusInputMessageStream which can be used to deserialize and read data from the given #DBusMessage.
+ * As no message-signature is checked, the user is responsible to ensure that the correct data types are read in the correct order.
+ *
+ * @param message the #DBusMessage from which data should be read.
+ */
+ DBusInputStream(const CommonAPI::DBus::DBusMessage& message);
+ DBusInputStream(const DBusInputStream& imessagestream) = delete;
+
+ /**
+ * Destructor; does not call the destructor of the referred #DBusMessage. Make sure to maintain a reference to the
+ * #DBusMessage outside of the stream if you intend to make further use of the message.
+ */
+ ~DBusInputStream();
+
+ /**
+ * Marks the stream as erroneous.
+ */
+ void setError();
+
+ /**
+ * @return An instance of #DBusError if this stream is in an erroneous state, NULL otherwise
+ */
+ const CommonAPI::DBus::DBusError& getError() const;
+
+ /**
+ * @return true if this stream is in an erroneous state, false otherwise.
+ */
+ bool isErrorSet() const;
+
+ /**
+ * Marks the state of the stream as cleared from all errors. Further reading is possible afterwards.
+ * The stream will have maintained the last valid position from before its state became erroneous.
+ */
+ void clearError();
+
+ /**
+ * Aligns the stream to the given byte boundary, i.e. the stream skips as many bytes as are necessary to execute the next read
+ * starting from the given boundary.
+ *
+ * @param alignBoundary the byte boundary to which the stream needs to be aligned.
+ */
+ void alignToBoundary(const size_t alignBoundary);
+
+ /**
+ * Reads the given number of bytes and returns them as an array of characters.
+ *
+ * Actually, for performance reasons this command only returns a pointer to the current position in the stream,
+ * and then increases the position of this pointer by the number of bytes indicated by the given parameter.
+ * It is the user's responsibility to actually use only the number of bytes he indicated he would use.
+ * It is assumed the user knows what kind of value is stored next in the #DBusMessage the data is streamed from.
+ * Using a reinterpret_cast on the returned pointer should then restore the original value.
+ *
+ * Example use case:
+ * @code
+ * ...
+ * inputMessageStream.alignForBasicType(sizeof(int32_t));
+ * char* const dataPtr = inputMessageStream.read(sizeof(int32_t));
+ * int32_t val = *(reinterpret_cast<int32_t*>(dataPtr));
+ * ...
+ * @endcode
+ */
+ char* readRawData(const size_t numBytesToRead);
+
+ /**
+ * Handles all reading of basic types from a given #DBusInputMessageStream.
+ * Basic types in this context are: uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double.
+ * Any types not listed here (especially all complex types, e.g. structs, unions etc.) need to provide a
+ * specialized implementation of this operator.
+ *
+ * @tparam _BasicType The type of the value that is to be read from the given stream.
+ * @param val The variable in which the retrieved value is to be stored
+ * @param inputMessageStream The stream which the value is to be read from
+ * @return The given inputMessageStream to allow for successive reading
+ */
+ template <typename _BasicType>
+ DBusInputStream& readBasicTypeValue(_BasicType& val) {
+ if (sizeof(val) > 1)
+ alignToBoundary(sizeof(_BasicType));
+
+ val = *(reinterpret_cast<_BasicType*>(readRawData(sizeof(_BasicType))));
+ return *this;
+ }
+
+ /**
+ * Returns the position of the reading pointer, relative to the beginning of the data stream.
+ */
+ position_t getCurrentPosition() const;
+
+ private:
+ inline void beginReadGenericVector() {
+ uint32_t vectorByteSize;
+ readBasicTypeValue(vectorByteSize);
+ bytesToRead_.push(vectorByteSize);
+ }
+
+ char* dataBegin_;
+ position_t currentDataPosition_;
+ size_t dataLength_;
+ CommonAPI::DBus::DBusError* exception_;
+ CommonAPI::DBus::DBusMessage message_;
+
+ std::stack<uint32_t> bytesToRead_;
+ std::stack<position_t> savedStreamPositions_;
+};
+
+
+inline void DBusInputStream::setError() {
+ exception_ = new CommonAPI::DBus::DBusError();
+}
+
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_INPUT_STREAM_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "DBusMessage.h"
+
+#include <cassert>
+#include <cstring>
+
+namespace CommonAPI {
+namespace DBus {
+
+DBusMessage::DBusMessage():
+ libdbusMessage_(NULL) {
+}
+
+DBusMessage::DBusMessage(::DBusMessage* libdbusMessage) {
+ libdbusMessage_ = libdbusMessage != NULL ? dbus_message_ref(libdbusMessage) : NULL;
+}
+
+DBusMessage::DBusMessage(::DBusMessage* libdbusMessage, bool increaseReferenceCount) {
+ assert(libdbusMessage);
+
+ libdbusMessage_ = increaseReferenceCount ? dbus_message_ref(libdbusMessage) : libdbusMessage;
+}
+
+DBusMessage::DBusMessage(const DBusMessage& src) {
+ libdbusMessage_ = src.libdbusMessage_ != NULL ? dbus_message_ref(src.libdbusMessage_) : NULL;
+}
+
+DBusMessage::DBusMessage(DBusMessage&& rsrc) {
+ libdbusMessage_ = rsrc.libdbusMessage_;
+ rsrc.libdbusMessage_ = NULL;
+}
+
+DBusMessage::~DBusMessage() {
+ if (libdbusMessage_)
+ dbus_message_unref(libdbusMessage_);
+}
+
+DBusMessage& DBusMessage::operator=(const DBusMessage& src) {
+ if (this != &src) {
+ if (libdbusMessage_)
+ dbus_message_unref(libdbusMessage_);
+
+ libdbusMessage_ = src.libdbusMessage_ != NULL ? dbus_message_ref(src.libdbusMessage_) : NULL;
+ }
+
+ return *this;
+}
+
+DBusMessage& DBusMessage::operator=(DBusMessage&& rsrc) {
+ if (this != &rsrc) {
+ if (libdbusMessage_)
+ dbus_message_unref(libdbusMessage_);
+
+ libdbusMessage_ = rsrc.libdbusMessage_;
+ rsrc.libdbusMessage_ = NULL;
+ }
+
+ return *this;
+}
+
+DBusMessage::operator bool() const {
+ const bool isNotNullDBusMessage = (libdbusMessage_ != NULL);
+ return isNotNullDBusMessage;
+}
+
+DBusMessage DBusMessage::createOrgFreedesktopOrgMethodCall(const char* methodName, const char* signature) {
+ return DBusMessage::createMethodCall("org.freedesktop.DBus",
+ "/",
+ "org.freedesktop.DBus",
+ methodName,
+ signature);
+}
+
+DBusMessage DBusMessage::createOrgFreedesktopOrgMethodCall(const std::string& methodName,
+ const std::string& signature) {
+ assert(!methodName.empty());
+
+ return createOrgFreedesktopOrgMethodCall(methodName.c_str(),
+ signature.empty() ? NULL : signature.c_str());
+}
+
+DBusMessage DBusMessage::createMethodCall(const char* busName,
+ const char* objectPath,
+ const char* interfaceName,
+ const char* methodName,
+ const char* signature) {
+ assert(busName);
+ assert(objectPath);
+ assert(interfaceName);
+ assert(methodName);
+
+ ::DBusMessage* libdbusMessageCall = dbus_message_new_method_call(busName,
+ objectPath,
+ interfaceName,
+ methodName);
+ assert(libdbusMessageCall);
+
+ if (signature)
+ dbus_message_set_signature(libdbusMessageCall, signature);
+
+ const bool increaseLibdbusMessageReferenceCount = false;
+ return DBusMessage(libdbusMessageCall, increaseLibdbusMessageReferenceCount);
+}
+
+DBusMessage DBusMessage::createMethodCall(const std::string& busName,
+ const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& methodName,
+ const std::string& signature) {
+ assert(!busName.empty());
+ assert(!objectPath.empty());
+ assert(!interfaceName.empty());
+ assert(!methodName.empty());
+
+ return createMethodCall(busName.c_str(),
+ objectPath.c_str(),
+ interfaceName.c_str(),
+ methodName.c_str(),
+ signature.empty() ? NULL : signature.c_str());
+}
+
+DBusMessage DBusMessage::createMethodReturn(const char* signature) const {
+ ::DBusMessage* libdbusMessageReturn = dbus_message_new_method_return(libdbusMessage_);
+ assert(libdbusMessageReturn);
+
+ if (signature)
+ dbus_message_set_signature(libdbusMessageReturn, signature);
+
+ const bool increaseLibdbusMessageReferenceCount = false;
+ return DBusMessage(libdbusMessageReturn, increaseLibdbusMessageReferenceCount);
+}
+
+DBusMessage DBusMessage::createMethodReturn(const std::string& signature) const {
+ return createMethodReturn(signature.empty() ? NULL : signature.c_str());
+}
+
+DBusMessage DBusMessage::createSignal(const char* objectPath,
+ const char* interfaceName,
+ const char* signalName,
+ const char* signature) {
+ assert(objectPath);
+ assert(interfaceName);
+ assert(signalName);
+
+ ::DBusMessage* libdbusMessageSignal = dbus_message_new_signal(objectPath,
+ interfaceName,
+ signalName);
+ assert(libdbusMessageSignal);
+
+ if (signature)
+ dbus_message_set_signature(libdbusMessageSignal, signature);
+
+ const bool increaseLibdbusMessageReferenceCount = false;
+ return DBusMessage(libdbusMessageSignal, increaseLibdbusMessageReferenceCount);
+}
+
+DBusMessage DBusMessage::createSignal(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& signalName,
+ const std::string& signature) {
+ assert(!objectPath.empty());
+ assert(!interfaceName.empty());
+ assert(!signalName.empty());
+
+ return createSignal(objectPath.c_str(),
+ interfaceName.c_str(),
+ signalName.c_str(),
+ signature.empty() ? NULL : signature.c_str());
+}
+
+const char* DBusMessage::getObjectPath() const {
+ return dbus_message_get_path(libdbusMessage_);
+}
+
+const char* DBusMessage::getSenderName() const {
+ return dbus_message_get_sender(libdbusMessage_);
+}
+
+const char* DBusMessage::getInterfaceName() const {
+ return dbus_message_get_interface(libdbusMessage_);
+}
+
+const char* DBusMessage::getMemberName() const {
+ return dbus_message_get_member(libdbusMessage_);
+}
+
+const char* DBusMessage::getSignatureString() const {
+ return dbus_message_get_signature(libdbusMessage_);
+}
+
+const char* DBusMessage::getErrorName() const {
+ assert(isErrorType());
+
+ return dbus_message_get_error_name(libdbusMessage_);
+}
+
+bool DBusMessage::hasMemberName(const char* memberName) const {
+ const char* dbusMessageMemberName = getMemberName();
+
+ assert(memberName);
+ assert(dbusMessageMemberName);
+
+ return !strcmp(dbusMessageMemberName, memberName);
+}
+
+bool DBusMessage::hasSignature(const char* signature) const {
+ const char* dbusMessageSignature = getSignatureString();
+
+ assert(signature);
+ assert(dbusMessageSignature);
+
+ return !strcmp(dbusMessageSignature, signature);
+}
+
+const DBusMessage::Type DBusMessage::getType() const {
+ const int libdbusType = dbus_message_get_type(libdbusMessage_);
+ return static_cast<Type>(libdbusType);
+}
+
+char* DBusMessage::getBodyData() const {
+ return dbus_message_get_body(libdbusMessage_);
+}
+
+int DBusMessage::getBodyLength() const {
+ return dbus_message_get_body_length(libdbusMessage_);
+}
+
+int DBusMessage::getBodySize() const {
+ return dbus_message_get_body_allocated(libdbusMessage_);
+}
+
+bool DBusMessage::setBodyLength(const int bodyLength) {
+ return dbus_message_set_body_length(libdbusMessage_, bodyLength);
+}
+
+} // namespace DBus
+} // namespace CommonAPI
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_DBUS_DBUS_MESSAGE_H_
+#define COMMONAPI_DBUS_DBUS_MESSAGE_H_
+
+#include <string>
+
+#include <dbus/dbus.h>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusConnection;
+
+class DBusMessage {
+ public:
+ DBusMessage();
+ DBusMessage(::DBusMessage* libdbusMessage);
+ DBusMessage(::DBusMessage* libdbusMessage, bool increaseReferenceCount);
+ DBusMessage(const DBusMessage& src);
+ DBusMessage(DBusMessage&& src);
+
+ ~DBusMessage();
+
+ DBusMessage& operator=(const DBusMessage& src);
+ DBusMessage& operator=(DBusMessage&& rsrc);
+ operator bool() const;
+
+ static DBusMessage createOrgFreedesktopOrgMethodCall(const char* methodName,
+ const char* signature = NULL);
+
+ static DBusMessage createOrgFreedesktopOrgMethodCall(const std::string& methodName,
+ const std::string& signature = "");
+
+ static DBusMessage createMethodCall(const char* busName,
+ const char* objectPath,
+ const char* interfaceName,
+ const char* methodName,
+ const char* signature = NULL);
+
+ static DBusMessage createMethodCall(const std::string& busName,
+ const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& methodName,
+ const std::string& signature = "");
+
+ DBusMessage createMethodReturn(const char* signature = NULL) const;
+
+ DBusMessage createMethodReturn(const std::string& signature) const;
+
+ static DBusMessage createSignal(const char* objectPath,
+ const char* interfaceName,
+ const char* signalName,
+ const char* signature = NULL);
+
+ static DBusMessage createSignal(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& signalName,
+ const std::string& signature = "");
+
+ const char* getSenderName() const;
+ const char* getObjectPath() const;
+ const char* getInterfaceName() const;
+ const char* getMemberName() const;
+ const char* getSignatureString() const;
+ const char* getErrorName() const;
+
+ bool hasMemberName(const char* memberName) const;
+ bool hasSignature(const char* signature) const;
+
+ enum class Type: int {
+ Invalid = DBUS_MESSAGE_TYPE_INVALID,
+ MethodCall = DBUS_MESSAGE_TYPE_METHOD_CALL,
+ MethodReturn = DBUS_MESSAGE_TYPE_METHOD_RETURN,
+ Error = DBUS_MESSAGE_TYPE_ERROR,
+ Signal = DBUS_MESSAGE_TYPE_SIGNAL
+ };
+ const Type getType() const;
+ inline bool isInvalidType() const;
+ inline bool isMethodCallType() const;
+ inline bool isMethodReturnType() const;
+ inline bool isErrorType() const;
+ inline bool isSignalType() const;
+
+ char* getBodyData() const;
+ int getBodyLength() const;
+ int getBodySize() const;
+
+ bool setBodyLength(const int bodyLength);
+
+ private:
+ ::DBusMessage* libdbusMessage_;
+
+ friend class DBusConnection;
+};
+
+bool DBusMessage::isInvalidType() const {
+ return (getType() == Type::Invalid);
+}
+
+bool DBusMessage::isMethodCallType() const {
+ return (getType() == Type::MethodCall);
+}
+
+bool DBusMessage::isMethodReturnType() const {
+ return (getType() == Type::MethodReturn);
+}
+
+bool DBusMessage::isErrorType() const {
+ return (getType() == Type::Error);
+}
+
+bool DBusMessage::isSignalType() const {
+ return (getType() == Type::Signal);
+}
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_MESSAGE_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_DBUS_DBUS_MULTI_EVENT_H_
+#define COMMONAPI_DBUS_DBUS_MULTI_EVENT_H_
+
+#include <CommonAPI/Event.h>
+
+#include <string>
+#include <unordered_map>
+
+namespace CommonAPI {
+namespace DBus {
+
+template <typename... _Arguments>
+class DBusMultiEvent {
+ public:
+ typedef std::function<SubscriptionStatus(const std::string&, const _Arguments&...)> Listener;
+ typedef std::unordered_multimap<std::string, Listener> ListenersMap;
+ typedef typename ListenersMap::iterator Subscription;
+
+ Subscription subscribeAll(const Listener& listener);
+ Subscription subscribe(const std::string& name, const Listener& listener);
+
+ void unsubscribe(Subscription listenerSubscription);
+
+ virtual ~DBusMultiEvent() { }
+
+ protected:
+ SubscriptionStatus notifyListeners(const std::string& name, const _Arguments&... eventArguments);
+
+ virtual void onFirstListenerAdded(const std::string& name, const Listener& listener) { }
+ virtual void onListenerAdded(const std::string& name, const Listener& listener) { }
+
+ virtual void onListenerRemoved(const std::string& name, const Listener& listener) { }
+ virtual void onLastListenerRemoved(const std::string& name, const Listener& listener) { }
+
+ private:
+ typedef std::pair<typename ListenersMap::iterator, typename ListenersMap::iterator> IteratorRange;
+ SubscriptionStatus notifyListenersRange(const std::string& name, IteratorRange listenersRange, const _Arguments&... eventArguments);
+
+ ListenersMap listenersMap_;
+};
+
+template <typename... _Arguments>
+typename DBusMultiEvent<_Arguments...>::Subscription
+DBusMultiEvent<_Arguments...>::subscribeAll(const Listener& listener) {
+ return subscribe(std::string(), listener);
+}
+
+template <typename... _Arguments>
+typename DBusMultiEvent<_Arguments...>::Subscription
+DBusMultiEvent<_Arguments...>::subscribe(const std::string& name, const Listener& listener) {
+ const bool firstListenerAdded = listenersMap_.empty();
+
+ auto listenerSubscription = listenersMap_.insert({name, listener});
+
+ if (firstListenerAdded)
+ onFirstListenerAdded(name, listener);
+
+ onListenerAdded(name, listener);
+
+ return listenerSubscription;
+}
+
+template <typename... _Arguments>
+void DBusMultiEvent<_Arguments...>::unsubscribe(Subscription listenerSubscription) {
+ const std::string name = listenerSubscription->first;
+ const Listener listener = listenerSubscription->second;
+
+ listenersMap_.erase(listenerSubscription);
+
+ onListenerRemoved(name, listener);
+
+ const bool lastListenerRemoved = listenersMap_.empty();
+ if (lastListenerRemoved)
+ onLastListenerRemoved(name, listener);
+}
+
+template <typename... _Arguments>
+SubscriptionStatus DBusMultiEvent<_Arguments...>::notifyListeners(const std::string& name, const _Arguments&... eventArguments) {
+ const SubscriptionStatus subscriptionStatus = notifyListenersRange(name, listenersMap_.equal_range(name), eventArguments...);
+
+ if (subscriptionStatus == SubscriptionStatus::CANCEL)
+ return SubscriptionStatus::CANCEL;
+
+ return notifyListenersRange(name, listenersMap_.equal_range(std::string()), eventArguments...);
+}
+
+template <typename... _Arguments>
+SubscriptionStatus DBusMultiEvent<_Arguments...>::notifyListenersRange(
+ const std::string& name,
+ IteratorRange listenersRange,
+ const _Arguments&... eventArguments) {
+ for (auto iterator = listenersRange.first; iterator != listenersRange.second; ) {
+ const Listener& listener = iterator->second;
+ const SubscriptionStatus listenerSubcriptionStatus = listener(name, eventArguments...);
+
+ if (listenerSubcriptionStatus == SubscriptionStatus::CANCEL) {
+ auto listenerIterator = iterator;
+ listenersMap_.erase(listenerIterator);
+ iterator++;
+ } else
+ iterator++;
+ }
+
+ return listenersMap_.empty() ? SubscriptionStatus::CANCEL : SubscriptionStatus::RETAIN;
+}
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_MULTI_EVENT_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public\r
+ * License, v. 2.0. If a copy of the MPL was not distributed with this\r
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\r
+#include "DBusObjectManager.h"\r
+#include "DBusOutputStream.h"\r
+\r
+#include <cassert>\r
+\r
+namespace CommonAPI {\r
+namespace DBus {\r
+\r
+DBusObjectManager::DBusObjectManager(const std::shared_ptr<DBusConnection>& dbusConnection):\r
+ dbusConnection_(dbusConnection) {\r
+\r
+ registerInterfaceHandler("/",\r
+ "org.freedesktop.DBus.ObjectManager",\r
+ std::bind(&DBusObjectManager::onGetDBusObjectManagerData, this, std::placeholders::_1));\r
+}\r
+\r
+DBusInterfaceHandlerToken DBusObjectManager::registerInterfaceHandler(const std::string& objectPath,\r
+ const std::string& interfaceName,\r
+ const DBusMessageInterfaceHandler& dbusMessageInterfaceHandler) {\r
+ DBusInterfaceHandlerPath handlerPath(objectPath, interfaceName);\r
+ bool noSuchHandlerRegistered = dbusRegisteredObjectsTable_.find(handlerPath) == dbusRegisteredObjectsTable_.end();\r
+\r
+ assert(noSuchHandlerRegistered);\r
+\r
+ dbusRegisteredObjectsTable_.insert({handlerPath, dbusMessageInterfaceHandler});\r
+ dbusConnection_->registerObjectPath(objectPath);\r
+\r
+ return handlerPath;\r
+}\r
+\r
+void DBusObjectManager::unregisterInterfaceHandler(const DBusInterfaceHandlerToken& dbusInterfaceHandlerToken) {\r
+ const std::string& objectPath = dbusInterfaceHandlerToken.first;\r
+\r
+ dbusConnection_->unregisterObjectPath(objectPath);\r
+\r
+ dbusRegisteredObjectsTable_.erase(dbusInterfaceHandlerToken);\r
+}\r
+\r
+bool DBusObjectManager::handleMessage(const DBusMessage& dbusMessage) const {\r
+ const char* objectPath = dbusMessage.getObjectPath();\r
+ const char* interfaceName = dbusMessage.getInterfaceName();\r
+\r
+ assert(objectPath);\r
+ assert(interfaceName);\r
+\r
+ DBusInterfaceHandlerPath handlerPath(objectPath, interfaceName);\r
+ auto handlerIterator = dbusRegisteredObjectsTable_.find(handlerPath);\r
+ const bool foundDBusInterfaceHandler = handlerIterator != dbusRegisteredObjectsTable_.end();\r
+ bool dbusMessageHandled = false;\r
+\r
+ if (foundDBusInterfaceHandler) {\r
+ const DBusMessageInterfaceHandler& interfaceHandlerDBusMessageHandler = handlerIterator->second;\r
+ dbusMessageHandled = interfaceHandlerDBusMessageHandler(dbusMessage);\r
+ }\r
+\r
+ return dbusMessageHandled;\r
+}\r
+\r
+bool DBusObjectManager::onGetDBusObjectManagerData(const DBusMessage& callMessage) {\r
+\r
+ DBusObjectToInterfaceDict dictToSend;\r
+\r
+ const char* interfaceName = callMessage.getInterfaceName();\r
+ const char* signature = callMessage.getSignatureString();\r
+\r
+ assert(!strcmp(interfaceName, "org.freedesktop.DBus.ObjectManager"));\r
+ assert(!strcmp(signature, ""));\r
+ assert(callMessage.getType() == DBusMessage::Type::MethodCall);\r
+\r
+ auto registeredObjectsIterator = dbusRegisteredObjectsTable_.begin();\r
+\r
+ while(registeredObjectsIterator != dbusRegisteredObjectsTable_.end()) {\r
+ DBusInterfaceHandlerPath handlerPath = registeredObjectsIterator->first;\r
+ auto foundDictEntry = dictToSend.find(handlerPath.first);\r
+\r
+ if(foundDictEntry == dictToSend.end()) {\r
+ dictToSend.insert( { handlerPath.first, { { handlerPath.second, {} } } } );\r
+ } else {\r
+ foundDictEntry->second.insert( {handlerPath.second, {} } );\r
+ }\r
+\r
+ ++registeredObjectsIterator;\r
+ }\r
+\r
+ DBusMessage replyMessage = callMessage.createMethodReturn(DBusServiceRegistry::getManagedObjectsDBusSignature_);\r
+\r
+ DBusOutputStream outStream(replyMessage);\r
+ outStream << dictToSend;\r
+ outStream.flush();\r
+ return dbusConnection_->sendDBusMessage(replyMessage);\r
+}\r
+\r
+\r
+} // namespace DBus\r
+} // namespace CommonAPI\r
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public\r
+ * License, v. 2.0. If a copy of the MPL was not distributed with this\r
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\r
+#ifndef COMMONAPI_DBUS_DBUS_OBJECT_MANAGER_H_\r
+#define COMMONAPI_DBUS_DBUS_OBJECT_MANAGER_H_\r
+\r
+#include "DBusMessage.h"\r
+#include "DBusConnection.h"\r
+\r
+namespace CommonAPI {\r
+namespace DBus {\r
+\r
+// objectPath, interfaceName\r
+typedef std::function<bool(const DBusMessage&)> DBusMessageInterfaceHandler;\r
+typedef std::pair<std::string, std::string> DBusInterfaceHandlerPath;\r
+typedef DBusInterfaceHandlerPath DBusInterfaceHandlerToken;\r
+\r
+class DBusConnection;\r
+\r
+class DBusObjectManager {\r
+ public:\r
+ DBusObjectManager(const std::shared_ptr<DBusConnection>&);\r
+\r
+ void init();\r
+\r
+ const DBusInterfaceHandlerToken registerInterfaceHandlerForDBusObject(const std::string& objectPath,\r
+ const std::string& interfaceName,\r
+ const DBusMessageInterfaceHandler& dbusMessageInterfaceHandler);\r
+\r
+ DBusInterfaceHandlerToken registerInterfaceHandler(const std::string& objectPath,\r
+ const std::string& interfaceName,\r
+ const DBusMessageInterfaceHandler& dbusMessageInterfaceHandler);\r
+\r
+ void unregisterInterfaceHandler(const DBusInterfaceHandlerToken& dbusInterfaceHandlerToken);\r
+\r
+ bool handleMessage(const DBusMessage&) const;\r
+\r
+\r
+ private:\r
+ void addLibdbusObjectPathHandler(const std::string& objectPath);\r
+ void removeLibdbusObjectPathHandler(const std::string& objectPath);\r
+\r
+ bool onGetDBusObjectManagerData(const DBusMessage& callMessage);\r
+\r
+ typedef std::unordered_map<DBusInterfaceHandlerPath, DBusMessageInterfaceHandler> DBusRegisteredObjectsTable;\r
+ DBusRegisteredObjectsTable dbusRegisteredObjectsTable_;\r
+\r
+ std::shared_ptr<DBusConnection> dbusConnection_;\r
+};\r
+\r
+} // namespace DBus\r
+} // namespace CommonAPI\r
+\r
+#endif // COMMONAPI_DBUS_DBUS_OBJECT_MANAGER_H_\r
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "DBusOutputStream.h"
+
+namespace CommonAPI {
+namespace DBus {
+
+DBusOutputStream::DBusOutputStream(DBusMessage dbusMessage) :
+ dbusMessage_(dbusMessage) {
+}
+
+DBusOutputStream::~DBusOutputStream() {
+}
+
+void DBusOutputStream::flush() {
+ const int toWrite = payload_.size();
+ const bool success = dbusMessage_.setBodyLength(toWrite);
+ char* destinationDataPtr = dbusMessage_.getBodyData();
+
+ memcpy(destinationDataPtr, payload_.c_str(), toWrite);
+}
+
+void DBusOutputStream::reserveMemory(size_t numOfBytes) {
+ assert(numOfBytes >= 0);
+
+ payload_.reserve(numOfBytes);
+}
+
+DBusOutputStream& DBusOutputStream::writeString(const char* cString, const uint32_t& length) {
+ assert(cString != NULL);
+ assert(cString[length] == '\0');
+
+ *this << length;
+
+ writeRawData(cString, length + 1);
+
+ return *this;
+}
+
+} // namespace DBus
+} // namespace CommonAPI
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_DBUS_DBUS_OUTPUT_MESSAGE_STREAM_H_
+#define COMMONAPI_DBUS_DBUS_OUTPUT_MESSAGE_STREAM_H_
+
+#include "DBusMessage.h"
+#include "DBusError.h"
+
+#include <CommonAPI/OutputStream.h>
+
+#include <string>
+#include <cstring>
+#include <vector>
+#include <cassert>
+#include <stack>
+
+namespace CommonAPI {
+namespace DBus {
+
+/**
+ * Used to mark the position of a pointer within an array of bytes.
+ */
+typedef uint32_t position_t;
+
+
+/**
+ * @class DBusOutputMessageStream
+ *
+ * Used to serialize and write data into a #DBusMessage. For all data types that may be written to a #DBusMessage, a "<<"-operator should be defined to handle the writing
+ * (this operator is predefined for all basic data types and for vectors). The signature that has to be written to the #DBusMessage separately is assumed
+ * to match the actual data that is inserted via the #DBusOutputMessageStream.
+ */
+class DBusOutputStream: public OutputStream {
+ public:
+ virtual OutputStream& writeValue(const bool& boolValue) { return writeBasicTypeValue<uint32_t>(boolValue); }
+
+ virtual OutputStream& writeValue(const int8_t& int8Value) { return writeBasicTypeValue(int8Value); }
+ virtual OutputStream& writeValue(const int16_t& int16Value) { return writeBasicTypeValue(int16Value); }
+ virtual OutputStream& writeValue(const int32_t& int32Value) { return writeBasicTypeValue(int32Value); }
+ virtual OutputStream& writeValue(const int64_t& int64Value) { return writeBasicTypeValue(int64Value); }
+
+ virtual OutputStream& writeValue(const uint8_t& uint8Value) { return writeBasicTypeValue(uint8Value); }
+ virtual OutputStream& writeValue(const uint16_t& uint16Value) { return writeBasicTypeValue(uint16Value); }
+ virtual OutputStream& writeValue(const uint32_t& uint32Value) { return writeBasicTypeValue(uint32Value); }
+ virtual OutputStream& writeValue(const uint64_t& uint64Value) { return writeBasicTypeValue(uint64Value); }
+
+ virtual OutputStream& writeValue(const float& floatValue) { return writeBasicTypeValue((double) floatValue); }
+ virtual OutputStream& writeValue(const double& doubleValue) { return writeBasicTypeValue(doubleValue); }
+
+ virtual OutputStream& writeValue(const std::string& stringValue) { return writeString(stringValue.c_str(), stringValue.length()); }
+
+ inline virtual OutputStream& writeValue(const ByteBuffer& byteBufferValue);
+
+ virtual OutputStream& writeEnumValue(const int8_t& int8BackingTypeValue) { return writeValue(int8BackingTypeValue); }
+ virtual OutputStream& writeEnumValue(const int16_t& int16BackingTypeValue) { return writeValue(int16BackingTypeValue); }
+ virtual OutputStream& writeEnumValue(const int32_t& int32BackingTypeValue) { return writeValue(int32BackingTypeValue); }
+ virtual OutputStream& writeEnumValue(const int64_t& int64BackingTypeValue) { return writeValue(int64BackingTypeValue); }
+ virtual OutputStream& writeEnumValue(const uint8_t& uint8BackingTypeValue) { return writeValue(uint8BackingTypeValue); }
+ virtual OutputStream& writeEnumValue(const uint16_t& uint16BackingTypeValue) { return writeValue(uint16BackingTypeValue); }
+ virtual OutputStream& writeEnumValue(const uint32_t& uint32BackingTypeValue) { return writeValue(uint32BackingTypeValue); }
+ virtual OutputStream& writeEnumValue(const uint64_t& uint64BackingTypeValue) { return writeValue(uint64BackingTypeValue); }
+
+ virtual void beginWriteBoolVector(uint32_t sizeOfVector) {
+ beginWriteGenericVector();
+ rememberCurrentStreamPosition();
+ }
+ virtual void beginWriteInt8Vector(uint32_t sizeOfVector) {
+ beginWriteGenericVector();
+ rememberCurrentStreamPosition();
+ }
+ virtual void beginWriteInt16Vector(uint32_t sizeOfVector) {
+ beginWriteGenericVector();
+ rememberCurrentStreamPosition();
+ }
+ virtual void beginWriteInt32Vector(uint32_t sizeOfVector) {
+ beginWriteGenericVector();
+ rememberCurrentStreamPosition();
+ }
+ virtual void beginWriteInt64Vector(uint32_t sizeOfVector) {
+ beginWriteGenericVector();
+ alignToBoundary(8);
+ rememberCurrentStreamPosition();
+ }
+ virtual void beginWriteUInt8Vector(uint32_t sizeOfVector) {
+ beginWriteGenericVector();
+ rememberCurrentStreamPosition();
+ }
+ virtual void beginWriteUInt16Vector(uint32_t sizeOfVector) {
+ beginWriteGenericVector();
+ rememberCurrentStreamPosition();
+ }
+ virtual void beginWriteUInt32Vector(uint32_t sizeOfVector) {
+ beginWriteGenericVector();
+ rememberCurrentStreamPosition();
+ }
+ virtual void beginWriteUInt64Vector(uint32_t sizeOfVector) {
+ beginWriteGenericVector();
+ alignToBoundary(8);
+ rememberCurrentStreamPosition();
+ }
+ virtual void beginWriteFloatVector(uint32_t sizeOfVector) {
+ beginWriteGenericVector();
+ alignToBoundary(8);
+ rememberCurrentStreamPosition();
+ }
+ virtual void beginWriteDoubleVector(uint32_t sizeOfVector) {
+ beginWriteGenericVector();
+ alignToBoundary(8);
+ rememberCurrentStreamPosition();
+ }
+ virtual void beginWriteStringVector(uint32_t sizeOfVector) {
+ beginWriteGenericVector();
+ rememberCurrentStreamPosition();
+ }
+ virtual void beginWriteByteBufferVector(uint32_t sizeOfVector) {
+ beginWriteGenericVector();
+ rememberCurrentStreamPosition();
+ }
+ virtual void beginWriteVersionVector(uint32_t sizeOfVector) {
+ beginWriteGenericVector();
+ alignToBoundary(8);
+ rememberCurrentStreamPosition();
+ }
+ virtual void beginWriteVectorOfSerializableStructs(uint32_t sizeOfVector) {
+ beginWriteGenericVector();
+ alignToBoundary(8);
+ rememberCurrentStreamPosition();
+ }
+ virtual void beginWriteVectorOfVectors(uint32_t sizeOfVector) {
+ beginWriteGenericVector();
+ rememberCurrentStreamPosition();
+ }
+ virtual void beginWriteVectorOfMaps(uint32_t sizeOfVector) {
+ beginWriteGenericVector();
+ alignToBoundary(8);
+ rememberCurrentStreamPosition();
+ }
+
+ virtual void endWriteVector() {
+ uint32_t numOfWrittenBytes = getCurrentStreamPosition() - popRememberedStreamPosition();
+ writeBasicTypeValueAtPosition(popRememberedStreamPosition(), numOfWrittenBytes);
+ }
+
+ virtual OutputStream& writeVersionValue(const Version& versionValue) {
+ alignToBoundary(8);
+ writeValue(versionValue.Major);
+ writeValue(versionValue.Minor);
+ return *this;
+ }
+
+ virtual void beginWriteSerializableStruct(const SerializableStruct& serializableStruct) { alignToBoundary(8); }
+ virtual void endWriteSerializableStruct(const SerializableStruct& serializableStruct) { }
+
+ virtual void beginWriteMap(size_t elementCount) {
+ alignToBoundary(sizeof(uint32_t));
+ rememberCurrentStreamPosition();
+ writeBasicTypeValue((uint32_t) 0);
+ alignToBoundary(8);
+ rememberCurrentStreamPosition();
+ }
+
+ virtual void endWriteMap() {
+ uint32_t numOfWrittenBytes = getCurrentStreamPosition() - popRememberedStreamPosition();
+ writeBasicTypeValueAtPosition(popRememberedStreamPosition(), numOfWrittenBytes);
+ }
+
+ virtual bool hasError() const {
+ return dbusError_;
+ }
+
+ /**
+ * Creates a #DBusOutputMessageStream which can be used to serialize and write data into the given #DBusMessage. Any data written is buffered within the stream.
+ * Remember to call flush() when you are done with writing: Only then the data actually is written to the #DBusMessage.
+ *
+ * @param dbusMessage The #DBusMessage any data pushed into this stream should be written to.
+ */
+ DBusOutputStream(DBusMessage dbusMessage);
+
+ /**
+ * Destructor; does not call the destructor of the referred #DBusMessage. Make sure to maintain a reference to the
+ * #DBusMessage outside of the stream if you intend to make further use of the message, e.g. in order to send it,
+ * now that you have written some payload into it.
+ */
+ virtual ~DBusOutputStream();
+
+ /**
+ * Writes the data that was buffered within this #DBusOutputMessageStream to the #DBusMessage that was given to the constructor. Each call to flush()
+ * will completely override the data that currently is contained in the #DBusMessage. The data that is buffered in this #DBusOutputMessageStream is
+ * not deleted by calling flush().
+ */
+ void flush();
+
+ /**
+ * Marks the stream as erroneous.
+ */
+ inline void setError();
+
+ /**
+ * Reserves the given number of bytes for writing, thereby negating the need to dynamically allocate memory while writing.
+ * Use this method for optimization: If possible, reserve as many bytes as you need for your data before doing any writing.
+ *
+ * @param numOfBytes The number of bytes that should be reserved for writing.
+ */
+ void reserveMemory(size_t numOfBytes);
+
+ /**
+ * @return current data position where later writing is possible
+ */
+ size_t getCurrentPosition();
+
+ template<typename _BasicType>
+ DBusOutputStream& writeBasicTypeValue(const _BasicType& basicValue) {
+ if (sizeof(_BasicType) > 1)
+ alignToBoundary(sizeof(_BasicType));
+
+ writeRawData(reinterpret_cast<const char*>(&basicValue), sizeof(_BasicType));
+
+ return *this;
+ }
+
+ template<typename _BasicType>
+ bool writeBasicTypeValueAtPosition(size_t position, const _BasicType& basicValue) {
+ assert(position + sizeof(_BasicType) <= payload_.size());
+
+ return writeRawDataAtPosition(position, reinterpret_cast<const char*>(&basicValue), sizeof(_BasicType));
+ }
+
+ DBusOutputStream& writeString(const char* cString, const uint32_t& length);
+
+ /**
+ * Fills the stream with 0-bytes to make the next value be aligned to the boundary given.
+ * This means that as many 0-bytes are written to the buffer as are necessary
+ * to make the next value start with the given alignment.
+ *
+ * @param alignBoundary The byte-boundary to which the next value should be aligned.
+ */
+ virtual void alignToBoundary(const size_t alignBoundary);
+
+ /**
+ * Takes sizeInByte characters, starting from the character which val points to, and stores them for later writing.
+ * When calling flush(), all values that were written to this stream are copied into the payload of the #DBusMessage.
+ *
+ * The array of characters might be created from a pointer to a given value by using a reinterpret_cast. Example:
+ * @code
+ * ...
+ * int32_t val = 15;
+ * outputMessageStream.alignForBasicType(sizeof(int32_t));
+ * const char* const reinterpreted = reinterpret_cast<const char*>(&val);
+ * outputMessageStream.writeValue(reinterpreted, sizeof(int32_t));
+ * ...
+ * @endcode
+ *
+ * @param val The array of chars that should serve as input
+ * @param sizeInByte The number of bytes that should be written
+ * @return true if writing was successful, false otherwise.
+ *
+ * @see DBusOutputMessageStream()
+ * @see flush()
+ */
+ bool writeRawData(const char* rawDataPtr, const size_t sizeInByte);
+
+ bool writeRawDataAtPosition(size_t position, const char* rawDataPtr, const size_t sizeInByte);
+
+ protected:
+ std::string payload_;
+
+ private:
+ inline void beginWriteGenericVector() {
+ alignToBoundary(sizeof(uint32_t));
+ rememberCurrentStreamPosition();
+ writeBasicTypeValue((uint32_t) 0);
+ }
+
+ inline void rememberCurrentStreamPosition() {
+ savedStreamPositions_.push(payload_.size());
+ }
+
+ inline size_t popRememberedStreamPosition() {
+ size_t val = savedStreamPositions_.top();
+ savedStreamPositions_.pop();
+ return val;
+ }
+
+ inline size_t getCurrentStreamPosition() {
+ return payload_.size();
+ }
+
+ DBusError dbusError_;
+ DBusMessage dbusMessage_;
+
+ std::stack<position_t> savedStreamPositions_;
+};
+
+
+//Additional 0-termination, so this is 8 byte of \0
+static const char* eightByteZeroString = "\0\0\0\0\0\0\0";
+
+inline void DBusOutputStream::alignToBoundary(const size_t alignBoundary) {
+ assert(alignBoundary > 0 && alignBoundary <= 8 && (alignBoundary % 2 == 0 || alignBoundary == 1));
+
+ size_t alignMask = alignBoundary - 1;
+ size_t necessaryAlignment = ((alignMask - (payload_.size() & alignMask)) + 1) & alignMask;
+
+ writeRawData(eightByteZeroString, necessaryAlignment);
+}
+
+inline bool DBusOutputStream::writeRawData(const char* rawDataPtr, const size_t sizeInByte) {
+ assert(sizeInByte >= 0);
+
+ payload_.append(rawDataPtr, sizeInByte);
+
+ return true;
+}
+
+inline bool DBusOutputStream::writeRawDataAtPosition(size_t position, const char* rawDataPtr, const size_t sizeInByte) {
+ assert(sizeInByte >= 0);
+
+ payload_ = payload_.replace(position, sizeInByte, rawDataPtr, sizeInByte);
+
+ return true;
+}
+
+inline size_t DBusOutputStream::getCurrentPosition() {
+ return payload_.size();
+}
+
+
+OutputStream& DBusOutputStream::writeValue(const ByteBuffer& byteBufferValue) {
+ *this << byteBufferValue;
+ return *this;
+}
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_OUTPUT_MESSAGE_STREAM_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "DBusProxy.h"
+#include "DBusServiceRegistry.h"
+#include "DBusUtils.h"
+
+#include <algorithm>
+#include <cassert>
+#include <iostream>
+#include <dbus/dbus.h>
+#include <functional>
+#include <CommonAPI/Event.h>
+
+namespace CommonAPI {
+namespace DBus {
+
+DBusProxyStatusEvent::DBusProxyStatusEvent(DBusProxy* dbusProxy) :
+ dbusProxy_(dbusProxy) {
+}
+
+void DBusProxyStatusEvent::onFirstListenerAdded(const Listener& listener) {
+ auto serviceStatusListener = std::bind(
+ &DBusProxyStatusEvent::onServiceAvailableSignalHandler,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2);
+
+ subscription_ = dbusProxy_->getDBusConnection()->getDBusServiceRegistry()->getServiceStatusEvent().subscribe(
+ dbusProxy_->dbusBusName_ + ":" + dbusProxy_->dbusObjectPath_ + ":" + dbusProxy_->interfaceName_,
+ serviceStatusListener);
+}
+
+void DBusProxyStatusEvent::onLastListenerRemoved(const Listener& listener) {
+ dbusProxy_->getDBusConnection()->getDBusServiceRegistry()->getServiceStatusEvent().unsubscribe(subscription_);
+}
+
+SubscriptionStatus DBusProxyStatusEvent::onServiceAvailableSignalHandler(const std::string& name,
+ const AvailabilityStatus& availabilityStatus) {
+ AvailabilityStatus availability = availabilityStatus;
+
+ return notifyListeners(availability);
+}
+
+const std::string DBusProxy::domain_ = "local";
+
+DBusProxy::DBusProxy(const std::string& dbusBusName,
+ const std::string& dbusObjectPath,
+ const std::string& interfaceName,
+ const std::shared_ptr<DBusProxyConnection>& dbusProxyConnection) :
+ dbusBusName_(dbusBusName),
+ dbusObjectPath_(dbusObjectPath),
+ interfaceName_(interfaceName),
+ statusEvent_(this),
+ interfaceVersionAttribute_(*this, "getInterfaceVersion"),
+ available_(false),
+ availableSet_(false),
+ connection_(dbusProxyConnection) {
+}
+
+DBusProxy::DBusProxy(const std::string& dbusBusName,
+ const std::string& dbusObjectPath,
+ const std::string& interfaceName,
+ const std::shared_ptr<DBusProxyConnection>& connection,
+ const bool isAlwaysAvailable) :
+ dbusBusName_(dbusBusName),
+ dbusObjectPath_(dbusObjectPath),
+ interfaceName_(interfaceName),
+ statusEvent_(this),
+ interfaceVersionAttribute_(*this, "getInterfaceVersion"),
+ available_(isAlwaysAvailable),
+ availableSet_(isAlwaysAvailable),
+ connection_(connection) {
+}
+
+std::string DBusProxy::getAddress() const {
+ return domain_ + ":" + interfaceName_ + ":" + dbusBusName_;
+}
+
+const std::string& DBusProxy::getDomain() const {
+ return domain_;
+}
+
+const std::string& DBusProxy::getServiceId() const {
+ return getInterfaceName();
+}
+
+const std::string& DBusProxy::getInstanceId() const {
+ return dbusBusName_;
+}
+
+
+bool DBusProxy::isAvailable() const {
+ if (!availableSet_) {
+ auto status = getDBusConnection()->getDBusServiceRegistry()->getReadyFuture().wait_for(std::chrono::milliseconds(1));
+ if (checkReady(status)) {
+ available_ = getDBusConnection()->getDBusServiceRegistry()->isServiceInstanceAlive(getAddress());
+ availableSet_ = true;
+ }
+ }
+ return available_;
+}
+
+bool DBusProxy::isAvailableBlocking() const {
+
+ if (!availableSet_) {
+ getDBusConnection()->getDBusServiceRegistry()->getReadyFuture().wait();
+ available_ = getDBusConnection()->getDBusServiceRegistry()->isServiceInstanceAlive(getAddress());
+ availableSet_ = true;
+ }
+ return available_;
+}
+
+ProxyStatusEvent& DBusProxy::getProxyStatusEvent() {
+ return statusEvent_;
+}
+
+InterfaceVersionAttribute& DBusProxy::getInterfaceVersionAttribute() {
+ return interfaceVersionAttribute_;
+}
+
+DBusMessage DBusProxy::createMethodCall(const char* methodName,
+ const char* methodSignature) const {
+ return DBusMessage::createMethodCall(
+ dbusBusName_.c_str(),
+ dbusObjectPath_.c_str(),
+ getInterfaceName().c_str(),
+ methodName,
+ methodSignature);
+}
+
+} // namespace DBus
+} // namespace CommonAPI
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_DBUS_DBUS_PROXY_H_
+#define COMMONAPI_DBUS_DBUS_PROXY_H_
+
+#include "DBusProxyConnection.h"
+#include "DBusAttribute.h"
+
+#include <CommonAPI/Proxy.h>
+#include <CommonAPI/types.h>
+
+#include <functional>
+#include <memory>
+#include <string>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusProxy;
+
+typedef Event<AvailabilityStatus> ProxyStatusEvent;
+
+class DBusProxyStatusEvent: public ProxyStatusEvent {
+ public:
+ DBusProxyStatusEvent(DBusProxy* dbusProxy);
+
+ void onFirstListenerAdded(const Listener& listener);
+ void onLastListenerRemoved(const Listener& listener);
+
+ Subscription subscribe(Listener listener);
+
+ private:
+ SubscriptionStatus onServiceAvailableSignalHandler(const std::string& name, const AvailabilityStatus& availabilityStatus);
+
+ DBusProxy* dbusProxy_;
+ DBusServiceStatusEvent::Subscription subscription_;
+
+ friend class DBusProxy;
+
+};
+
+
+class DBusProxy: public virtual CommonAPI::Proxy {
+ public:
+ DBusProxy(const std::string& dbusBusName,
+ const std::string& dbusObjectPath,
+ const std::string& interfaceName,
+ const std::shared_ptr<DBusProxyConnection>& dbusProxyConnection);
+
+ virtual std::string getAddress() const;
+ virtual const std::string& getDomain() const;
+ virtual const std::string& getServiceId() const;
+ virtual const std::string& getInstanceId() const;
+ virtual bool isAvailable() const;
+ virtual bool isAvailableBlocking() const;
+ virtual ProxyStatusEvent& getProxyStatusEvent();
+ virtual InterfaceVersionAttribute& getInterfaceVersionAttribute();
+
+ inline const std::string& getDBusBusName() const;
+ inline const std::string& getDBusObjectPath() const;
+ inline const std::string& getInterfaceName() const;
+ inline const std::shared_ptr<DBusProxyConnection>& getDBusConnection() const;
+
+ DBusMessage createMethodCall(const char* methodName,
+ const char* methodSignature = NULL) const;
+
+ inline DBusProxyConnection::DBusSignalHandlerToken addSignalMemberHandler(
+ const std::string& signalName,
+ const std::string& signalSignature,
+ DBusProxyConnection::DBusSignalHandler* dbusSignalHandler);
+
+ inline void removeSignalMemberHandler(const DBusProxyConnection::DBusSignalHandlerToken& dbusSignalHandlerToken);
+
+ protected:
+ DBusProxy(const DBusProxy& abstractProxy) = delete;
+
+ DBusProxy(const std::string& busName,
+ const std::string& objectId,
+ const std::string& interfaceName,
+ const std::shared_ptr<DBusProxyConnection>& connection,
+ const bool isAlwaysAvailable);
+
+ virtual void getOwnVersion(uint16_t& ownVersionMajor, uint16_t& ownVersionMinor) const = 0;
+
+ DBusProxyStatusEvent statusEvent_;
+ DBusProxyStatusEvent::Subscription remoteStatusSubscription_;
+
+ private:
+ void onServiceAlive(bool alive);
+
+ const std::string dbusBusName_;
+ const std::string dbusObjectPath_;
+ const std::string interfaceName_;
+
+ mutable bool available_;
+ mutable bool availableSet_;
+
+ std::shared_ptr<DBusProxyConnection> connection_;
+
+ DBusReadonlyAttribute<InterfaceVersionAttribute> interfaceVersionAttribute_;
+
+ static const std::string domain_;
+
+ friend class DBusProxyStatusEvent;
+};
+
+const std::string& DBusProxy::getDBusBusName() const {
+ return dbusBusName_;
+}
+
+const std::string& DBusProxy::getDBusObjectPath() const {
+ return dbusObjectPath_;
+}
+
+const std::string& DBusProxy::getInterfaceName() const {
+ return interfaceName_;
+}
+
+const std::shared_ptr<DBusProxyConnection>& DBusProxy::getDBusConnection() const {
+ return connection_;
+}
+
+DBusProxyConnection::DBusSignalHandlerToken DBusProxy::addSignalMemberHandler(
+ const std::string& signalName,
+ const std::string& signalSignature,
+ DBusProxyConnection::DBusSignalHandler* dbusSignalHandler) {
+ return connection_->addSignalMemberHandler(dbusObjectPath_, getInterfaceName(), signalName, signalSignature, dbusSignalHandler);
+}
+
+void DBusProxy::removeSignalMemberHandler(const DBusProxyConnection::DBusSignalHandlerToken& dbusSignalHandlerToken) {
+ return connection_->removeSignalMemberHandler(dbusSignalHandlerToken);
+}
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_PROXY_H_
+
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_DBUS_DBUS_PROXY_ASYNC_CALLBACK_HANDLER_H_
+#define COMMONAPI_DBUS_DBUS_PROXY_ASYNC_CALLBACK_HANDLER_H_
+
+#include "DBusProxyConnection.h"
+#include "DBusMessage.h"
+#include "DBusSerializableArguments.h"
+#include "DBusHelper.h"
+
+#include <functional>
+#include <future>
+#include <memory>
+#include <iostream>
+
+
+namespace CommonAPI {
+namespace DBus {
+
+template <typename ... _ArgTypes>
+class DBusProxyAsyncCallbackHandler: public DBusProxyConnection::DBusMessageReplyAsyncHandler {
+ public:
+ typedef std::function<void(CallStatus, _ArgTypes...)> FunctionType;
+
+ static inline std::unique_ptr<DBusProxyConnection::DBusMessageReplyAsyncHandler> create(FunctionType&& callback) {
+ return std::unique_ptr<DBusProxyConnection::DBusMessageReplyAsyncHandler>(
+ new DBusProxyAsyncCallbackHandler(std::move(callback)));
+ }
+
+ DBusProxyAsyncCallbackHandler() = delete;
+ DBusProxyAsyncCallbackHandler(FunctionType&& callback):
+ callback_(std::move(callback)) {
+ }
+
+ virtual std::future<CallStatus> getFuture() {
+ return promise_.get_future();
+ }
+
+ virtual void onDBusMessageReply(const CallStatus& dbusMessageCallStatus, const DBusMessage& dbusMessage) {
+ promise_.set_value(handleDBusMessageReply(dbusMessageCallStatus, dbusMessage, typename make_sequence<sizeof...(_ArgTypes)>::type()));
+ }
+
+ private:
+ template <int... _ArgIndices>
+ inline CallStatus handleDBusMessageReply(const CallStatus dbusMessageCallStatus, const DBusMessage& dbusMessage, index_sequence<_ArgIndices...>) const {
+ CallStatus callStatus = dbusMessageCallStatus;
+ std::tuple<_ArgTypes...> argTuple;
+
+ if (dbusMessageCallStatus == CallStatus::SUCCESS) {
+ if (!dbusMessage.isErrorType()) {
+ DBusInputStream dbusInputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_ArgTypes...>::deserialize(dbusInputStream, std::get<_ArgIndices>(argTuple)...);
+ if (!success)
+ callStatus = CallStatus::REMOTE_ERROR;
+ } else {
+ callStatus = CallStatus::REMOTE_ERROR;
+ }
+ }
+
+ callback_(callStatus, std::move(std::get<_ArgIndices>(argTuple))...);
+ return callStatus;
+ }
+
+ std::promise<CallStatus> promise_;
+ const FunctionType callback_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_PROXY_ASYNC_CALLBACK_HANDLER_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public\r
+ * License, v. 2.0. If a copy of the MPL was not distributed with this\r
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\r
+#ifndef COMMONAPI_DBUS_DBUS_PROXY_CONNECTION_H_\r
+#define COMMONAPI_DBUS_DBUS_PROXY_CONNECTION_H_\r
+\r
+#include "DBusError.h"\r
+#include "DBusMessage.h"\r
+\r
+#include "DBusFunctionalHash.h"\r
+#include "DBusServiceStatusEvent.h"\r
+\r
+#include <CommonAPI/types.h>\r
+#include <CommonAPI/Attribute.h>\r
+#include <CommonAPI/Event.h>\r
+\r
+#include <cstdint>\r
+#include <functional>\r
+#include <future>\r
+#include <memory>\r
+#include <tuple>\r
+#include <unordered_map>\r
+#include <utility>\r
+#include <vector>\r
+\r
+namespace CommonAPI {\r
+namespace DBus {\r
+\r
+\r
+typedef std::function<void(const DBusMessage&)> DBusMessageHandler;\r
+\r
+class DBusDaemonProxy;\r
+class DBusServiceRegistry;\r
+class DBusObjectManager;\r
+\r
+\r
+class DBusProxyConnection {\r
+ public:\r
+ class DBusMessageReplyAsyncHandler {\r
+ public:\r
+ virtual ~DBusMessageReplyAsyncHandler() { }\r
+ virtual std::future<CallStatus> getFuture() = 0;\r
+ virtual void onDBusMessageReply(const CallStatus&, const DBusMessage&) = 0;\r
+ };\r
+\r
+ class DBusSignalHandler {\r
+ public:\r
+ virtual ~DBusSignalHandler() { }\r
+ virtual SubscriptionStatus onSignalDBusMessage(const DBusMessage&) = 0;\r
+ };\r
+\r
+ // objectPath, interfaceName, interfaceMemberName, interfaceMemberSignature\r
+ typedef std::tuple<std::string, std::string, std::string, std::string> DBusSignalHandlerPath;\r
+ typedef std::unordered_multimap<DBusSignalHandlerPath, DBusSignalHandler*> DBusSignalHandlerTable;\r
+ typedef DBusSignalHandlerPath DBusSignalHandlerToken;\r
+\r
+\r
+ virtual ~DBusProxyConnection() { }\r
+\r
+ virtual bool isConnected() const = 0;\r
+\r
+ virtual bool sendDBusMessage(const DBusMessage& dbusMessage, uint32_t* allocatedSerial = NULL) const = 0;\r
+\r
+ static const int kDefaultSendTimeoutMs = 100 * 1000;\r
+\r
+ virtual std::future<CallStatus> sendDBusMessageWithReplyAsync(\r
+ const DBusMessage& dbusMessage,\r
+ std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler,\r
+ int timeoutMilliseconds = kDefaultSendTimeoutMs) const = 0;\r
+\r
+ virtual DBusMessage sendDBusMessageWithReplyAndBlock(\r
+ const DBusMessage& dbusMessage,\r
+ DBusError& dbusError,\r
+ int timeoutMilliseconds = kDefaultSendTimeoutMs) const = 0;\r
+\r
+ virtual DBusSignalHandlerToken addSignalMemberHandler(\r
+ const std::string& objectPath,\r
+ const std::string& interfaceName,\r
+ const std::string& interfaceMemberName,\r
+ const std::string& interfaceMemberSignature,\r
+ DBusSignalHandler* dbusSignalHandler) = 0;\r
+\r
+ virtual void removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken) = 0;\r
+\r
+ virtual const std::shared_ptr<DBusDaemonProxy>& getDBusDaemonProxy() = 0;\r
+ virtual const std::shared_ptr<DBusServiceRegistry>& getDBusServiceRegistry() = 0;\r
+ virtual const std::shared_ptr<DBusObjectManager>& getDBusObjectManager() = 0;\r
+};\r
+\r
+\r
+} // namespace DBus\r
+} // namespace CommonAPI\r
+\r
+#endif //COMMONAPI_DBUS_DBUS_PROXY_CONNECTION_H_\r
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_DBUS_DBUS_PROXY_HELPER_H_
+#define COMMONAPI_DBUS_DBUS_PROXY_HELPER_H_
+
+#include "DBusMessage.h"
+#include "DBusSerializableArguments.h"
+#include "DBusProxyAsyncCallbackHandler.h"
+
+#include <functional>
+#include <future>
+#include <memory>
+#include <string>
+
+namespace CommonAPI {
+namespace DBus {
+
+
+class DBusProxy;
+
+
+template< class, class >
+struct DBusProxyHelper;
+
+template <
+ template <class...> class _In, class... _InArgs,
+ template <class...> class _Out, class... _OutArgs>
+struct DBusProxyHelper<_In<_InArgs...>, _Out<_OutArgs...>> {
+ template <typename _DBusProxy = DBusProxy>
+ static void callMethod(const _DBusProxy& dbusProxy,
+ const char* methodName,
+ const char* methodSignature,
+ const _InArgs&... inArgs,
+ CommonAPI::CallStatus& callStatus) {
+ if (dbusProxy.isAvailableBlocking()) {
+
+ DBusMessage dbusMessage = dbusProxy.createMethodCall(methodName, methodSignature);
+
+ if (sizeof...(_InArgs) > 0) {
+ DBusOutputStream outputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...);
+ if (!success) {
+ callStatus = CallStatus::OUT_OF_MEMORY;
+ return;
+ }
+ outputStream.flush();
+ }
+
+ const bool dbusMessageSent = dbusProxy.getDBusConnection()->sendDBusMessage(dbusMessage);
+ callStatus = dbusMessageSent ? CallStatus::SUCCESS : CallStatus::OUT_OF_MEMORY;
+ } else {
+ callStatus = CallStatus::NOT_AVAILABLE;
+ }
+ }
+
+ template <typename _DBusProxy = DBusProxy>
+ static void callMethodWithReply(
+ const _DBusProxy& dbusProxy,
+ const char* methodName,
+ const char* methodSignature,
+ const _InArgs&... inArgs,
+ CommonAPI::CallStatus& callStatus,
+ _OutArgs&... outArgs) {
+
+ if (dbusProxy.isAvailableBlocking()) {
+
+ DBusMessage dbusMethodCall = dbusProxy.createMethodCall(methodName, methodSignature);
+
+ if (sizeof...(_InArgs) > 0) {
+ DBusOutputStream outputStream(dbusMethodCall);
+ const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...);
+ if (!success) {
+ callStatus = CallStatus::OUT_OF_MEMORY;
+ return;
+ }
+ outputStream.flush();
+ }
+
+ DBusError dbusError;
+ DBusMessage dbusMessageReply = dbusProxy.getDBusConnection()->sendDBusMessageWithReplyAndBlock(dbusMethodCall, dbusError);
+ if (dbusError || !dbusMessageReply.isMethodReturnType()) {
+ callStatus = CallStatus::REMOTE_ERROR;
+ return;
+ }
+
+ if (sizeof...(_OutArgs) > 0) {
+ DBusInputStream inputStream(dbusMessageReply);
+ const bool success = DBusSerializableArguments<_OutArgs...>::deserialize(inputStream, outArgs...);
+ if (!success) {
+ callStatus = CallStatus::REMOTE_ERROR;
+ return;
+ }
+ }
+
+ callStatus = CallStatus::SUCCESS;
+ } else {
+ callStatus = CallStatus::NOT_AVAILABLE;
+ }
+ }
+
+ template <typename _DBusProxy = DBusProxy, typename _AsyncCallback>
+ static std::future<CallStatus> callMethodAsync(
+ const _DBusProxy& dbusProxy,
+ const char* methodName,
+ const char* methodSignature,
+ const _InArgs&... inArgs,
+ _AsyncCallback asyncCallback) {
+
+ if (dbusProxy.isAvailable()) {
+
+ DBusMessage dbusMessage = dbusProxy.createMethodCall(methodName, methodSignature);
+
+ if (sizeof...(_InArgs) > 0) {
+ DBusOutputStream outputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...);
+ if (!success) {
+ std::promise<CallStatus> promise;
+ promise.set_value(CallStatus::OUT_OF_MEMORY);
+ return promise.get_future();
+ }
+ outputStream.flush();
+ }
+
+ return dbusProxy.getDBusConnection()->sendDBusMessageWithReplyAsync(
+ dbusMessage,
+ DBusProxyAsyncCallbackHandler<_OutArgs...>::create(std::move(asyncCallback)));
+ } else {
+ std::promise<CallStatus> promise;
+ promise.set_value(CallStatus::NOT_AVAILABLE);
+ return promise.get_future();
+ }
+ }
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_PROXY_HELPER_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public\r
+ * License, v. 2.0. If a copy of the MPL was not distributed with this\r
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\r
+#include "DBusRuntime.h"\r
+\r
+namespace CommonAPI {\r
+namespace DBus {\r
+\r
+const MiddlewareInfo DBusRuntime::middlewareInfo_("DBus", &DBusRuntime::getInstance);\r
+\r
+__attribute__((constructor)) void registerDBusMiddleware(void) {\r
+ Runtime::registerRuntimeLoader("DBus", &DBusRuntime::getInstance);\r
+}\r
+\r
+std::shared_ptr<Runtime> DBusRuntime::getInstance() {\r
+ static std::shared_ptr<Runtime> singleton_;\r
+ if(!singleton_) {\r
+ singleton_ = std::make_shared<DBusRuntime>();\r
+ }\r
+ return singleton_;\r
+}\r
+\r
+std::shared_ptr<Factory> DBusRuntime::createFactory() {\r
+ auto factory = std::make_shared<DBusFactory>(this->shared_from_this(), &middlewareInfo_);\r
+ return factory;\r
+}\r
+\r
+} // namespace DBus\r
+} // namespace CommonAPI\r
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public\r
+ * License, v. 2.0. If a copy of the MPL was not distributed with this\r
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\r
+#ifndef COMMONAPI_DBUS_DBUS_RUNTIME_H_\r
+#define COMMONAPI_DBUS_DBUS_RUNTIME_H_\r
+\r
+#include "CommonAPI/Runtime.h"\r
+\r
+#include "DBusFactory.h"\r
+\r
+namespace CommonAPI {\r
+namespace DBus {\r
+\r
+class DBusRuntime: public Runtime, public std::enable_shared_from_this<DBusRuntime> {\r
+ public:\r
+ static std::shared_ptr<Runtime> getInstance();\r
+\r
+ std::shared_ptr<Factory> createFactory();\r
+\r
+ static const MiddlewareInfo middlewareInfo_;\r
+};\r
+\r
+} // namespace DBus\r
+} // namespace CommonAPI\r
+\r
+\r
+extern "C" {\r
+\r
+CommonAPI::MiddlewareInfo middlewareInfo = CommonAPI::DBus::DBusRuntime::middlewareInfo_;\r
+\r
+}\r
+\r
+#endif // COMMONAPI_DBUS_DBUS_RUNTIME_H_\r
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_DBUS_SERIALIZABLE_ARGUMENTS_H_
+#define COMMONAPI_DBUS_SERIALIZABLE_ARGUMENTS_H_
+
+#include "DBusInputStream.h"
+#include "DBusOutputStream.h"
+
+namespace CommonAPI {
+namespace DBus {
+
+template <typename... _Arguments>
+struct DBusSerializableArguments;
+
+template <>
+struct DBusSerializableArguments<> {
+ static inline bool serialize(OutputStream& outputStream) {
+ return true;
+ }
+
+ static inline bool deserialize(DBusInputStream& inputStream) {
+ return true;
+ }
+};
+
+template <typename _ArgumentType>
+struct DBusSerializableArguments<_ArgumentType> {
+ static inline bool serialize(OutputStream& outputStream, const _ArgumentType& argument) {
+ outputStream << argument;
+ return !outputStream.hasError();
+ }
+
+ static inline bool deserialize(DBusInputStream& inputStream, _ArgumentType& argument) {
+ inputStream >> argument;
+ return !inputStream.hasError();
+ }
+};
+
+template <typename _ArgumentType, typename ... _Rest>
+struct DBusSerializableArguments<_ArgumentType, _Rest...> {
+ static inline bool serialize(OutputStream& outputStream, const _ArgumentType& argument, const _Rest&... rest) {
+ outputStream << argument;
+ const bool success = !outputStream.hasError();
+ return success ? DBusSerializableArguments<_Rest...>::serialize(outputStream, rest...) : false;
+ }
+
+ static inline bool deserialize(DBusInputStream& inputStream, _ArgumentType& argument, _Rest&... rest) {
+ inputStream >> argument;
+ const bool success = !inputStream.hasError();
+ return success ? DBusSerializableArguments<_Rest...>::deserialize(inputStream, rest...) : false;
+ }
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_SERIALIZABLE_ARGUMENTS_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public\r
+ * License, v. 2.0. If a copy of the MPL was not distributed with this\r
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\r
+#include <utility>\r
+#include <sstream>\r
+#include <iostream>\r
+#include <string>\r
+#include <tuple>\r
+#include <unistd.h>\r
+\r
+#include "DBusServiceRegistry.h"\r
+#include "DBusInputStream.h"\r
+#include "DBusDaemonProxy.h"\r
+#include "DBusConnection.h"\r
+#include "DBusUtils.h"\r
+\r
+\r
+namespace CommonAPI {\r
+namespace DBus {\r
+\r
+\r
+DBusServiceRegistry::DBusServiceRegistry(std::shared_ptr<DBusConnection> dbusConnection) :\r
+ dbusConnection_(dbusConnection),\r
+ ready(false),\r
+ serviceStatusEvent_(std::shared_ptr<DBusServiceRegistry>(this)),\r
+ readyPromise_(),\r
+ readyMutex_()\r
+{\r
+ readyFuture_ = readyPromise_.get_future();\r
+ cacheAllServices();\r
+ dbusNameOwnerChangedEventSubscription_ =\r
+ dbusConnection_->getDBusDaemonProxy()->getNameOwnerChangedEvent().subscribe(\r
+ std::bind(&DBusServiceRegistry::onDBusNameOwnerChangedEvent,\r
+ this,\r
+ std::placeholders::_1,\r
+ std::placeholders::_2,\r
+ std::placeholders::_3));\r
+ std::thread(std::bind(&DBusServiceRegistry::isReadyBlocking, this)).detach();\r
+}\r
+\r
+void DBusServiceRegistry::registerAvailabilityListener(const std::string& service, const std::function<void(bool)>& listener) {\r
+ availabilityCallbackList.insert({service, listener});\r
+\r
+}\r
+\r
+DBusServiceStatusEvent& DBusServiceRegistry::getServiceStatusEvent() {\r
+ return serviceStatusEvent_;\r
+}\r
+\r
+DBusServiceRegistry::~DBusServiceRegistry() {\r
+ dbusConnection_->getDBusDaemonProxy()->getNameOwnerChangedEvent().unsubscribe(dbusNameOwnerChangedEventSubscription_);\r
+}\r
+\r
+std::future<bool>& DBusServiceRegistry::getReadyFuture() {\r
+ return readyFuture_;\r
+}\r
+\r
+bool DBusServiceRegistry::isReadyBlocking() {\r
+ if (!ready) {\r
+ readyMutex_.lock();\r
+ auto status = readyFuture_.wait_for(std::chrono::seconds(5));\r
+ if (checkReady(status)) {\r
+ ready = true;\r
+ } else {\r
+ ready = true;\r
+ readyPromise_.set_value(true);\r
+ }\r
+ readyMutex_.unlock();\r
+ }\r
+ return ready;\r
+}\r
+\r
+bool DBusServiceRegistry::isReady() {\r
+ return ready;\r
+}\r
+\r
+std::vector<std::string> DBusServiceRegistry::getAvailableServiceInstances(const std::string& serviceInterfaceName,\r
+ const std::string& serviceDomainName) {\r
+ if (!isReadyBlocking()) {\r
+ return std::vector<std::string>();\r
+ }\r
+\r
+ if (serviceDomainName != "local" || !dbusConnection_->isConnected()) {\r
+ return std::vector<std::string>();\r
+ }\r
+\r
+ std::vector<std::string> addressesOfKnownServiceInstances;\r
+ auto knownServiceInstancesIteratorPair = dbusCachedProvidersForInterfaces_.equal_range(serviceInterfaceName);\r
+\r
+ while(knownServiceInstancesIteratorPair.first != knownServiceInstancesIteratorPair.second) {\r
+ const DBusServiceInstanceId dbusServiceInstanceId = knownServiceInstancesIteratorPair.first->second;\r
+ addressesOfKnownServiceInstances.push_back(findInstanceIdMapping(dbusServiceInstanceId));\r
+ ++knownServiceInstancesIteratorPair.first;\r
+ }\r
+\r
+ return addressesOfKnownServiceInstances;\r
+}\r
+\r
+void DBusServiceRegistry::onManagedPathsList(const CallStatus& status, DBusObjectToInterfaceDict managedObjects,\r
+ std::list<std::string>::iterator iter, std::shared_ptr<std::list<std::string>> list) {\r
+\r
+ auto objectPathIterator = managedObjects.begin();\r
+\r
+ while (objectPathIterator != managedObjects.end()) {\r
+ const std::string& serviceObjPath = objectPathIterator->first;\r
+ auto interfaceNameIterator = objectPathIterator->second.begin();\r
+\r
+ while (interfaceNameIterator != objectPathIterator->second.end()) {\r
+ const std::string& interfaceName = interfaceNameIterator->first;\r
+ dbusCachedProvidersForInterfaces_.insert( { interfaceName, { *iter, serviceObjPath } });\r
+ ++interfaceNameIterator;\r
+ }\r
+ ++objectPathIterator;\r
+ }\r
+\r
+ list->erase(iter);\r
+\r
+ if (list->size() == 0) {\r
+ readyMutex_.lock();\r
+ if (!ready) {\r
+ readyPromise_.set_value(true);\r
+ ready = true;\r
+ }\r
+ readyMutex_.unlock();\r
+ }\r
+}\r
+\r
+bool DBusServiceRegistry::isServiceInstanceAlive(const std::string& address) {\r
+ std::vector<std::string> parts = split(address, ':');\r
+ return isServiceInstanceAlive(parts[2], parts[1], parts[0]);\r
+}\r
+\r
+\r
+bool DBusServiceRegistry::isServiceInstanceAlive(const std::string& serviceInstanceID,\r
+ const std::string& serviceInterfaceName,\r
+ const std::string& serviceDomainName ) {\r
+ if (!isReadyBlocking()) {\r
+ return false;\r
+ }\r
+\r
+ if (serviceDomainName != "local" || !dbusConnection_->isConnected()) {\r
+ return false;\r
+ }\r
+\r
+ DBusServiceInstanceId serviceInstanceId = findInstanceIdMapping(serviceInstanceID);\r
+\r
+ auto knownInstancesForInterfaceIteratorPair = dbusCachedProvidersForInterfaces_.equal_range(serviceInterfaceName);\r
+\r
+ while(knownInstancesForInterfaceIteratorPair.first != knownInstancesForInterfaceIteratorPair.second) {\r
+ DBusServiceInstanceId knownServiceId = knownInstancesForInterfaceIteratorPair.first->second;\r
+ if(knownServiceId == serviceInstanceId) {\r
+ return true;\r
+ }\r
+ ++knownInstancesForInterfaceIteratorPair.first;\r
+ }\r
+\r
+ return false;\r
+}\r
+\r
+void DBusServiceRegistry::getManagedObjects(const std::string& dbusWellKnownBusName) {\r
+ auto callMessage = DBusMessage::createMethodCall(\r
+ dbusWellKnownBusName.c_str(),\r
+ "/",\r
+ "org.freedesktop.DBus.ObjectManager",\r
+ "GetManagedObjects",\r
+ "");\r
+ dbusConnection_->sendDBusMessageWithReplyAsync(\r
+ callMessage,\r
+ DBusProxyAsyncCallbackHandler<DBusObjectToInterfaceDict>::create(\r
+ std::bind(\r
+ &DBusServiceRegistry::onManagedPaths,\r
+ this,\r
+ std::placeholders::_1,\r
+ std::placeholders::_2,\r
+ dbusWellKnownBusName)), 100);\r
+\r
+}\r
+\r
+void DBusServiceRegistry::onManagedPaths(const CallStatus& status, DBusObjectToInterfaceDict managedObjects,\r
+ std::string dbusWellKnownBusName) {\r
+\r
+ auto objectPathIterator = managedObjects.begin();\r
+\r
+ while (objectPathIterator != managedObjects.end()) {\r
+ const std::string& serviceObjPath = objectPathIterator->first;\r
+ auto interfaceNameIterator = objectPathIterator->second.begin();\r
+\r
+ while (interfaceNameIterator != objectPathIterator->second.end()) {\r
+ const std::string& interfaceName = interfaceNameIterator->first;\r
+ dbusCachedProvidersForInterfaces_.insert( { interfaceName, { dbusWellKnownBusName, serviceObjPath } });\r
+ updateListeners(dbusWellKnownBusName, serviceObjPath, interfaceName, true);\r
+ ++interfaceNameIterator;\r
+ }\r
+\r
+ ++objectPathIterator;\r
+ }\r
+}\r
+\r
+void DBusServiceRegistry::updateListeners(const std::string& conName, const std::string& objName, const std::string& intName , bool available) {\r
+ auto found = availabilityCallbackList.equal_range(findCommonAPIAddressForDBusAddress(conName, objName, intName));\r
+ auto foundIter = found.first;\r
+ while (foundIter != found.second) {\r
+ foundIter->second(true);\r
+ foundIter++;\r
+ }\r
+\r
+}\r
+\r
+void DBusServiceRegistry::addProvidedServiceInstancesToCache(const std::string& dbusNames) {\r
+ getManagedObjects(dbusNames);\r
+}\r
+\r
+void DBusServiceRegistry::addProvidedServiceInstancesToCache(std::vector<std::string>& dbusNames) {\r
+\r
+ std::shared_ptr<std::list<std::string>> dbusList = std::make_shared<std::list<std::string>>(dbusNames.begin(), dbusNames.end());\r
+\r
+ auto iter = dbusList->begin();\r
+\r
+ while (iter != dbusList->end()) {\r
+\r
+ auto callMessage = DBusMessage::createMethodCall(\r
+ iter->c_str(),\r
+ "/",\r
+ "org.freedesktop.DBus.ObjectManager",\r
+ "GetManagedObjects",\r
+ "");\r
+ dbusConnection_->sendDBusMessageWithReplyAsync(\r
+ callMessage,\r
+ DBusProxyAsyncCallbackHandler<DBusObjectToInterfaceDict>::create(\r
+ std::bind(\r
+ &DBusServiceRegistry::onManagedPathsList,\r
+ this,\r
+ std::placeholders::_1,\r
+ std::placeholders::_2,\r
+ iter,\r
+ dbusList)), 10);\r
+ iter++;\r
+ }\r
+}\r
+\r
+\r
+DBusServiceInstanceId DBusServiceRegistry::findInstanceIdMapping(const std::string& instanceId) const {\r
+ DBusServiceInstanceId instanceDescriptor;\r
+ findFallbackInstanceIdMapping(instanceId, instanceDescriptor.first, instanceDescriptor.second);\r
+ return instanceDescriptor;\r
+}\r
+\r
+std::string DBusServiceRegistry::findInstanceIdMapping(const DBusServiceInstanceId& dbusInstanceId) const {\r
+ return findFallbackInstanceIdMapping(dbusInstanceId.first, dbusInstanceId.second);\r
+}\r
+\r
+inline const bool isServiceName(const std::string& name) {\r
+ return name[0] != ':';\r
+}\r
+\r
+void DBusServiceRegistry::onDBusNameOwnerChangedEvent(const std::string& affectedName,\r
+ const std::string& oldOwner,\r
+ const std::string& newOwner) {\r
+ if (isServiceName(affectedName)) {\r
+ if(!oldOwner.empty()) {\r
+ removeProvidedServiceInstancesFromCache(affectedName);\r
+ }\r
+\r
+ if (!newOwner.empty()) {\r
+ addProvidedServiceInstancesToCache(affectedName);\r
+ }\r
+ }\r
+}\r
+\r
+\r
+void DBusServiceRegistry::removeProvidedServiceInstancesFromCache(const std::string& dbusWellKnownBusName) {\r
+ auto providersForInterfacesIteratorPair = dbusCachedProvidersForInterfaces_.equal_range(dbusWellKnownBusName);\r
+\r
+ //Iteriere über (interfaceName, (serviceInstanceId))\r
+ while(providersForInterfacesIteratorPair.first != providersForInterfacesIteratorPair.second) {\r
+\r
+ DBusServiceInstanceId dbusInstanceId = providersForInterfacesIteratorPair.first->second;\r
+ if(dbusInstanceId.first == dbusWellKnownBusName) {\r
+ auto toErase = providersForInterfacesIteratorPair.first;\r
+ ++providersForInterfacesIteratorPair.first;\r
+ dbusCachedProvidersForInterfaces_.erase(toErase);\r
+ }\r
+\r
+ ++providersForInterfacesIteratorPair.first;\r
+ }\r
+}\r
+\r
+void DBusServiceRegistry::onListNames(const CommonAPI::CallStatus& callStatus, std::vector<std::string> existingBusConnections) {\r
+\r
+ if (callStatus == CallStatus::SUCCESS) {\r
+ std::vector<std::string> dbusLivingServiceBusNames;\r
+ for (const std::string& connectionName : existingBusConnections) {\r
+ const bool isWellKnownName = (connectionName[0] != ':');\r
+\r
+ if (isWellKnownName) {\r
+ dbusLivingServiceBusNames.push_back(connectionName);\r
+ }\r
+ }\r
+ addProvidedServiceInstancesToCache(dbusLivingServiceBusNames);\r
+ }\r
+}\r
+\r
+void DBusServiceRegistry::cacheAllServices() {\r
+ CommonAPI::CallStatus callStatus;\r
+ std::vector<std::string> existingBusConnections;\r
+ dbusConnection_->getDBusDaemonProxy()->listNames(callStatus, existingBusConnections);\r
+ onListNames(callStatus, existingBusConnections);\r
+}\r
+\r
+\r
+}// namespace DBus\r
+} // namespace CommonAPI\r
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public\r
+ * License, v. 2.0. If a copy of the MPL was not distributed with this\r
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\r
+#ifndef COMMONAPI_DBUS_DBUS_SERVICE_REGISTRY_H_\r
+#define COMMONAPI_DBUS_DBUS_SERVICE_REGISTRY_H_\r
+\r
+\r
+#include <CommonAPI/types.h>\r
+#include <CommonAPI/Attribute.h>\r
+\r
+#include "DBusConnection.h"\r
+\r
+#include <unordered_map>\r
+#include <map>\r
+#include <unordered_set>\r
+#include <string>\r
+#include <vector>\r
+#include <memory>\r
+#include <list>\r
+#include <mutex>\r
+\r
+namespace CommonAPI {\r
+namespace DBus {\r
+\r
+typedef Event<std::string, std::string, std::string> NameOwnerChangedEvent;\r
+\r
+typedef Event<std::string, std::string, std::string>::Subscription NameOwnerChangedEventSubscription;\r
+\r
+typedef std::pair<std::string, std::string> DBusServiceInstanceId;\r
+\r
+typedef std::unordered_map<std::string, int> PropertyDictStub;\r
+typedef std::unordered_map<std::string, PropertyDictStub> InterfaceToPropertyDict;\r
+typedef std::unordered_map<std::string, InterfaceToPropertyDict> DBusObjectToInterfaceDict;\r
+\r
+class DBusConnection;\r
+class DBusDaemonProxy;\r
+\r
+\r
+class DBusServiceRegistry {\r
+ public:\r
+ static constexpr const char* getManagedObjectsDBusSignature_ = "a{oa{sa{sv}}}";\r
+\r
+ DBusServiceRegistry() = delete;\r
+ DBusServiceRegistry(const DBusServiceRegistry&) = delete;\r
+ DBusServiceRegistry& operator=(const DBusServiceRegistry&) = delete;\r
+\r
+ DBusServiceRegistry(std::shared_ptr<DBusConnection> connection);\r
+ ~DBusServiceRegistry();\r
+\r
+ std::vector<std::string> getAvailableServiceInstances(const std::string& interfaceName,\r
+ const std::string& domainName = "local");\r
+\r
+ bool isServiceInstanceAlive(const std::string& instanceID,\r
+ const std::string& interfaceName,\r
+ const std::string& domainName = "local");\r
+\r
+ bool isServiceInstanceAlive(const std::string& address);\r
+\r
+ bool isReady();\r
+\r
+ bool isReadyBlocking();\r
+\r
+ void registerAvailabilityListener(const std::string& service, const std::function<void(bool)>& listener);\r
+\r
+ std::future<bool>& getReadyFuture();\r
+\r
+ DBusServiceStatusEvent& getServiceStatusEvent();\r
+\r
+ private:\r
+ void cacheAllServices();\r
+\r
+ void removeProvidedServiceInstancesFromCache(const std::string& serviceBusName);\r
+ void addProvidedServiceInstancesToCache(std::vector<std::string>& dbusNames);\r
+ void addProvidedServiceInstancesToCache(const std::string& dbusNames);\r
+ void addAllProvidedServiceInstancesToCache(const std::vector<std::string>& serviceBusNames);\r
+\r
+ void getManagedObjects(const std::string& serviceBusName);\r
+\r
+ void onDBusNameOwnerChangedEvent(const std::string& name, const std::string& oldOwner, const std::string& newOwner);\r
+\r
+ bool isRemoteServiceVersionMatchingLocalVersion(const std::string& serviceBusName, const std::string& serviceInterfaceName);\r
+ bool isServiceInstanceAliveHelper(const std::string& connectionName) const;\r
+\r
+ DBusServiceInstanceId findInstanceIdMapping(const std::string& instanceId) const;\r
+ std::string findInstanceIdMapping(const DBusServiceInstanceId& dbusInstanceId) const;\r
+\r
+ void onManagedPaths(const CallStatus& status, DBusObjectToInterfaceDict replyMessage, std::string dbusWellKnownBusName);\r
+ void onManagedPathsList(const CallStatus& status, DBusObjectToInterfaceDict managedObjects, std::list<std::string>::iterator iter, std::shared_ptr<std::list<std::string>> list);\r
+\r
+ std::multimap<std::string, DBusServiceInstanceId> dbusCachedProvidersForInterfaces_;\r
+\r
+ std::shared_ptr<DBusConnection> dbusConnection_;\r
+\r
+ std::unordered_multimap<std::string, std::function<void(bool)>> availabilityCallbackList;\r
+\r
+ bool ready;\r
+\r
+ void onListNames(const CommonAPI::CallStatus&, std::vector<std::string>);\r
+\r
+ NameOwnerChangedEvent::Subscription dbusNameOwnerChangedEventSubscription_;\r
+\r
+ void updateListeners(const std::string& conName, const std::string& objName, const std::string& intName , bool available);\r
+\r
+ mutable std::future<bool> readyFuture_;\r
+ mutable std::promise<bool> readyPromise_;\r
+\r
+ std::mutex readyMutex_;\r
+\r
+ DBusServiceStatusEvent serviceStatusEvent_;\r
+};\r
+\r
+\r
+} // namespace DBus\r
+} // namespace CommonAPI\r
+\r
+#endif // COMMONAPI_DBUS_DBUS_SERVICE_REGISTRY_H_\r
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "DBusServiceStatusEvent.h"
+#include "DBusServiceRegistry.h"
+#include <cassert>
+
+namespace CommonAPI {
+namespace DBus {
+
+DBusServiceStatusEvent::DBusServiceStatusEvent(std::shared_ptr<DBusServiceRegistry> registry) :
+ registry_(registry) {
+}
+
+void DBusServiceStatusEvent::onFirstListenerAdded(const std::string& serviceName, const Listener& listener) {
+ if (registry_) {
+ registry_->registerAvailabilityListener(serviceName, std::bind(
+ &DBusServiceStatusEvent::availabilityEvent,
+ this,
+ serviceName,
+ std::placeholders::_1));
+ }
+}
+
+void DBusServiceStatusEvent::availabilityEvent(const std::string& name, const bool& available) {
+
+ const AvailabilityStatus availabilityStatus = !available ? AvailabilityStatus::NOT_AVAILABLE :
+ AvailabilityStatus::AVAILABLE;
+ notifyListeners(name, availabilityStatus);
+}
+
+void DBusServiceStatusEvent::onListenerAdded(const std::string& name, const Listener& listener) {
+ if (registry_) {
+ const AvailabilityStatus availabilityStatus =
+ !registry_->isServiceInstanceAlive(name) ? AvailabilityStatus::NOT_AVAILABLE :
+ AvailabilityStatus::AVAILABLE;
+
+ notifyListeners(name, availabilityStatus);
+ }
+
+}
+
+} // namespace DBus
+} // namespace CommonAPI
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public\r
+ * License, v. 2.0. If a copy of the MPL was not distributed with this\r
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\r
+#ifndef COMMONAPI_DBUS_DBUS_SERVICE_STATUS_EVENT_H_\r
+#define COMMONAPI_DBUS_DBUS_SERVICE_STATUS_EVENT_H_\r
+\r
+#include "DBusMultiEvent.h"\r
+\r
+#include <CommonAPI/Event.h>\r
+#include <CommonAPI/types.h>\r
+\r
+#include <string>\r
+#include <memory>\r
+\r
+namespace CommonAPI {\r
+namespace DBus {\r
+\r
+\r
+class DBusServiceRegistry;\r
+\r
+class DBusServiceStatusEvent: public DBusMultiEvent<AvailabilityStatus> {\r
+ public:\r
+ DBusServiceStatusEvent(std::shared_ptr<DBusServiceRegistry> registry);\r
+\r
+ protected:\r
+ void onFirstListenerAdded(const std::string& serviceName, const Listener& listener);\r
+ void onListenerAdded(const std::string& serviceName, const Listener& listener);\r
+\r
+ private:\r
+ void availabilityEvent(const std::string& name, const bool& available);\r
+\r
+ std::shared_ptr<DBusServiceRegistry> registry_;\r
+};\r
+\r
+} // namespace DBus\r
+} // namespace CommonAPI\r
+\r
+#endif // COMMONAPI_DBUS_DBUS_SERVICE_STATUS_EVENT_H_\r
+\r
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "DBusStubAdapter.h"
+
+#include <dbus/dbus-protocol.h>
+
+#include <cassert>
+#include <functional>
+#include <sstream>
+
+namespace CommonAPI {
+namespace DBus {
+
+const std::string DBusStubAdapter::domain_ = "local";
+
+DBusStubAdapter::DBusStubAdapter(const std::string& dbusBusName,
+ const std::string& dbusObjectPath,
+ const std::string& interfaceName,
+ const std::shared_ptr<DBusProxyConnection>& dbusConnection) :
+ dbusBusName_(dbusBusName),
+ dbusObjectPath_(dbusObjectPath),
+ interfaceName_(interfaceName),
+ dbusConnection_(dbusConnection),
+ isInitialized_(false) {
+
+ assert(!dbusBusName_.empty());
+ assert(!interfaceName_.empty());
+ assert(!dbusObjectPath_.empty());
+ assert(dbusObjectPath_[0] == '/');
+ assert(!interfaceName.empty());
+ assert(dbusConnection_);
+}
+
+DBusStubAdapter::~DBusStubAdapter() {
+ assert(dbusConnection_);
+ assert(isInitialized_);
+
+ dbusConnection_->getDBusObjectManager()->unregisterInterfaceHandler(dbusIntrospectionInterfaceHandlerToken_);
+ dbusConnection_->getDBusObjectManager()->unregisterInterfaceHandler(dbusInterfaceHandlerToken_);
+}
+
+void DBusStubAdapter::init() {
+ dbusIntrospectionInterfaceHandlerToken_ = dbusConnection_->getDBusObjectManager()->registerInterfaceHandler(
+ dbusObjectPath_,
+ "org.freedesktop.DBus.Introspectable",
+ std::bind(&DBusStubAdapter::onIntrospectionInterfaceDBusMessage, this, std::placeholders::_1));
+
+ dbusInterfaceHandlerToken_ = dbusConnection_->getDBusObjectManager()->registerInterfaceHandler(
+ dbusObjectPath_,
+ interfaceName_,
+ std::bind(&DBusStubAdapter::onInterfaceDBusMessage, this, std::placeholders::_1));
+
+ isInitialized_ = true;
+}
+
+const std::string DBusStubAdapter::getAddress() const {
+ return domain_ + ":" + interfaceName_ + ":" + dbusBusName_;
+}
+
+const std::string& DBusStubAdapter::getDomain() const {
+ return domain_;
+}
+
+const std::string& DBusStubAdapter::getServiceId() const {
+ return interfaceName_;
+}
+
+const std::string& DBusStubAdapter::getInstanceId() const {
+ return dbusObjectPath_;
+}
+
+bool DBusStubAdapter::onIntrospectionInterfaceDBusMessage(const DBusMessage& dbusMessage) {
+ bool dbusMessageHandled = false;
+
+ if (dbusMessage.isMethodCallType() && dbusMessage.hasMemberName("Introspect")) {
+ std::stringstream xmlData(std::ios_base::out);
+ xmlData << "<!DOCTYPE node PUBLIC \"" DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER "\"\n\""
+ DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER"\">\n"
+ "<node name=\"" << dbusObjectPath_ << "\">\n"
+ "<interface name=\"org.freedesktop.DBus.Introspectable\">\n"
+ "<method name=\"Introspect\">\n"
+ "<arg type=\"s\" name=\"xml_data\" direction=\"out\"/>\n"
+ "</method>\n"
+ "</interface>\n"
+ "<interface name=\"" << interfaceName_ << "\">\n"
+ << getMethodsDBusIntrospectionXmlData() << "\n"
+ "</interface>\n"
+ "</node>";
+
+ DBusMessage dbusMessageReply = dbusMessage.createMethodReturn("s");
+ DBusOutputStream dbusOutputStream(dbusMessageReply);
+ dbusOutputStream << xmlData.str();
+ dbusOutputStream.flush();
+
+ dbusMessageHandled = dbusConnection_->sendDBusMessage(dbusMessageReply);
+ }
+
+ return dbusMessageHandled;
+}
+
+} // namespace dbus
+} // namespace CommonAPI
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_DBUS_DBUS_STUB_ADAPTER_H_
+#define COMMONAPI_DBUS_DBUS_STUB_ADAPTER_H_
+
+#include "DBusConnection.h"
+
+#include <CommonAPI/Stub.h>
+#include <CommonAPI/DBus/DBusMessage.h>
+
+#include <string>
+#include <memory>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusStubAdapter: virtual public CommonAPI::StubAdapter {
+ public:
+ DBusStubAdapter(const std::string& dbusBusName,
+ const std::string& dbusObjectPath,
+ const std::string& interfaceName,
+ const std::shared_ptr<DBusProxyConnection>& dbusConnection);
+
+ virtual ~DBusStubAdapter();
+
+ virtual void init();
+
+ virtual const std::string getAddress() const;
+ virtual const std::string& getDomain() const;
+ virtual const std::string& getServiceId() const;
+ virtual const std::string& getInstanceId() const;
+
+ inline const std::string& getObjectPath() const;
+
+ inline const std::shared_ptr<DBusProxyConnection>& getDBusConnection() const;
+
+ protected:
+ virtual const char* getMethodsDBusIntrospectionXmlData() const = 0;
+ virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage) = 0;
+
+ private:
+ bool onIntrospectionInterfaceDBusMessage(const DBusMessage& dbusMessage);
+
+ const std::string dbusBusName_;
+ const std::string dbusObjectPath_;
+ const std::string interfaceName_;
+ const std::shared_ptr<DBusProxyConnection> dbusConnection_;
+
+ bool isInitialized_;
+
+ DBusInterfaceHandlerToken dbusIntrospectionInterfaceHandlerToken_;
+ DBusInterfaceHandlerToken dbusInterfaceHandlerToken_;
+
+ static const std::string domain_;
+};
+
+const std::string& DBusStubAdapter::getObjectPath() const {
+ return dbusObjectPath_;
+}
+
+const std::shared_ptr<DBusProxyConnection>& DBusStubAdapter::getDBusConnection() const {
+ return dbusConnection_;
+}
+
+} // namespace dbus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_STUB_ADAPTER_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_
+#define COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_
+
+#include "DBusStubAdapter.h"
+#include "DBusInputStream.h"
+#include "DBusOutputStream.h"
+#include "DBusHelper.h"
+
+#include <iostream>
+#include <memory>
+#include <initializer_list>
+#include <tuple>
+#include <unordered_map>
+
+namespace CommonAPI {
+namespace DBus {
+
+template <typename _StubClass>
+class DBusStubAdapterHelper: public DBusStubAdapter, public std::enable_shared_from_this<typename _StubClass::StubAdapterType> {
+ public:
+ typedef typename _StubClass::StubAdapterType StubAdapterType;
+ typedef typename _StubClass::RemoteEventHandlerType RemoteEventHandlerType;
+
+ class StubDispatcher {
+ public:
+ virtual ~StubDispatcher() { }
+ virtual bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelper<_StubClass>& dbusStubAdapterHelper) = 0;
+ };
+
+ public:
+ DBusStubAdapterHelper(const std::string& dbusBusName,
+ const std::string& dbusObjectPath,
+ const std::string& interfaceName,
+ const std::shared_ptr<DBusProxyConnection>& dbusConnection,
+ std::shared_ptr<_StubClass> stub):
+ DBusStubAdapter(dbusBusName, dbusObjectPath, interfaceName, dbusConnection),
+ stub_(stub) {
+ }
+
+ virtual ~DBusStubAdapterHelper() { }
+
+ virtual void init() {
+ DBusStubAdapter::init();
+ remoteEventHandler_ = stub_->initStubAdapter(getStubAdapter());
+ }
+
+ inline std::shared_ptr<StubAdapterType> getStubAdapter() {
+ return this->shared_from_this();
+ }
+
+ inline const std::shared_ptr<_StubClass>& getStub() {
+ return stub_;
+ }
+
+ inline RemoteEventHandlerType* getRemoteEventHandler() {
+ return remoteEventHandler_;
+ }
+
+ protected:
+ // interfaceMemberName, interfaceMemberSignature
+ typedef std::pair<const char*, const char*> DBusInterfaceMemberPath;
+ typedef std::unordered_map<DBusInterfaceMemberPath, StubDispatcher*> StubDispatcherTable;
+
+ virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage) {
+ const char* interfaceMemberName = dbusMessage.getMemberName();
+ const char* interfaceMemberSignature = dbusMessage.getSignatureString();
+
+ assert(interfaceMemberName);
+ assert(interfaceMemberSignature);
+
+ DBusInterfaceMemberPath dbusInterfaceMemberPath(interfaceMemberName, interfaceMemberSignature);
+ auto findIterator = this->stubDispatcherTable_.find(dbusInterfaceMemberPath);
+ const bool foundInterfaceMemberHandler = (findIterator != this->stubDispatcherTable_.end());
+ bool dbusMessageHandled = false;
+
+ if (foundInterfaceMemberHandler) {
+ StubDispatcher* stubDispatcher = findIterator->second;
+ dbusMessageHandled = stubDispatcher->dispatchDBusMessage(dbusMessage, *this);
+ }
+
+ return dbusMessageHandled;
+ }
+
+ std::shared_ptr<_StubClass> stub_;
+ RemoteEventHandlerType* remoteEventHandler_;
+ static const StubDispatcherTable stubDispatcherTable_;
+};
+
+template< class >
+struct DBusStubSignalHelper;
+
+template<template<class ...> class _In, class... _InArgs>
+struct DBusStubSignalHelper<_In<_InArgs...>> {
+ template <typename _DBusStub = DBusStubAdapter>
+ static bool sendSignal(const _DBusStub& dbusStub,
+ const char* signalName,
+ const char* signalSignature,
+ const _InArgs&... inArgs) {
+ DBusMessage dbusMessage = DBusMessage::createSignal(
+ dbusStub.getObjectPath().c_str(),
+ dbusStub.getInterfaceName(),
+ signalName,
+ signalSignature);
+
+ if (sizeof...(_InArgs) > 0) {
+ DBusOutputStream outputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...);
+ if (!success) {
+ return false;
+ }
+ outputStream.flush();
+ }
+
+ const bool dbusMessageSent = dbusStub.getDBusConnection()->sendDBusMessage(dbusMessage);
+ return dbusMessageSent;
+ }
+};
+
+
+
+template< class, class >
+class DBusMethodStubDispatcher;
+
+template <
+ typename _StubClass,
+ template <class...> class _In, class... _InArgs>
+class DBusMethodStubDispatcher<_StubClass, _In<_InArgs...> >: public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
+ public:
+ typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
+ typedef void (_StubClass::*_StubFunctor)(_InArgs...);
+
+ DBusMethodStubDispatcher(_StubFunctor stubFunctor):
+ stubFunctor_(stubFunctor) {
+ }
+
+ bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ return handleDBusMessage(dbusMessage, dbusStubAdapterHelper, typename make_sequence<sizeof...(_InArgs)>::type());
+ }
+
+ private:
+ template <int... _InArgIndices, int... _OutArgIndices>
+ inline bool handleDBusMessage(const DBusMessage& dbusMessage,
+ DBusStubAdapterHelperType& dbusStubAdapterHelper,
+ index_sequence<_InArgIndices...>) const {
+ std::tuple<_InArgs...> argTuple;
+
+ if (sizeof...(_InArgs) > 0) {
+ DBusInputStream dbusInputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...);
+ if (!success)
+ return false;
+ }
+
+ (dbusStubAdapterHelper.getStub().get()->*stubFunctor_)(std::move(std::get<_InArgIndices>(argTuple))...);
+
+ return true;
+ }
+
+ _StubFunctor stubFunctor_;
+};
+
+
+template< class, class, class >
+class DBusMethodWithReplyStubDispatcher;
+
+template <
+ typename _StubClass,
+ template <class...> class _In, class... _InArgs,
+ template <class...> class _Out, class... _OutArgs>
+class DBusMethodWithReplyStubDispatcher<_StubClass, _In<_InArgs...>, _Out<_OutArgs...> >:
+ public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
+ public:
+ typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
+ typedef void (_StubClass::*_StubFunctor)(_InArgs..., _OutArgs&...);
+
+ DBusMethodWithReplyStubDispatcher(_StubFunctor stubFunctor, const char* dbusReplySignature):
+ stubFunctor_(stubFunctor),
+ dbusReplySignature_(dbusReplySignature) {
+ }
+
+ bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ return handleDBusMessage(
+ dbusMessage,
+ dbusStubAdapterHelper,
+ typename make_sequence_range<sizeof...(_InArgs), 0>::type(),
+ typename make_sequence_range<sizeof...(_OutArgs), sizeof...(_InArgs)>::type());
+ }
+
+ private:
+ template <int... _InArgIndices, int... _OutArgIndices>
+ inline bool handleDBusMessage(const DBusMessage& dbusMessage,
+ DBusStubAdapterHelperType& dbusStubAdapterHelper,
+ index_sequence<_InArgIndices...>,
+ index_sequence<_OutArgIndices...>) const {
+ std::tuple<_InArgs..., _OutArgs...> argTuple;
+
+ if (sizeof...(_InArgs) > 0) {
+ DBusInputStream dbusInputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...);
+ if (!success)
+ return false;
+ }
+
+ (dbusStubAdapterHelper.getStub().get()->*stubFunctor_)(std::move(std::get<_InArgIndices>(argTuple))..., std::get<_OutArgIndices>(argTuple)...);
+
+ DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(dbusReplySignature_);
+
+ if (sizeof...(_OutArgs) > 0) {
+ DBusOutputStream dbusOutputStream(dbusMessageReply);
+ const bool success = DBusSerializableArguments<_OutArgs...>::serialize(dbusOutputStream, std::get<_OutArgIndices>(argTuple)...);
+ if (!success)
+ return false;
+
+ dbusOutputStream.flush();
+ }
+
+ return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply);
+ }
+
+ _StubFunctor stubFunctor_;
+ const char* dbusReplySignature_;
+};
+
+
+template <typename _StubClass, typename _AttributeType>
+class DBusGetAttributeStubDispatcher: public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
+ public:
+ typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
+ typedef const _AttributeType& (_StubClass::*GetStubFunctor)();
+
+ DBusGetAttributeStubDispatcher(GetStubFunctor getStubFunctor, const char* dbusSignature):
+ getStubFunctor_(getStubFunctor),
+ dbusSignature_(dbusSignature) {
+ }
+
+ bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ return sendAttributeValueReply(dbusMessage, dbusStubAdapterHelper);
+ }
+
+ protected:
+ inline bool sendAttributeValueReply(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(dbusSignature_);
+ DBusOutputStream dbusOutputStream(dbusMessageReply);
+
+ dbusOutputStream << (dbusStubAdapterHelper.getStub().get()->*getStubFunctor_)();
+ dbusOutputStream.flush();
+
+ return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply);
+ }
+
+ GetStubFunctor getStubFunctor_;
+ const char* dbusSignature_;
+};
+
+
+template <typename _StubClass, typename _AttributeType>
+class DBusSetAttributeStubDispatcher: public DBusGetAttributeStubDispatcher<_StubClass, _AttributeType> {
+ public:
+ typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
+ typedef typename DBusStubAdapterHelperType::RemoteEventHandlerType RemoteEventHandlerType;
+
+ typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor;
+ typedef bool (RemoteEventHandlerType::*OnRemoteSetFunctor)(_AttributeType);
+ typedef void (RemoteEventHandlerType::*OnRemoteChangedFunctor)();
+
+ DBusSetAttributeStubDispatcher(GetStubFunctor getStubFunctor,
+ OnRemoteSetFunctor onRemoteSetFunctor,
+ OnRemoteChangedFunctor onRemoteChangedFunctor,
+ const char* dbusSignature) :
+ DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor, dbusSignature),
+ onRemoteSetFunctor_(onRemoteSetFunctor),
+ onRemoteChangedFunctor_(onRemoteChangedFunctor) {
+ }
+
+ bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ bool attributeValueChanged;
+
+ if (!setAttributeValue(dbusMessage, dbusStubAdapterHelper, attributeValueChanged))
+ return false;
+
+ if (attributeValueChanged)
+ notifyOnRemoteChanged(dbusStubAdapterHelper);
+
+ return true;
+ }
+
+ protected:
+ inline bool setAttributeValue(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper, bool& attributeValueChanged) {
+ DBusInputStream dbusInputStream(dbusMessage);
+ _AttributeType attributeValue;
+ dbusInputStream >> attributeValue;
+ if (dbusInputStream.hasError())
+ return false;
+
+ attributeValueChanged = (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteSetFunctor_)(std::move(attributeValue));
+
+ return this->sendAttributeValueReply(dbusMessage, dbusStubAdapterHelper);
+ }
+
+ inline void notifyOnRemoteChanged(DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteChangedFunctor_)();
+ }
+
+ inline const _AttributeType& getAttributeValue(DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ return (dbusStubAdapterHelper.getStub().get()->*(this->getStubFunctor_))();
+ }
+
+ const OnRemoteSetFunctor onRemoteSetFunctor_;
+ const OnRemoteChangedFunctor onRemoteChangedFunctor_;
+};
+
+
+template <typename _StubClass, typename _AttributeType>
+class DBusSetObservableAttributeStubDispatcher: public DBusSetAttributeStubDispatcher<_StubClass, _AttributeType> {
+ public:
+ typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
+ typedef typename DBusStubAdapterHelperType::StubAdapterType StubAdapterType;
+
+ typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor;
+ typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteSetFunctor OnRemoteSetFunctor;
+ typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteChangedFunctor OnRemoteChangedFunctor;
+ typedef void (StubAdapterType::*FireChangedFunctor)(const _AttributeType&);
+
+ DBusSetObservableAttributeStubDispatcher(GetStubFunctor getStubFunctor,
+ OnRemoteSetFunctor onRemoteSetFunctor,
+ OnRemoteChangedFunctor onRemoteChangedFunctor,
+ FireChangedFunctor fireChangedFunctor,
+ const char* dbusSignature) :
+ DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor,
+ onRemoteSetFunctor,
+ onRemoteChangedFunctor,
+ dbusSignature),
+ fireChangedFunctor_(fireChangedFunctor) {
+ }
+
+ bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ bool attributeValueChanged;
+ if (!this->setAttributeValue(dbusMessage, dbusStubAdapterHelper, attributeValueChanged))
+ return false;
+
+ if (attributeValueChanged) {
+ fireAttributeValueChanged(dbusStubAdapterHelper);
+ this->notifyOnRemoteChanged(dbusStubAdapterHelper);
+ }
+ return true;
+ }
+
+ private:
+ inline void fireAttributeValueChanged(DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ (dbusStubAdapterHelper.getStubAdapter().get()->*fireChangedFunctor_)(this->getAttributeValue(dbusStubAdapterHelper));
+ }
+
+ const FireChangedFunctor fireChangedFunctor_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef DBUSUTILS_H_
+#define DBUSUTILS_H_
+
+#include <algorithm>
+#include <string>
+#include <sstream>
+#include <vector>
+
+namespace CommonAPI {
+namespace DBus {
+
+inline std::vector<std::string>& split(const std::string& s, char delim, std::vector<std::string>& elems) {
+ std::istringstream ss(s);
+ std::string item;
+ while (std::getline(ss, item, delim)) {
+ elems.push_back(item);
+ }
+ return elems;
+}
+
+inline std::vector<std::string> split(const std::string& s, char delim) {
+ std::vector<std::string> elems;
+ return split(s, delim, elems);
+}
+
+inline void findFallbackInstanceIdMapping(const std::string& instanceId,
+ std::string& connectionName,
+ std::string& objectPath) {
+ connectionName = instanceId;
+ objectPath = '/' + instanceId;
+ std::replace(objectPath.begin(), objectPath.end(), '.', '/');
+}
+
+inline std::string findCommonAPIAddressForDBusAddress(const std::string& conName,
+ const std::string& objName,
+ const std::string& intName) {
+
+ return "local:" + intName + ":" + conName;
+}
+
+inline std::string findFallbackInstanceIdMapping(const std::string& connectionName, const std::string& objectPath) {
+ return connectionName;
+}
+
+template<typename _FutureWaitType>
+inline bool checkReady(_FutureWaitType&);
+
+template<>
+inline bool checkReady<bool>(bool& returnedValue) {
+ return returnedValue;
+}
+
+template<>
+inline bool checkReady<std::future_status>(std::future_status& returnedValue) {
+ return returnedValue == std::future_status::ready;
+}
+
+}
+}
+
+#endif /* DBUSUTILS_H_ */
--- /dev/null
+//-----------------------------------------------------------------------------\r
+// MurmurHash3 was written by Austin Appleby, and is placed in the public\r
+// domain. The author hereby disclaims copyright to this source code.\r
+\r
+// Note - The x86 and x64 versions do _not_ produce the same results, as the\r
+// algorithms are optimized for their respective platforms. You can still\r
+// compile and run any of them on any platform, but your performance with the\r
+// non-native version will be less than optimal.\r
+\r
+#include "MurmurHash3.h"\r
+\r
+//-----------------------------------------------------------------------------\r
+// Platform-specific functions and macros\r
+\r
+// Microsoft Visual Studio\r
+\r
+#if defined(_MSC_VER)\r
+\r
+#define FORCE_INLINE __forceinline\r
+\r
+#include <stdlib.h>\r
+\r
+#define ROTL32(x,y) _rotl(x,y)\r
+#define ROTL64(x,y) _rotl64(x,y)\r
+\r
+#define BIG_CONSTANT(x) (x)\r
+\r
+// Other compilers\r
+\r
+#else // defined(_MSC_VER)\r
+\r
+#define FORCE_INLINE __attribute__((always_inline))\r
+\r
+inline uint32_t rotl32 ( uint32_t x, int8_t r )\r
+{\r
+ return (x << r) | (x >> (32 - r));\r
+}\r
+\r
+inline uint64_t rotl64 ( uint64_t x, int8_t r )\r
+{\r
+ return (x << r) | (x >> (64 - r));\r
+}\r
+\r
+#define ROTL32(x,y) rotl32(x,y)\r
+#define ROTL64(x,y) rotl64(x,y)\r
+\r
+#define BIG_CONSTANT(x) (x##LLU)\r
+\r
+#endif // !defined(_MSC_VER)\r
+\r
+//-----------------------------------------------------------------------------\r
+// Block read - if your platform needs to do endian-swapping or can only\r
+// handle aligned reads, do the conversion here\r
+\r
+inline uint32_t getblock ( const uint32_t * p, int i )\r
+{\r
+ return p[i];\r
+}\r
+\r
+inline uint64_t getblock ( const uint64_t * p, int i )\r
+{\r
+ return p[i];\r
+}\r
+\r
+//-----------------------------------------------------------------------------\r
+// Finalization mix - force all bits of a hash block to avalanche\r
+\r
+inline uint32_t fmix ( uint32_t h )\r
+{\r
+ h ^= h >> 16;\r
+ h *= 0x85ebca6b;\r
+ h ^= h >> 13;\r
+ h *= 0xc2b2ae35;\r
+ h ^= h >> 16;\r
+\r
+ return h;\r
+}\r
+\r
+//----------\r
+\r
+inline uint64_t fmix ( uint64_t k )\r
+{\r
+ k ^= k >> 33;\r
+ k *= BIG_CONSTANT(0xff51afd7ed558ccd);\r
+ k ^= k >> 33;\r
+ k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);\r
+ k ^= k >> 33;\r
+\r
+ return k;\r
+}\r
+\r
+//-----------------------------------------------------------------------------\r
+\r
+void MurmurHash3_x86_32 ( const void * key, int len,\r
+ uint32_t seed, void * out )\r
+{\r
+ const uint8_t * data = (const uint8_t*)key;\r
+ const int nblocks = len / 4;\r
+\r
+ uint32_t h1 = seed;\r
+\r
+ uint32_t c1 = 0xcc9e2d51;\r
+ uint32_t c2 = 0x1b873593;\r
+\r
+ //----------\r
+ // body\r
+\r
+ const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);\r
+\r
+ for(int i = -nblocks; i; i++)\r
+ {\r
+ uint32_t k1 = getblock(blocks,i);\r
+\r
+ k1 *= c1;\r
+ k1 = ROTL32(k1,15);\r
+ k1 *= c2;\r
+ \r
+ h1 ^= k1;\r
+ h1 = ROTL32(h1,13); \r
+ h1 = h1*5+0xe6546b64;\r
+ }\r
+\r
+ //----------\r
+ // tail\r
+\r
+ const uint8_t * tail = (const uint8_t*)(data + nblocks*4);\r
+\r
+ uint32_t k1 = 0;\r
+\r
+ switch(len & 3)\r
+ {\r
+ case 3: k1 ^= tail[2] << 16;\r
+ case 2: k1 ^= tail[1] << 8;\r
+ case 1: k1 ^= tail[0];\r
+ k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;\r
+ };\r
+\r
+ //----------\r
+ // finalization\r
+\r
+ h1 ^= len;\r
+\r
+ h1 = fmix(h1);\r
+\r
+ *(uint32_t*)out = h1;\r
+} \r
+\r
+//-----------------------------------------------------------------------------\r
+\r
+void MurmurHash3_x86_128 ( const void * key, const int len,\r
+ uint32_t seed, void * out )\r
+{\r
+ const uint8_t * data = (const uint8_t*)key;\r
+ const int nblocks = len / 16;\r
+\r
+ uint32_t h1 = seed;\r
+ uint32_t h2 = seed;\r
+ uint32_t h3 = seed;\r
+ uint32_t h4 = seed;\r
+\r
+ uint32_t c1 = 0x239b961b; \r
+ uint32_t c2 = 0xab0e9789;\r
+ uint32_t c3 = 0x38b34ae5; \r
+ uint32_t c4 = 0xa1e38b93;\r
+\r
+ //----------\r
+ // body\r
+\r
+ const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);\r
+\r
+ for(int i = -nblocks; i; i++)\r
+ {\r
+ uint32_t k1 = getblock(blocks,i*4+0);\r
+ uint32_t k2 = getblock(blocks,i*4+1);\r
+ uint32_t k3 = getblock(blocks,i*4+2);\r
+ uint32_t k4 = getblock(blocks,i*4+3);\r
+\r
+ k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;\r
+\r
+ h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b;\r
+\r
+ k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;\r
+\r
+ h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747;\r
+\r
+ k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;\r
+\r
+ h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35;\r
+\r
+ k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;\r
+\r
+ h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;\r
+ }\r
+\r
+ //----------\r
+ // tail\r
+\r
+ const uint8_t * tail = (const uint8_t*)(data + nblocks*16);\r
+\r
+ uint32_t k1 = 0;\r
+ uint32_t k2 = 0;\r
+ uint32_t k3 = 0;\r
+ uint32_t k4 = 0;\r
+\r
+ switch(len & 15)\r
+ {\r
+ case 15: k4 ^= tail[14] << 16;\r
+ case 14: k4 ^= tail[13] << 8;\r
+ case 13: k4 ^= tail[12] << 0;\r
+ k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;\r
+\r
+ case 12: k3 ^= tail[11] << 24;\r
+ case 11: k3 ^= tail[10] << 16;\r
+ case 10: k3 ^= tail[ 9] << 8;\r
+ case 9: k3 ^= tail[ 8] << 0;\r
+ k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;\r
+\r
+ case 8: k2 ^= tail[ 7] << 24;\r
+ case 7: k2 ^= tail[ 6] << 16;\r
+ case 6: k2 ^= tail[ 5] << 8;\r
+ case 5: k2 ^= tail[ 4] << 0;\r
+ k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;\r
+\r
+ case 4: k1 ^= tail[ 3] << 24;\r
+ case 3: k1 ^= tail[ 2] << 16;\r
+ case 2: k1 ^= tail[ 1] << 8;\r
+ case 1: k1 ^= tail[ 0] << 0;\r
+ k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;\r
+ };\r
+\r
+ //----------\r
+ // finalization\r
+\r
+ h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;\r
+\r
+ h1 += h2; h1 += h3; h1 += h4;\r
+ h2 += h1; h3 += h1; h4 += h1;\r
+\r
+ h1 = fmix(h1);\r
+ h2 = fmix(h2);\r
+ h3 = fmix(h3);\r
+ h4 = fmix(h4);\r
+\r
+ h1 += h2; h1 += h3; h1 += h4;\r
+ h2 += h1; h3 += h1; h4 += h1;\r
+\r
+ ((uint32_t*)out)[0] = h1;\r
+ ((uint32_t*)out)[1] = h2;\r
+ ((uint32_t*)out)[2] = h3;\r
+ ((uint32_t*)out)[3] = h4;\r
+}\r
+\r
+//-----------------------------------------------------------------------------\r
+\r
+void MurmurHash3_x64_128 ( const void * key, const int len,\r
+ const uint32_t seed, void * out )\r
+{\r
+ const uint8_t * data = (const uint8_t*)key;\r
+ const int nblocks = len / 16;\r
+\r
+ uint64_t h1 = seed;\r
+ uint64_t h2 = seed;\r
+\r
+ uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);\r
+ uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);\r
+\r
+ //----------\r
+ // body\r
+\r
+ const uint64_t * blocks = (const uint64_t *)(data);\r
+\r
+ for(int i = 0; i < nblocks; i++)\r
+ {\r
+ uint64_t k1 = getblock(blocks,i*2+0);\r
+ uint64_t k2 = getblock(blocks,i*2+1);\r
+\r
+ k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;\r
+\r
+ h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;\r
+\r
+ k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;\r
+\r
+ h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;\r
+ }\r
+\r
+ //----------\r
+ // tail\r
+\r
+ const uint8_t * tail = (const uint8_t*)(data + nblocks*16);\r
+\r
+ uint64_t k1 = 0;\r
+ uint64_t k2 = 0;\r
+\r
+ switch(len & 15)\r
+ {\r
+ case 15: k2 ^= uint64_t(tail[14]) << 48;\r
+ case 14: k2 ^= uint64_t(tail[13]) << 40;\r
+ case 13: k2 ^= uint64_t(tail[12]) << 32;\r
+ case 12: k2 ^= uint64_t(tail[11]) << 24;\r
+ case 11: k2 ^= uint64_t(tail[10]) << 16;\r
+ case 10: k2 ^= uint64_t(tail[ 9]) << 8;\r
+ case 9: k2 ^= uint64_t(tail[ 8]) << 0;\r
+ k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;\r
+\r
+ case 8: k1 ^= uint64_t(tail[ 7]) << 56;\r
+ case 7: k1 ^= uint64_t(tail[ 6]) << 48;\r
+ case 6: k1 ^= uint64_t(tail[ 5]) << 40;\r
+ case 5: k1 ^= uint64_t(tail[ 4]) << 32;\r
+ case 4: k1 ^= uint64_t(tail[ 3]) << 24;\r
+ case 3: k1 ^= uint64_t(tail[ 2]) << 16;\r
+ case 2: k1 ^= uint64_t(tail[ 1]) << 8;\r
+ case 1: k1 ^= uint64_t(tail[ 0]) << 0;\r
+ k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;\r
+ };\r
+\r
+ //----------\r
+ // finalization\r
+\r
+ h1 ^= len; h2 ^= len;\r
+\r
+ h1 += h2;\r
+ h2 += h1;\r
+\r
+ h1 = fmix(h1);\r
+ h2 = fmix(h2);\r
+\r
+ h1 += h2;\r
+ h2 += h1;\r
+\r
+ ((uint64_t*)out)[0] = h1;\r
+ ((uint64_t*)out)[1] = h2;\r
+}\r
+\r
+//-----------------------------------------------------------------------------\r
+\r
--- /dev/null
+//-----------------------------------------------------------------------------\r
+// MurmurHash3 was written by Austin Appleby, and is placed in the public\r
+// domain. The author hereby disclaims copyright to this source code.\r
+\r
+#ifndef _MURMURHASH3_H_\r
+#define _MURMURHASH3_H_\r
+\r
+//-----------------------------------------------------------------------------\r
+// Platform-specific functions and macros\r
+\r
+// Microsoft Visual Studio\r
+\r
+#if defined(_MSC_VER)\r
+\r
+typedef unsigned char uint8_t;\r
+typedef unsigned long uint32_t;\r
+typedef unsigned __int64 uint64_t;\r
+\r
+// Other compilers\r
+\r
+#else // defined(_MSC_VER)\r
+\r
+#include <stdint.h>\r
+\r
+#endif // !defined(_MSC_VER)\r
+\r
+//-----------------------------------------------------------------------------\r
+\r
+void MurmurHash3_x86_32 ( const void * key, int len, uint32_t seed, void * out );\r
+\r
+void MurmurHash3_x86_128 ( const void * key, int len, uint32_t seed, void * out );\r
+\r
+void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * out );\r
+\r
+//-----------------------------------------------------------------------------\r
+\r
+#endif // _MURMURHASH3_H_\r
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include <CommonAPI/SerializableStruct.h>
+#include <CommonAPI/DBus/DBusInputStream.h>
+#include <CommonAPI/DBus/DBusOutputStream.h>
+
+#include <unordered_map>
+#include <bits/functional_hash.h>
+
+#include <gtest/gtest.h>
+
+#include <dbus/dbus.h>
+
+#include <chrono>
+#include <cstdint>
+#include <vector>
+#include <unordered_map>
+#include <bits/functional_hash.h>
+
+
+class BenchmarkingTest: public ::testing::Test {
+ protected:
+ DBusMessage* libdbusMessage;
+ DBusMessageIter libdbusMessageWriteIter;
+ size_t numOfElements;
+
+ void SetUp() {
+ numOfElements = 2;
+ libdbusMessage = dbus_message_new_method_call("no.bus.here", "/no/object/here", NULL, "noMethodHere");
+ ASSERT_TRUE(libdbusMessage != NULL);
+ dbus_message_iter_init_append(libdbusMessage, &libdbusMessageWriteIter);
+ }
+
+ void TearDown() {
+ dbus_message_unref(libdbusMessage);
+ }
+};
+
+template <typename _ArrayElementLibdbusType, typename _ArrayElementCommonApiType>
+void prepareLibdbusArray(DBusMessage* libdbusMessage,
+ const int arrayElementLibdbusType,
+ const char* arrayElementLibdbusTypeAsString,
+ const _ArrayElementLibdbusType& arrayInitElementValue,
+ const uint32_t arrayInitTime,
+ size_t& libdbusInitElementCount) {
+
+ DBusMessageIter libdbusMessageIter;
+ DBusMessageIter libdbusMessageContainerIter;
+
+ dbus_message_iter_init_append(libdbusMessage, &libdbusMessageIter);
+
+ dbus_bool_t libdbusSuccess = dbus_message_iter_open_container(&libdbusMessageIter,
+ DBUS_TYPE_ARRAY,
+ arrayElementLibdbusTypeAsString,
+ &libdbusMessageContainerIter);
+ ASSERT_TRUE(libdbusSuccess);
+
+
+ std::chrono::milliseconds libdbusInitTime;
+ std::chrono::time_point<std::chrono::high_resolution_clock> clockStart = std::chrono::high_resolution_clock::now();
+
+ do {
+ for (int i = 0; i < 1000; i++)
+ dbus_message_iter_append_basic(&libdbusMessageContainerIter,
+ arrayElementLibdbusType,
+ &arrayInitElementValue);
+
+ libdbusInitElementCount += 1000;
+
+ libdbusInitTime = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::high_resolution_clock::now() - clockStart);
+ } while (libdbusInitTime.count() < arrayInitTime);
+
+ libdbusSuccess = dbus_message_iter_close_container(&libdbusMessageIter, &libdbusMessageContainerIter);
+ ASSERT_TRUE(libdbusSuccess);
+
+ std::cout << "LibdbusInitTime = " << libdbusInitTime.count() << std::endl;
+ std::cout << "LibdbusInitElementCount = " << libdbusInitElementCount << std::endl;
+}
+
+
+template <typename _ArrayElementLibdbusType, typename _ArrayElementCommonApiType>
+void measureLibdbusArrayReadTime(DBusMessage* libdbusMessage,
+ size_t& libdbusInitElementCount,
+ std::chrono::milliseconds& libdbusArrayReadTime) {
+
+ DBusMessageIter libdbusMessageIter;
+ DBusMessageIter libdbusMessageContainerIter;
+
+ dbus_bool_t libdbusSuccess;
+
+ libdbusSuccess = dbus_message_iter_init(libdbusMessage, &libdbusMessageIter);
+ ASSERT_TRUE(libdbusSuccess);
+
+ dbus_message_iter_recurse(&libdbusMessageIter, &libdbusMessageContainerIter);
+
+ size_t libdbusReadElementCount = 0;
+ std::chrono::time_point<std::chrono::high_resolution_clock> clockStart = std::chrono::high_resolution_clock::now();
+
+ do {
+ _ArrayElementLibdbusType libdbusValue;
+
+ dbus_message_iter_get_basic(&libdbusMessageContainerIter, &libdbusValue);
+
+ ++libdbusReadElementCount;
+ } while (dbus_message_iter_next(&libdbusMessageContainerIter));
+
+ libdbusArrayReadTime = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::high_resolution_clock::now() - clockStart);
+
+ ASSERT_EQ(libdbusInitElementCount, libdbusReadElementCount);
+}
+
+
+template <typename _ArrayElementLibdbusType, typename _ArrayElementCommonApiType>
+void measureCommonApiArrayReadTime(DBusMessage* libdbusMessage,
+ std::chrono::milliseconds& commonArrayApiReadTime,
+ size_t& libdbusInitElementCount) {
+
+ CommonAPI::DBus::DBusMessage dbusMessage(libdbusMessage);
+ CommonAPI::DBus::DBusInputStream DBusInputStream(dbusMessage);
+ std::vector<_ArrayElementCommonApiType> commonApiVector;
+
+ std::chrono::time_point<std::chrono::high_resolution_clock> clockStart = std::chrono::high_resolution_clock::now();
+
+ DBusInputStream >> commonApiVector;
+
+ commonArrayApiReadTime = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::high_resolution_clock::now() - clockStart);
+
+ ASSERT_EQ(libdbusInitElementCount, commonApiVector.size());
+}
+
+
+template <typename _ArrayElementLibdbusType, typename _ArrayElementCommonApiType>
+void measureArrayReadTime(
+ const int arrayElementLibdbusType,
+ const char* arrayElementLibdbusTypeAsString,
+ const _ArrayElementLibdbusType arrayInitElementValue,
+ const uint32_t arrayInitTime,
+ std::chrono::milliseconds& libdbusArrayReadTime,
+ std::chrono::milliseconds& commonArrayApiReadTime) {
+
+ DBusMessage* libdbusMessage;
+ dbus_bool_t libdbusSuccess;
+ size_t libdbusInitElementCount = 0;
+
+ libdbusMessage = dbus_message_new_method_call("no.bus.here", "/no/object/here", NULL, "noMethodHere");
+ ASSERT_TRUE(libdbusMessage != NULL);
+
+ prepareLibdbusArray<_ArrayElementLibdbusType, _ArrayElementCommonApiType>(
+ libdbusMessage,
+ arrayElementLibdbusType,
+ arrayElementLibdbusTypeAsString,
+ arrayInitElementValue,
+ arrayInitTime,
+ libdbusInitElementCount);
+
+ measureLibdbusArrayReadTime<_ArrayElementLibdbusType, _ArrayElementCommonApiType>(
+ libdbusMessage,
+ libdbusInitElementCount,
+ libdbusArrayReadTime);
+
+ measureCommonApiArrayReadTime<_ArrayElementLibdbusType, _ArrayElementCommonApiType>(
+ libdbusMessage,
+ commonArrayApiReadTime,
+ libdbusInitElementCount);
+}
+
+
+TEST_F(BenchmarkingTest, InputStreamReadsIntegerArrayFasterThanLibdbus) {
+ std::chrono::milliseconds libdbusArrayReadTime;
+ std::chrono::milliseconds commonApiArrayReadTime;
+
+ measureArrayReadTime<int32_t, int32_t>(DBUS_TYPE_INT32,
+ DBUS_TYPE_INT32_AS_STRING,
+ 1234567890,
+ 1000,
+ libdbusArrayReadTime,
+ commonApiArrayReadTime);
+
+ RecordProperty("LibdbusArrayReadTime", libdbusArrayReadTime.count());
+ RecordProperty("CommonApiArrayReadTime", commonApiArrayReadTime.count());
+
+ std::cout << "LibdbusArrayReadTime = " << libdbusArrayReadTime.count() << std::endl;
+ std::cout << "CommonApiArrayReadTime = " << commonApiArrayReadTime.count() << std::endl;
+
+ ASSERT_LT(commonApiArrayReadTime.count(), libdbusArrayReadTime.count() * 0.30)
+ << "CommonAPI::DBus::DBusInputStream must be at least 70% faster than libdbus!";
+}
+
+TEST_F(BenchmarkingTest, InputStreamReadsStringArrayFasterThanLibdbus) {
+ std::chrono::milliseconds libdbusArrayReadTime;
+ std::chrono::milliseconds commonApiArrayReadTime;
+
+ measureArrayReadTime<char*, std::string>(DBUS_TYPE_STRING,
+ DBUS_TYPE_STRING_AS_STRING,
+ const_cast<char*>("01234567890123456789"),
+ 1000,
+ libdbusArrayReadTime,
+ commonApiArrayReadTime);
+
+ RecordProperty("LibdbusArrayReadTime", libdbusArrayReadTime.count());
+ RecordProperty("CommonApiArrayReadTime", commonApiArrayReadTime.count());
+
+ std::cout << "LibdbusArrayReadTime = " << libdbusArrayReadTime.count() << std::endl;
+ std::cout << "CommonApiArrayReadTime = " << commonApiArrayReadTime.count() << std::endl;
+
+ ASSERT_LT(commonApiArrayReadTime.count(), libdbusArrayReadTime.count() * 0.30)
+ << "CommonAPI::DBus::DBusInputStream must be at least 70% faster than libdbus!";
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <gtest/gtest.h>
+
+#include <cassert>
+#include <cstdint>
+#include <iostream>
+#include <functional>
+#include <memory>
+#include <stdint.h>
+#include <string>
+#include <utility>
+#include <tuple>
+#include <type_traits>
+
+#include <CommonAPI/types.h>
+#include <CommonAPI/AttributeExtension.h>
+#include <CommonAPI/Runtime.h>
+
+#include <CommonAPI/DBus/DBusConnection.h>
+#include <CommonAPI/DBus/DBusProxy.h>
+#include <CommonAPI/DBus/DBusRuntime.h>
+
+#include "commonapi/tests/PredefinedTypeCollection.h"
+#include "commonapi/tests/DerivedTypeCollection.h"
+#include "commonapi/tests/TestInterfaceProxy.h"
+#include "commonapi/tests/TestInterfaceStubDefault.h"
+#include "commonapi/tests/TestInterfaceDBusStubAdapter.h"
+
+#include "commonapi/tests/TestInterfaceDBusProxy.h"
+
+
+class DBusCommunicationTest: public ::testing::Test {
+ protected:
+ virtual void SetUp() {
+ runtime_ = CommonAPI::Runtime::load();
+ ASSERT_TRUE((bool)runtime_);
+ CommonAPI::DBus::DBusRuntime* dbusRuntime = dynamic_cast<CommonAPI::DBus::DBusRuntime*>(&(*runtime_));
+ ASSERT_TRUE(dbusRuntime != NULL);
+ }
+
+ virtual void TearDown() {
+ }
+
+ std::shared_ptr<CommonAPI::Runtime> runtime_;
+
+ static const std::string serviceAddress_;
+};
+
+const std::string DBusCommunicationTest::serviceAddress_ = "local:commonapi.tests.TestInterface:commonapi.tests.TestInterface";
+
+
+
+namespace myExtensions {
+
+template<typename _AttributeType>
+class AttributeTestExtension: public CommonAPI::AttributeExtension<_AttributeType> {
+ typedef CommonAPI::AttributeExtension<_AttributeType> __baseClass_t;
+
+public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+
+ AttributeTestExtension(_AttributeType& baseAttribute) :
+ CommonAPI::AttributeExtension<_AttributeType>(baseAttribute) {}
+
+ ~AttributeTestExtension() {}
+
+ bool testExtensionMethod() const {
+ return true;
+ }
+};
+
+} // namespace myExtensions
+
+//####################################################################################################################
+
+
+TEST_F(DBusCommunicationTest, RemoteMethodCallSucceeds) {
+ std::shared_ptr<CommonAPI::Factory> proxyFactory = runtime_->createFactory();
+ ASSERT_TRUE((bool)proxyFactory);
+
+ auto defaultTestProxy = proxyFactory->buildProxy<commonapi::tests::TestInterfaceProxy>(serviceAddress_);
+ ASSERT_TRUE((bool)defaultTestProxy);
+
+ std::shared_ptr<CommonAPI::Factory> stubFactory = runtime_->createFactory();
+ ASSERT_TRUE((bool)stubFactory);
+
+ auto stub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>();
+ bool success = stubFactory->registerService(stub, serviceAddress_);
+ ASSERT_TRUE(success);
+
+ uint32_t v1 = 5;
+ std::string v2 = "Hai :)";
+ CommonAPI::CallStatus stat;
+ defaultTestProxy->testVoidPredefinedTypeMethod(v1, v2, stat);
+
+ ASSERT_EQ(stat, CommonAPI::CallStatus::SUCCESS);
+}
+
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <common-api-dbus/dbus-connection.h>
+#include <common-api-dbus/dbus-output-message-stream.h>
+
+#include <gtest/gtest.h>
+
+#include <cstring>
+
+
+#define ASSERT_DBUSMESSAGE_EQ(_dbusMessage1, _dbusMessage2) \
+ ASSERT_FALSE(_dbusMessage1.getSignatureString() == NULL); \
+ ASSERT_FALSE(_dbusMessage2.getSignatureString() == NULL); \
+ ASSERT_STREQ(_dbusMessage1.getSignatureString(), _dbusMessage2.getSignatureString()); \
+ ASSERT_EQ(_dbusMessage1.getBodyLength(), _dbusMessage2.getBodyLength()); \
+ ASSERT_FALSE(_dbusMessage1.getBodyData() == NULL); \
+ ASSERT_FALSE(_dbusMessage2.getBodyData() == NULL); \
+ ASSERT_EQ(memcmp(_dbusMessage1.getBodyData(), _dbusMessage2.getBodyData(), _dbusMessage1.getBodyLength()), 0)
+
+
+namespace {
+
+class DBusConnectionTest: public ::testing::Test {
+ public:
+ void onConnectionStatusEvent(const common::api::AvailabilityStatus& newConnectionStatus) {
+ connectionStatusEventCount_++;
+ connectionStatus_ = newConnectionStatus;
+ }
+
+ bool onInterfaceHandlerDBusMessageReply(const common::api::dbus::DBusMessage& dbusMessage,
+ const std::shared_ptr<common::api::dbus::DBusConnection>& dbusConnection) {
+ interfaceHandlerDBusMessageCount_++;
+ interfaceHandlerDBusMessage_ = dbusMessage;
+ interfaceHandlerDBusMessageReply_ = dbusMessage.createMethodReturn("si");
+
+ common::api::dbus::DBusOutputMessageStream dbusOutputMessageStream(interfaceHandlerDBusMessageReply_);
+ dbusOutputMessageStream << "This is a default message reply!" << interfaceHandlerDBusMessageCount_;
+ dbusOutputMessageStream.flush();
+
+ dbusConnection->sendDBusMessage(interfaceHandlerDBusMessageReply_);
+
+ return true;
+ }
+
+ void onDBusMessageHandler(const common::api::dbus::DBusMessage& dbusMessage) {
+ dbusMessageHandlerCount_++;
+ dbusMessageHandlerDBusMessage_ = dbusMessage;
+ }
+
+ protected:
+ virtual void SetUp() {
+ dbusConnection_ = common::api::dbus::DBusConnection::getSessionBus();
+ connectionStatusEventCount_ = 0;
+ interfaceHandlerDBusMessageCount_ = 0;
+ dbusMessageHandlerCount_ = 0;
+ }
+
+ virtual void TearDown() {
+ if (dbusConnection_ && dbusConnection_->isConnected())
+ dbusConnection_->disconnect();
+
+ // reset DBusMessage
+ interfaceHandlerDBusMessage_ = common::api::dbus::DBusMessage();
+ interfaceHandlerDBusMessageReply_ = common::api::dbus::DBusMessage();
+
+ dbusMessageHandlerDBusMessage_ = common::api::dbus::DBusMessage();
+ }
+
+
+ std::shared_ptr<common::api::dbus::DBusConnection> dbusConnection_;
+
+ uint32_t connectionStatusEventCount_;
+ common::api::AvailabilityStatus connectionStatus_;
+
+ uint32_t interfaceHandlerDBusMessageCount_;
+ common::api::dbus::DBusMessage interfaceHandlerDBusMessage_;
+ common::api::dbus::DBusMessage interfaceHandlerDBusMessageReply_;
+
+ uint32_t dbusMessageHandlerCount_;
+ common::api::dbus::DBusMessage dbusMessageHandlerDBusMessage_;
+};
+
+
+TEST_F(DBusConnectionTest, IsInitiallyDisconnected) {
+ ASSERT_FALSE(dbusConnection_->isConnected());
+}
+
+TEST_F(DBusConnectionTest, ConnectAndDisconnectWork) {
+ ASSERT_TRUE(dbusConnection_->connect());
+ ASSERT_TRUE(dbusConnection_->isConnected());
+
+ dbusConnection_->disconnect();
+ ASSERT_FALSE(dbusConnection_->isConnected());
+}
+
+TEST_F(DBusConnectionTest, ConnectionStatusEventWorks) {
+ ASSERT_EQ(connectionStatusEventCount_, 0);
+
+ auto connectionStatusSubscription = dbusConnection_->getConnectionStatusEvent().subscribe(std::bind(
+ &DBusConnectionTest::onConnectionStatusEvent,
+ this,
+ std::placeholders::_1));
+
+ ASSERT_FALSE(dbusConnection_->isConnected());
+ ASSERT_EQ(connectionStatusEventCount_, 0);
+
+ uint32_t expectedEventCount = 0;
+ while (expectedEventCount < 10) {
+ ASSERT_TRUE(dbusConnection_->connect());
+ ASSERT_TRUE(dbusConnection_->isConnected());
+ ASSERT_EQ(connectionStatusEventCount_, ++expectedEventCount);
+ ASSERT_EQ(connectionStatus_, common::api::AvailabilityStatus::AVAILABLE);
+
+ dbusConnection_->disconnect();
+ ASSERT_FALSE(dbusConnection_->isConnected());
+ ASSERT_EQ(connectionStatusEventCount_, ++expectedEventCount);
+ ASSERT_EQ(connectionStatus_, common::api::AvailabilityStatus::NOT_AVAILABLE);
+ }
+
+ dbusConnection_->getConnectionStatusEvent().unsubscribe(connectionStatusSubscription);
+ ASSERT_EQ(connectionStatusEventCount_, expectedEventCount);
+
+ ASSERT_TRUE(dbusConnection_->connect());
+ ASSERT_TRUE(dbusConnection_->isConnected());
+ ASSERT_EQ(connectionStatusEventCount_, expectedEventCount);
+
+ dbusConnection_->disconnect();
+ ASSERT_FALSE(dbusConnection_->isConnected());
+ ASSERT_EQ(connectionStatusEventCount_, expectedEventCount);
+}
+
+TEST_F(DBusConnectionTest, SendingAsyncDBusMessagesWorks) {
+ const char* busName = "common.api.dbus.test.TestInterfaceHandler";
+ const char* objectPath = "/common/api/dbus/test/TestObject";
+ const char* interfaceName = "common.api.dbus.test.TestInterface";
+ const char* methodName = "TestMethod";
+
+ auto interfaceHandlerDBusConnection = common::api::dbus::DBusConnection::getSessionBus();
+
+ ASSERT_TRUE(interfaceHandlerDBusConnection->connect());
+ ASSERT_TRUE(interfaceHandlerDBusConnection->requestServiceNameAndBlock(busName));
+
+ auto interfaceHandlerToken = interfaceHandlerDBusConnection->registerInterfaceHandler(
+ objectPath,
+ interfaceName,
+ std::bind(&DBusConnectionTest::onInterfaceHandlerDBusMessageReply,
+ this,
+ std::placeholders::_1,
+ interfaceHandlerDBusConnection));
+
+
+ ASSERT_TRUE(dbusConnection_->connect());
+
+ for (uint32_t expectedDBusMessageCount = 1; expectedDBusMessageCount <= 10; expectedDBusMessageCount++) {
+ auto dbusMessageCall = common::api::dbus::DBusMessage::createMethodCall(
+ busName,
+ objectPath,
+ interfaceName,
+ methodName,
+ "si");
+ ASSERT_TRUE(dbusMessageCall);
+
+ common::api::dbus::DBusOutputMessageStream dbusOutputMessageStream(dbusMessageCall);
+ dbusOutputMessageStream << "This is a test async call"
+ << expectedDBusMessageCount;
+ dbusOutputMessageStream.flush();
+
+ dbusConnection_->sendDBusMessageWithReplyAsync(
+ dbusMessageCall,
+ std::bind(&DBusConnectionTest::onDBusMessageHandler, this, std::placeholders::_1));
+
+ for (int i = 0; i < 10 && interfaceHandlerDBusMessageCount_ < expectedDBusMessageCount; i++)
+ interfaceHandlerDBusConnection->readWriteDispatch(100);
+
+ ASSERT_EQ(interfaceHandlerDBusMessageCount_, expectedDBusMessageCount);
+ ASSERT_DBUSMESSAGE_EQ(dbusMessageCall, interfaceHandlerDBusMessage_);
+
+ for (int i = 0; i < 10 && dbusMessageHandlerCount_ < expectedDBusMessageCount; i++)
+ dbusConnection_->readWriteDispatch(100);
+
+ ASSERT_EQ(dbusMessageHandlerCount_, expectedDBusMessageCount);
+ ASSERT_DBUSMESSAGE_EQ(dbusMessageHandlerDBusMessage_, interfaceHandlerDBusMessageReply_);
+ }
+
+ dbusConnection_->disconnect();
+
+
+ interfaceHandlerDBusConnection->unregisterInterfaceHandler(interfaceHandlerToken);
+
+ ASSERT_TRUE(interfaceHandlerDBusConnection->releaseServiceName(busName));
+ interfaceHandlerDBusConnection->disconnect();
+}
+
+} // namespace
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include <CommonAPI/DBus/DBusConnection.h>
+#include <CommonAPI/DBus/DBusDaemonProxy.h>
+
+#include <gtest/gtest.h>
+
+#include <future>
+#include <tuple>
+
+namespace {
+
+void dispatch(std::shared_ptr<CommonAPI::DBus::DBusConnection> dbusConnection) {
+ while (dbusConnection->readWriteDispatch(10)) {}
+}
+
+class DBusDaemonProxyTest: public ::testing::Test {
+ protected:
+
+ std::thread* thread;
+
+ virtual void SetUp() {
+ dbusConnection_ = CommonAPI::DBus::DBusConnection::getSessionBus();
+ ASSERT_TRUE(dbusConnection_->connect());
+ thread = new std::thread(dispatch, dbusConnection_);
+ thread->detach();
+ //readWriteDispatchCount_ = 0;
+ }
+
+ virtual void TearDown() {
+ delete thread;
+ if (dbusConnection_ && dbusConnection_->isConnected()) {
+ //dbusConnection_->disconnect();
+ }
+ }
+
+ /*bool doReadWriteDispatch(int timeoutMilliseconds = 100) {
+ readWriteDispatchCount_++;
+ return dbusConnection_->readWriteDispatch(timeoutMilliseconds);
+ }*/
+
+ std::shared_ptr<CommonAPI::DBus::DBusConnection> dbusConnection_;
+ //size_t readWriteDispatchCount_;
+};
+
+TEST_F(DBusDaemonProxyTest, ListNames) {
+ std::vector<std::string> busNames;
+ CommonAPI::CallStatus callStatus;
+
+ dbusConnection_->getDBusDaemonProxy()->listNames(callStatus, busNames);
+ ASSERT_EQ(callStatus, CommonAPI::CallStatus::SUCCESS);
+
+ ASSERT_GT(busNames.size(), 0);
+ for (const std::string& busName : busNames) {
+ ASSERT_FALSE(busName.empty());
+ ASSERT_GT(busName.length(), 1);
+ }
+}
+
+TEST_F(DBusDaemonProxyTest, ListNamesAsync) {
+ std::promise<std::tuple<CommonAPI::CallStatus, std::vector<std::string>>> promise;
+ auto future = promise.get_future();
+
+ auto callStatusFuture = dbusConnection_->getDBusDaemonProxy()->listNamesAsync(
+ [&](const CommonAPI::CallStatus& callStatus, std::vector<std::string> busNames) {
+ promise.set_value(std::tuple<CommonAPI::CallStatus, std::vector<std::string>>(callStatus, std::move(busNames)));
+ });
+
+ ASSERT_EQ(future.wait_for(std::chrono::milliseconds(200)), std::future_status::ready);
+
+ ASSERT_EQ(callStatusFuture.get(), CommonAPI::CallStatus::SUCCESS);
+
+ auto futureResult = future.get();
+ const CommonAPI::CallStatus& callStatus = std::get<0>(futureResult);
+ const std::vector<std::string>& busNames = std::get<1>(futureResult);
+
+ ASSERT_EQ(callStatus, CommonAPI::CallStatus::SUCCESS);
+
+ ASSERT_GT(busNames.size(), 0);
+ for (const std::string& busName : busNames) {
+ ASSERT_FALSE(busName.empty());
+ ASSERT_GT(busName.length(), 1);
+ }
+}
+
+TEST_F(DBusDaemonProxyTest, NameHasOwner) {
+ bool nameHasOwner;
+ CommonAPI::CallStatus callStatus;
+
+ dbusConnection_->getDBusDaemonProxy()->nameHasOwner("org.freedesktop.DBus", callStatus, nameHasOwner);
+ ASSERT_EQ(callStatus, CommonAPI::CallStatus::SUCCESS);
+ ASSERT_TRUE(nameHasOwner);
+
+ dbusConnection_->getDBusDaemonProxy()->nameHasOwner("org.freedesktop.DBus.InvalidName.XXYYZZ", callStatus, nameHasOwner);
+ ASSERT_EQ(callStatus, CommonAPI::CallStatus::SUCCESS);
+ ASSERT_FALSE(nameHasOwner);
+}
+
+TEST_F(DBusDaemonProxyTest, NameHasOwnerAsync) {
+ std::promise<std::tuple<CommonAPI::CallStatus, bool>> promise;
+ auto future = promise.get_future();
+
+ auto callStatusFuture = dbusConnection_->getDBusDaemonProxy()->nameHasOwnerAsync(
+ "org.freedesktop.DBus",
+ [&](const CommonAPI::CallStatus& callStatus, bool nameHasOwner) {
+ promise.set_value(std::tuple<CommonAPI::CallStatus, bool>(callStatus, std::move(nameHasOwner)));
+ });
+
+ //while (readWriteDispatchCount_ < 5) {
+ // ASSERT_TRUE(doReadWriteDispatch());
+ //if (callStatusFuture.wait_for(std::chrono::milliseconds(100)) == std::future_status::ready)
+ // break;
+ //}
+ //ASSERT_NE(readWriteDispatchCount_, 5);
+ ASSERT_EQ(future.wait_for(std::chrono::milliseconds(100)), std::future_status::ready);
+
+ ASSERT_EQ(callStatusFuture.get(), CommonAPI::CallStatus::SUCCESS);
+
+ auto futureResult = future.get();
+ const CommonAPI::CallStatus& callStatus = std::get<0>(futureResult);
+ const bool& nameHasOwner = std::get<1>(futureResult);
+
+ ASSERT_EQ(callStatus, CommonAPI::CallStatus::SUCCESS);
+ ASSERT_TRUE(nameHasOwner);
+}
+
+TEST_F(DBusDaemonProxyTest, NameOwnerChangedEvent) {
+ std::promise<bool> promise;
+ auto future = promise.get_future();
+
+ dbusConnection_->getDBusDaemonProxy()->getNameOwnerChangedEvent().subscribe(
+ [&](const std::string& name, const std::string& oldOwner, const std::string& newOwner) {
+ static bool promiseIsSet = false;
+ if(!promiseIsSet) {
+ promiseIsSet = true;
+ promise.set_value(!name.empty() && (!oldOwner.empty() || !newOwner.empty()));
+ }
+ });
+
+ // Trigger NameOwnerChanged using a new DBusConnection
+ ASSERT_TRUE(CommonAPI::DBus::DBusConnection::getSessionBus()->connect());
+
+ //while (readWriteDispatchCount_ < 5) {
+ // ASSERT_TRUE(doReadWriteDispatch());
+ //if (future.wait_for(std::chrono::milliseconds(100)) == std::future_status::ready)
+ // break;
+ //}
+
+ //ASSERT_NE(readWriteDispatchCount_, 5);
+ ASSERT_TRUE(future.get());
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <gtest/gtest.h>
+
+#include <cassert>
+#include <cstdint>
+#include <iostream>
+#include <functional>
+#include <memory>
+#include <stdint.h>
+#include <string>
+#include <utility>
+#include <tuple>
+#include <type_traits>
+
+#include <CommonAPI/types.h>
+#include <CommonAPI/AttributeExtension.h>
+#include <CommonAPI/Runtime.h>
+
+#include <CommonAPI/DBus/DBusConnection.h>
+#include <CommonAPI/DBus/DBusProxy.h>
+#include <CommonAPI/DBus/DBusRuntime.h>
+
+#include "commonapi/tests/PredefinedTypeCollection.h"
+#include "commonapi/tests/DerivedTypeCollection.h"
+#include "commonapi/tests/TestInterfaceProxy.h"
+#include "commonapi/tests/TestInterfaceStubDefault.h"
+#include "commonapi/tests/TestInterfaceDBusStubAdapter.h"
+
+#include "commonapi/tests/TestInterfaceDBusProxy.h"
+
+std::shared_ptr<CommonAPI::Runtime> runtime_;
+std::shared_ptr<CommonAPI::Factory> proxyFactory;
+
+class DBusProxyFactoryTest: public ::testing::Test {
+ protected:
+ virtual void SetUp() {
+ if(!runtime_) {
+ runtime_ = CommonAPI::Runtime::load();
+
+ }
+ ASSERT_TRUE((bool)runtime_);
+ CommonAPI::DBus::DBusRuntime* dbusRuntime = dynamic_cast<CommonAPI::DBus::DBusRuntime*>(&(*runtime_));
+ ASSERT_TRUE(dbusRuntime != NULL);
+ }
+
+ virtual void TearDown() {
+ }
+};
+
+
+
+namespace myExtensions {
+
+template<typename _AttributeType>
+class AttributeTestExtension: public CommonAPI::AttributeExtension<_AttributeType> {
+ typedef CommonAPI::AttributeExtension<_AttributeType> __baseClass_t;
+
+public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+
+ AttributeTestExtension(_AttributeType& baseAttribute) :
+ CommonAPI::AttributeExtension<_AttributeType>(baseAttribute) {}
+
+ ~AttributeTestExtension() {}
+
+ bool testExtensionMethod() const {
+ return true;
+ }
+};
+
+} // namespace myExtensions
+
+//####################################################################################################################
+
+TEST_F(DBusProxyFactoryTest, DBusFactoryCanBeCreated) {
+ proxyFactory = runtime_->createFactory();
+ ASSERT_TRUE((bool)proxyFactory);
+ CommonAPI::DBus::DBusFactory* dbusProxyFactory = dynamic_cast<CommonAPI::DBus::DBusFactory*>(&(*proxyFactory));
+ ASSERT_TRUE(dbusProxyFactory != NULL);
+}
+
+TEST_F(DBusProxyFactoryTest, CreatesDefaultTestProxy) {
+ ASSERT_TRUE((bool)proxyFactory);
+ auto defaultTestProxy = proxyFactory->buildProxy<commonapi::tests::TestInterfaceProxy>("local:commonapi.tests.TestInterface:commonapi.tests.TestInterface");
+ ASSERT_TRUE((bool)defaultTestProxy);
+}
+
+TEST_F(DBusProxyFactoryTest, CreatesDefaultExtendedTestProxy) {
+ ASSERT_TRUE((bool)proxyFactory);
+ auto defaultTestProxy = proxyFactory->buildProxyWithDefaultAttributeExtension<
+ commonapi::tests::TestInterfaceProxy,
+ myExtensions::AttributeTestExtension>("local:commonapi.tests.TestInterface:commonapi.tests.TestInterface");
+ ASSERT_TRUE((bool)defaultTestProxy);
+}
+
+TEST_F(DBusProxyFactoryTest, CreatesIndividuallyExtendedTestProxy) {
+ ASSERT_TRUE((bool)proxyFactory);
+ auto specificAttributeExtendedTestProxy = proxyFactory->buildProxy<
+ commonapi::tests::TestInterfaceProxy,
+ commonapi::tests::TestInterfaceExtensions::TestDerivedArrayAttributeAttributeExtension<myExtensions::AttributeTestExtension> >
+ ("local:commonapi.tests.TestInterface:commonapi.tests.TestInterface");
+
+ ASSERT_TRUE((bool)specificAttributeExtendedTestProxy);
+
+ auto attributeExtension = specificAttributeExtendedTestProxy->getTestDerivedArrayAttributeAttributeExtension();
+ ASSERT_TRUE(attributeExtension.testExtensionMethod());
+}
+
+TEST_F(DBusProxyFactoryTest, HandlesRegistrationOfStubAdapters) {
+ ASSERT_TRUE((bool)proxyFactory);
+
+ const std::string serviceAddress = "local:commonapi.tests.TestInterface:commonapi.tests.TestInterface";
+
+ auto myStub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>();
+ bool success = proxyFactory->registerService(myStub, serviceAddress);
+ ASSERT_TRUE(success);
+
+ success = proxyFactory->unregisterService("SomeOther:Unknown:Service");
+ ASSERT_FALSE(success);
+
+ success = proxyFactory->unregisterService(serviceAddress);
+ ASSERT_TRUE(success);
+}
+
+TEST_F(DBusProxyFactoryTest, GracefullyHandlesWrongAddresses) {
+ ASSERT_TRUE((bool)proxyFactory);
+ auto myStub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>();
+
+ ASSERT_FALSE(proxyFactory->registerService(myStub, ""));
+ ASSERT_FALSE(proxyFactory->registerService(myStub, "too:much:stuff:here"));
+}
+
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include <CommonAPI/SerializableStruct.h>
+#include <CommonAPI/DBus/DBusInputStream.h>
+#include <CommonAPI/DBus/DBusOutputStream.h>
+
+#include <unordered_map>
+#include <bits/functional_hash.h>
+
+#include <gtest/gtest.h>
+
+#include <dbus/dbus.h>
+
+#include <chrono>
+#include <cstdint>
+#include <vector>
+#include <unordered_map>
+#include <bits/functional_hash.h>
+
+
+class InputStreamTest: public ::testing::Test {
+ protected:
+ DBusMessage* libdbusMessage;
+ DBusMessageIter libdbusMessageWriteIter;
+ size_t numOfElements;
+
+ void SetUp() {
+ numOfElements = 2;
+ libdbusMessage = dbus_message_new_method_call("no.bus.here", "/no/object/here", NULL, "noMethodHere");
+ ASSERT_TRUE(libdbusMessage != NULL);
+ dbus_message_iter_init_append(libdbusMessage, &libdbusMessageWriteIter);
+ }
+
+ void TearDown() {
+ dbus_message_unref(libdbusMessage);
+ }
+};
+
+TEST_F(InputStreamTest, CanBeConstructed) {
+ CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage);
+ CommonAPI::DBus::DBusInputStream inStream(scopedMessage);
+}
+
+TEST_F(InputStreamTest, ReadsEmptyMessages) {
+ CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage);
+ CommonAPI::DBus::DBusInputStream inStream(scopedMessage);
+
+ EXPECT_EQ(0, scopedMessage.getBodyLength());
+}
+
+TEST_F(InputStreamTest, ReadsBytes) {
+ uint8_t val = 0xff;
+ for (int i = 0; i < numOfElements; i += 1) {
+ dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_BYTE, &val);
+ }
+
+ CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage);
+ CommonAPI::DBus::DBusInputStream inStream(scopedMessage);
+
+ EXPECT_EQ(numOfElements, scopedMessage.getBodyLength());
+ for (int i = 0; i < numOfElements; i += 1) {
+ uint8_t readVal;
+ inStream >> readVal;
+ EXPECT_EQ(val, readVal);
+ }
+}
+
+TEST_F(InputStreamTest, ReadsBools) {
+ dbus_bool_t f = FALSE;
+ dbus_bool_t t = TRUE;
+ for (int i = 0; i < numOfElements; i += 2) {
+ dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_BOOLEAN, &t);
+ dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_BOOLEAN, &f);
+ }
+
+ CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage);
+ CommonAPI::DBus::DBusInputStream inStream(scopedMessage);
+
+ EXPECT_EQ(numOfElements*4, scopedMessage.getBodyLength());
+ for (int i = 0; i < numOfElements; i += 2) {
+ bool readVal;
+ inStream >> readVal;
+ EXPECT_EQ(t, readVal);
+ inStream >> readVal;
+ EXPECT_EQ(f, readVal);
+ }
+}
+
+TEST_F(InputStreamTest, ReadsUint16) {
+
+ uint16_t val = 0xffff;
+ for (int i = 0; i < numOfElements; i += 1) {
+ dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_UINT16, &val);
+ }
+
+ CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage);
+ CommonAPI::DBus::DBusInputStream inStream(scopedMessage);
+
+ EXPECT_EQ(numOfElements*2, scopedMessage.getBodyLength());
+ for (int i = 0; i < numOfElements; i += 1) {
+ uint16_t readVal;
+ inStream >> readVal;
+ EXPECT_EQ(val, readVal);
+ }
+}
+
+TEST_F(InputStreamTest, ReadsInt16) {
+
+ int16_t val = 0x7fff;
+ for (int i = 0; i < numOfElements; i += 1) {
+ dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_INT16, &val);
+ }
+
+ CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage);
+ CommonAPI::DBus::DBusInputStream inStream(scopedMessage);
+
+ EXPECT_EQ(numOfElements*2, scopedMessage.getBodyLength());
+ for (int i = 0; i < numOfElements; i += 1) {
+ int16_t readVal;
+ inStream >> readVal;
+ EXPECT_EQ(val, readVal);
+ }
+}
+
+TEST_F(InputStreamTest, ReadsUint32) {
+
+ uint32_t val = 0xffffffff;
+ for (int i = 0; i < numOfElements; i += 1) {
+ dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_UINT32, &val);
+ }
+
+ CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage);
+ CommonAPI::DBus::DBusInputStream inStream(scopedMessage);
+
+ EXPECT_EQ(numOfElements*4, scopedMessage.getBodyLength());
+ for (int i = 0; i < numOfElements; i += 1) {
+ uint32_t readVal;
+ inStream >> readVal;
+ EXPECT_EQ(val, readVal);
+ }
+}
+
+TEST_F(InputStreamTest, ReadsInt32) {
+
+ int32_t val = 0x7fffffff;
+ for (int i = 0; i < numOfElements; i += 1) {
+ dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_INT32, &val);
+ }
+
+ CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage);
+ CommonAPI::DBus::DBusInputStream inStream(scopedMessage);
+
+ EXPECT_EQ(numOfElements*4, scopedMessage.getBodyLength());
+ for (int i = 0; i < numOfElements; i += 1) {
+ int32_t readVal;
+ inStream >> readVal;
+ EXPECT_EQ(val, readVal);
+ }
+}
+
+TEST_F(InputStreamTest, ReadsUint64) {
+
+ uint64_t val = 0xffffffffffffffff;
+ for (int i = 0; i < numOfElements; i += 1) {
+ dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_UINT64, &val);
+ }
+
+ CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage);
+ CommonAPI::DBus::DBusInputStream inStream(scopedMessage);
+
+ EXPECT_EQ(numOfElements*8, scopedMessage.getBodyLength());
+ for (int i = 0; i < numOfElements; i += 1) {
+ uint64_t readVal;
+ inStream >> readVal;
+ EXPECT_EQ(val, readVal);
+ }
+}
+
+TEST_F(InputStreamTest, ReadsInt64) {
+
+ int64_t val = 0x7fffffffffffffff;
+ for (int i = 0; i < numOfElements; i += 1) {
+ dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_INT64, &val);
+ }
+
+ CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage);
+ CommonAPI::DBus::DBusInputStream inStream(scopedMessage);
+
+ EXPECT_EQ(numOfElements*8, scopedMessage.getBodyLength());
+ for (int i = 0; i < numOfElements; i += 1) {
+ int64_t readVal;
+ inStream >> readVal;
+ EXPECT_EQ(val, readVal);
+ }
+}
+
+TEST_F(InputStreamTest, ReadsDoubles) {
+
+ double val = 13.37;
+ for (int i = 0; i < numOfElements; i += 1) {
+ dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_DOUBLE, &val);
+ }
+
+ CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage);
+ CommonAPI::DBus::DBusInputStream inStream(scopedMessage);
+
+ EXPECT_EQ(numOfElements*8, scopedMessage.getBodyLength());
+ for (int i = 0; i < numOfElements; i += 1) {
+ double readVal;
+ inStream >> readVal;
+ EXPECT_EQ(val, readVal);
+ }
+}
+
+TEST_F(InputStreamTest, ReadsStrings) {
+
+ std::string val = "hai";
+ for (int i = 0; i < numOfElements; i += 1) {
+ dbus_message_iter_append_basic(&libdbusMessageWriteIter, DBUS_TYPE_STRING, &val);
+ }
+
+ CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage);
+ CommonAPI::DBus::DBusInputStream inStream(scopedMessage);
+
+ EXPECT_EQ(numOfElements*4 + numOfElements*4, scopedMessage.getBodyLength());
+ for (int i = 0; i < numOfElements; i += 1) {
+ std::string readVal;
+ inStream >> readVal;
+ EXPECT_EQ(val, readVal);
+ }
+}
+
+namespace bmw {
+namespace test {
+
+struct TestSerializableStruct: CommonAPI::SerializableStruct {
+ uint32_t a;
+ int16_t b;
+ bool c;
+ std::string d;
+ double e;
+
+ virtual void readFromInputStream(CommonAPI::InputStream& inputStream) {
+ inputStream >> a >> b >> c >> d >> e;
+ }
+
+ virtual void writeToOutputStream(CommonAPI::OutputStream& outputStream) const {
+ outputStream << a << b << c << d << e;
+ }
+};
+
+} //namespace test
+} //namespace bmw
+
+TEST_F(InputStreamTest, ReadsStructs) {
+
+ bmw::test::TestSerializableStruct testStruct;
+ testStruct.a = 15;
+ testStruct.b = -32;
+ testStruct.c = FALSE;
+ testStruct.d = "Hello all";
+ testStruct.e = 3.414;
+
+ DBusMessageIter subIter;
+ dbus_message_iter_open_container(&libdbusMessageWriteIter, DBUS_TYPE_STRUCT, NULL, &subIter);
+ dbus_message_iter_append_basic(&subIter, DBUS_TYPE_UINT32, &testStruct.a);
+ dbus_message_iter_append_basic(&subIter, DBUS_TYPE_INT16, &testStruct.b);
+ dbus_bool_t dbusBool = static_cast<dbus_bool_t>(testStruct.c);
+ dbus_message_iter_append_basic(&subIter, DBUS_TYPE_BOOLEAN, &dbusBool);
+ dbus_message_iter_append_basic(&subIter, DBUS_TYPE_STRING, &testStruct.d);
+ dbus_message_iter_append_basic(&subIter, DBUS_TYPE_DOUBLE, &testStruct.e);
+ dbus_message_iter_close_container(&libdbusMessageWriteIter, &subIter);
+
+ CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage);
+ CommonAPI::DBus::DBusInputStream inStream(scopedMessage);
+
+ //40(byte length of struct) = 4(uint32_t) + 2(int16_t) + 2(padding) + 4(bool) + 4(strlength)
+ // + 9(string) + 1(terminating '\0' of string) + 6(padding) + 8 (double)
+ EXPECT_EQ(40, scopedMessage.getBodyLength());
+
+ bmw::test::TestSerializableStruct verifyStruct;
+ inStream >> verifyStruct;
+ EXPECT_EQ(testStruct.a, verifyStruct.a);
+ EXPECT_EQ(testStruct.b, verifyStruct.b);
+ EXPECT_EQ(testStruct.c, verifyStruct.c);
+ EXPECT_EQ(testStruct.d, verifyStruct.d);
+ EXPECT_EQ(testStruct.e, verifyStruct.e);
+}
+
+TEST_F(InputStreamTest, ReadsArrays) {
+
+ std::vector<int32_t> testVector;
+ int32_t val1 = 0xffffffff;
+ int32_t val2 = 0x7fffffff;
+ for (int i = 0; i < numOfElements; i += 2) {
+ testVector.push_back(val1);
+ testVector.push_back(val2);
+ }
+
+ DBusMessageIter subIter;
+ dbus_message_iter_open_container(&libdbusMessageWriteIter, DBUS_TYPE_ARRAY, "i", &subIter);
+ for (int i = 0; i < numOfElements; i++) {
+ dbus_message_iter_append_basic(&subIter, DBUS_TYPE_INT32, &testVector[i]);
+ }
+ dbus_message_iter_close_container(&libdbusMessageWriteIter, &subIter);
+
+ CommonAPI::DBus::DBusMessage scopedMessage(libdbusMessage);
+ CommonAPI::DBus::DBusInputStream inStream(scopedMessage);
+
+ EXPECT_EQ(scopedMessage.getBodyLength(), numOfElements*4 + 4);
+ std::vector<int32_t> verifyVector;
+ inStream >> verifyVector;
+ int32_t res1;
+ int32_t res2;
+ for (int i = 0; i < numOfElements; i += 2) {
+ res1 = verifyVector[i];
+ EXPECT_EQ(val1, res1);
+ res2 = verifyVector[i + 1];
+ EXPECT_EQ(val2, res2);
+ }
+}
+
+TEST_F(InputStreamTest, ReadsArraysInArrays) {
+ size_t numOfElements = 2;
+ DBusMessage* dbusMessage = dbus_message_new_method_call("no.bus.here", "/no/object/here", NULL, "noMethodHere");
+ ASSERT_TRUE(dbusMessage != NULL);
+
+ DBusMessageIter writeIter;
+ dbus_message_iter_init_append(dbusMessage, &writeIter);
+
+ std::vector<std::vector<int32_t>> testVector;
+ int32_t val1 = 0xffffffff;
+ int32_t val2 = 0x7fffffff;
+ for (int i = 0; i < numOfElements; i++) {
+ std::vector<int32_t> inner;
+ for (int j = 0; j < numOfElements; j += 2) {
+ inner.push_back(val1);
+ inner.push_back(val2);
+ }
+ testVector.push_back(inner);
+ }
+
+ DBusMessageIter subIter;
+ dbus_message_iter_open_container(&writeIter, DBUS_TYPE_ARRAY, "ai", &subIter);
+ for (int i = 0; i < numOfElements; i++) {
+ DBusMessageIter subsubIter;
+ dbus_message_iter_open_container(&subIter, DBUS_TYPE_ARRAY, "i", &subsubIter);
+ for (int j = 0; j < numOfElements; j++) {
+ dbus_message_iter_append_basic(&subsubIter, DBUS_TYPE_INT32, &(testVector[i][j]));
+ }
+ dbus_message_iter_close_container(&subIter, &subsubIter);
+ }
+ dbus_message_iter_close_container(&writeIter, &subIter);
+
+ CommonAPI::DBus::DBusMessage scopedMessage(dbusMessage);
+ CommonAPI::DBus::DBusInputStream inStream(scopedMessage);
+
+ // 5*5*int32_t + 5*lengthField_inner(int32_t) + lengthField_outer(int32_t)
+ EXPECT_EQ(numOfElements*numOfElements*4 + numOfElements*4 + 4, scopedMessage.getBodyLength());
+ std::vector<std::vector<int32_t>> verifyVector;
+ inStream >> verifyVector;
+
+ int32_t res1;
+ int32_t res2;
+ for (int i = 0; i < numOfElements; i++) {
+ std::vector<int32_t> innerVerify = verifyVector[i];
+ for (int j = 0; j < numOfElements; j += 2) {
+ res1 = innerVerify[j];
+ EXPECT_EQ(val1, res1);
+ res2 = innerVerify[j + 1];
+ EXPECT_EQ(val2, res2);
+ }
+ }
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <gtest/gtest.h>
+
+#include <cassert>
+#include <cstdint>
+#include <iostream>
+#include <functional>
+#include <memory>
+#include <stdint.h>
+#include <string>
+#include <utility>
+#include <tuple>
+#include <type_traits>
+
+#include <CommonAPI/types.h>
+#include <CommonAPI/Runtime.h>
+
+#include "commonapi/tests/TestInterfaceProxy.h"
+#include "commonapi/tests/TestInterfaceStubDefault.h"
+const std::string serviceAddress = "local:commonapi.tests.TestInterface:commonapi.tests.TestInterface";
+
+class DBusMultipleConnectionTest: public ::testing::Test {
+ protected:
+ virtual void SetUp() {
+ proxyFactory = CommonAPI::Runtime::load()->createFactory();
+ stubFactory = CommonAPI::Runtime::load()->createFactory();
+ ASSERT_TRUE((bool)proxyFactory);
+ ASSERT_TRUE((bool)stubFactory);
+
+ stub = std::make_shared<commonapi::tests::TestInterfaceStubDefault>();
+ bool success = stubFactory->registerService(stub, serviceAddress);
+ ASSERT_TRUE(success);
+
+ proxy = proxyFactory->buildProxy<commonapi::tests::TestInterfaceProxy>(serviceAddress);
+ ASSERT_TRUE((bool)proxy);
+ }
+
+ virtual void TearDown() {
+ }
+
+ std::shared_ptr<CommonAPI::Factory> proxyFactory;
+ std::shared_ptr<CommonAPI::Factory> stubFactory;
+ std::shared_ptr<commonapi::tests::TestInterfaceStubDefault> stub;
+ std::shared_ptr<commonapi::tests::TestInterfaceProxy<> > proxy;
+
+};
+
+
+TEST_F(DBusMultipleConnectionTest, SetAttribute) {
+ uint32_t v1 = 5;
+ uint32_t v2;
+ CommonAPI::CallStatus stat;
+ proxy->getTestPredefinedTypeAttributeAttribute().setValue(v1, stat, v2);
+ ASSERT_EQ(stat, CommonAPI::CallStatus::SUCCESS);
+ ASSERT_EQ(v1, v2);
+}
+
+TEST_F(DBusMultipleConnectionTest, SetAttributeBroadcast) {
+ uint32_t v1 = 6;
+ uint32_t v2;
+ uint32_t v3 = 0;
+
+ std::promise<bool> promise;
+ auto future = promise.get_future();
+
+ proxy->getTestPredefinedTypeAttributeAttribute().getChangedEvent().subscribe([&](
+ const uint32_t intVal) {
+ v3 = intVal;
+ promise.set_value(true);
+ });
+
+ CommonAPI::CallStatus stat;
+ proxy->getTestPredefinedTypeAttributeAttribute().setValue(v1, stat, v2);
+ ASSERT_EQ(stat, CommonAPI::CallStatus::SUCCESS);
+ ASSERT_EQ(v1, v2);
+
+ ASSERT_TRUE(future.get());
+ ASSERT_EQ(v1, v3);
+
+}
+
+
+TEST_F(DBusMultipleConnectionTest, GetAttribute) {
+ uint32_t v1;
+ CommonAPI::CallStatus stat = proxy->getTestPredefinedTypeAttributeAttribute().getValue(v1);
+ ASSERT_EQ(stat, CommonAPI::CallStatus::SUCCESS);
+}
+
+TEST_F(DBusMultipleConnectionTest, RemoteMethodCall) {
+ uint32_t v1 = 5;
+ std::string v2 = "Hai :)";
+ CommonAPI::CallStatus stat;
+ proxy->testVoidPredefinedTypeMethod(v1, v2, stat);
+ ASSERT_EQ(stat, CommonAPI::CallStatus::SUCCESS);
+}
+
+TEST_F(DBusMultipleConnectionTest, Broadcast) {
+ uint32_t v1 = 5;
+ uint32_t v3 = 0;
+ std::string v2 = "Hai :)";
+
+ std::promise<bool> promise;
+ auto future = promise.get_future();
+
+ proxy->getTestPredefinedTypeBroadcastEvent().subscribe([&](
+ const uint32_t intVal, const std::string& strVal) {
+ v3 = intVal;
+ promise.set_value(true);
+ });
+
+ stub->firePredefinedBroadcast(v1, v2);
+
+ ASSERT_TRUE(future.get());
+ ASSERT_EQ(v1, v3);
+}
+
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <common-api-dbus/dbus-connection.h>
+#include <common-api-dbus/dbus-name-cache.h>
+
+
+
+int main(void) {
+ auto dbusConnection = common::api::dbus::DBusConnection::getSessionBus();
+
+ dbusConnection->connect();
+
+ common::api::dbus::DBusNameCache dbusNameCache(dbusConnection);
+
+ dbusConnection->requestServiceNameAndBlock("common.api.dbus.test.DBusNameCache");
+
+ for (int i = 0; i < 5; i++)
+ dbusConnection->readWriteDispatch(100);
+
+ dbusConnection->releaseServiceName("common.api.dbus.test.DBusNameCache");
+
+ for (int i = 0; i < 5; i++)
+ dbusConnection->readWriteDispatch(100);
+
+ return 0;
+}
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <dbus/dbus.h>
+#include <gtest/gtest.h>
+
+#include <CommonAPI/DBus/DBusMessage.h>
+#include <CommonAPI/DBus/DBusOutputStream.h>
+#include <CommonAPI/DBus/DBusInputStream.h>
+#include <CommonAPI/SerializableStruct.h>
+
+
+class OutputStreamTest: public ::testing::Test {
+protected:
+ size_t numOfElements;
+ CommonAPI::DBus::DBusMessage message;
+ const char* busName;
+ const char* objectPath;
+ const char* interfaceName;
+ const char* methodName;
+
+ void SetUp() {
+ numOfElements = 10;
+ busName = "no.bus.here";
+ objectPath = "/no/object/here";
+ interfaceName = "no.interface.here";
+ methodName = "noMethodHere";
+ }
+
+ void TearDown() {
+ }
+};
+
+TEST_F(OutputStreamTest, CanBeConstructed) {
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+}
+
+TEST_F(OutputStreamTest, WritesBytes) {
+ const char* signature = "yyyyyyyyyy";
+ message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature);
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+
+ outStream.reserveMemory(numOfElements);
+ uint8_t val1 = 0xff;
+ uint8_t val2 = 0x00;
+ for (int i = 0; i < numOfElements; i += 2) {
+ outStream << val1;
+ outStream << val2;
+ }
+ outStream.flush();
+
+ EXPECT_EQ(numOfElements, message.getBodyLength());
+
+ CommonAPI::DBus::DBusInputStream inStream(message);
+
+ uint8_t verifyVal1;
+ uint8_t verifyVal2;
+ for (int i = 0; i < numOfElements; i += 2) {
+ inStream >> verifyVal1;
+ EXPECT_EQ(val1, verifyVal1);
+
+ inStream >> verifyVal2;
+ EXPECT_EQ(val2, verifyVal2);
+ }
+}
+
+TEST_F(OutputStreamTest, WritesBools) {
+ const char* signature = "bbbbbbbbbb";
+ message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature);
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+
+ outStream.reserveMemory(numOfElements * 4);
+ bool val1 = TRUE;
+ bool val2 = FALSE;
+ for (int i = 0; i < numOfElements; i += 2) {
+ outStream << val1;
+ outStream << val2;
+ }
+ outStream.flush();
+
+ EXPECT_EQ(numOfElements*4, message.getBodyLength());
+
+ CommonAPI::DBus::DBusInputStream inStream(message);
+
+ bool verifyVal1;
+ bool verifyVal2;
+ for (int i = 0; i < numOfElements; i += 2) {
+ inStream >> verifyVal1;
+ EXPECT_EQ(val1, verifyVal1);
+
+ inStream >> verifyVal2;
+ EXPECT_EQ(val2, verifyVal2);
+ }
+}
+
+TEST_F(OutputStreamTest, WritesUInt16) {
+ const char* signature = "qqqqqqqqqq";
+ message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature);
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+
+ outStream.reserveMemory(numOfElements * 2);
+ uint16_t val1 = 0x0000;
+ uint16_t val2 = 0xffff;
+ for (int i = 0; i < numOfElements; i += 2) {
+ outStream << val1;
+ outStream << val2;
+ }
+ outStream.flush();
+
+ EXPECT_EQ(numOfElements*2, message.getBodyLength());
+
+ CommonAPI::DBus::DBusInputStream inStream(message);
+
+ uint16_t verifyVal1;
+ uint16_t verifyVal2;
+ for (int i = 0; i < numOfElements; i += 2) {
+ inStream >> verifyVal1;
+ EXPECT_EQ(val1, verifyVal1);
+
+ inStream >> verifyVal2;
+ EXPECT_EQ(val2, verifyVal2);
+ }
+}
+
+TEST_F(OutputStreamTest, WritesInt16) {
+ const char* signature = "nnnnnnnnnn";
+ message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature);
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+
+ outStream.reserveMemory(numOfElements * 2);
+ int16_t val1 = 0x7fff;
+ int16_t val2 = 0xffff;
+ for (int i = 0; i < numOfElements; i += 2) {
+ outStream << val1;
+ outStream << val2;
+ }
+ outStream.flush();
+
+ EXPECT_EQ(numOfElements*2, message.getBodyLength());
+
+ CommonAPI::DBus::DBusInputStream inStream(message);
+
+ int16_t verifyVal1;
+ int16_t verifyVal2;
+ for (int i = 0; i < numOfElements; i += 2) {
+ inStream >> verifyVal1;
+ EXPECT_EQ(val1, verifyVal1);
+
+ inStream >> verifyVal2;
+ EXPECT_EQ(val2, verifyVal2);
+ }
+}
+
+TEST_F(OutputStreamTest, WritesUInt32) {
+ const char* signature = "uuuuuuuuuu";
+ message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature);
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+
+ outStream.reserveMemory(numOfElements * 4);
+ uint32_t val1 = 0x00000000;
+ uint32_t val2 = 0xffffffff;
+ for (int i = 0; i < numOfElements; i += 2) {
+ outStream << val1;
+ outStream << val2;
+ }
+ outStream.flush();
+
+ EXPECT_EQ(numOfElements*4, message.getBodyLength());
+
+ CommonAPI::DBus::DBusInputStream inStream(message);
+
+ uint32_t verifyVal1;
+ uint32_t verifyVal2;
+ for (int i = 0; i < numOfElements; i += 2) {
+ inStream >> verifyVal1;
+ EXPECT_EQ(val1, verifyVal1);
+
+ inStream >> verifyVal2;
+ EXPECT_EQ(val2, verifyVal2);
+ }
+}
+
+TEST_F(OutputStreamTest, WritesInt32) {
+ const char* signature = "iiiiiiiiii";
+ message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature);
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+
+ outStream.reserveMemory(numOfElements * 4);
+ int32_t val1 = 0x7fffffff;
+ int32_t val2 = 0xffffffff;
+ for (int i = 0; i < numOfElements; i += 2) {
+ outStream << val1;
+ outStream << val2;
+ }
+ outStream.flush();
+
+ EXPECT_EQ(numOfElements*4, message.getBodyLength());
+
+ CommonAPI::DBus::DBusInputStream inStream(message);
+
+ int32_t verifyVal1;
+ int32_t verifyVal2;
+ for (int i = 0; i < numOfElements; i += 2) {
+ inStream >> verifyVal1;
+ EXPECT_EQ(val1, verifyVal1);
+
+ inStream >> verifyVal2;
+ EXPECT_EQ(val2, verifyVal2);
+ }
+}
+
+TEST_F(OutputStreamTest, WritesUInt64) {
+ const char* signature = "tttttttttt";
+ message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature);
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+
+ outStream.reserveMemory(numOfElements * 8);
+ uint64_t val1 = 0x0000000000000000;
+ uint64_t val2 = 0xffffffffffffffff;
+ for (int i = 0; i < numOfElements; i += 2) {
+ outStream << val1;
+ outStream << val2;
+ }
+ outStream.flush();
+
+ EXPECT_EQ(numOfElements*8, message.getBodyLength());
+
+ CommonAPI::DBus::DBusInputStream inStream(message);
+
+ uint64_t verifyVal1;
+ uint64_t verifyVal2;
+ for (int i = 0; i < numOfElements; i += 2) {
+ inStream >> verifyVal1;
+ EXPECT_EQ(val1, verifyVal1);
+
+ inStream >> verifyVal2;
+ EXPECT_EQ(val2, verifyVal2);
+ }
+}
+
+TEST_F(OutputStreamTest, WritesInt64) {
+ const char* signature = "xxxxxxxxxx";
+ message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature);
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+
+ outStream.reserveMemory(numOfElements * 8);
+ int64_t val1 = 0x7fffffffffffffff;
+ int64_t val2 = 0xffffffffffffffff;
+ for (int i = 0; i < numOfElements; i += 2) {
+ outStream << val1;
+ outStream << val2;
+ }
+ outStream.flush();
+
+ EXPECT_EQ(numOfElements*8, message.getBodyLength());
+
+ CommonAPI::DBus::DBusInputStream inStream(message);
+
+ int64_t verifyVal1;
+ int64_t verifyVal2;
+ for (int i = 0; i < numOfElements; i += 2) {
+ inStream >> verifyVal1;
+ EXPECT_EQ(val1, verifyVal1);
+
+ inStream >> verifyVal2;
+ EXPECT_EQ(val2, verifyVal2);
+ }
+}
+
+TEST_F(OutputStreamTest, WritesDouble) {
+ const char* signature = "dddddddddd";
+ message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature);
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+
+ outStream.reserveMemory(numOfElements * 8);
+ double val1 = 13.37;
+ double val2 = 3.414;
+ for (int i = 0; i < numOfElements; i += 2) {
+ outStream << val1;
+ outStream << val2;
+ }
+ outStream.flush();
+
+ EXPECT_EQ(numOfElements*8, message.getBodyLength());
+
+ CommonAPI::DBus::DBusInputStream inStream(message);
+
+ double verifyVal1;
+ double verifyVal2;
+ std::string verifySignature;
+ for (int i = 0; i < numOfElements; i += 2) {
+ inStream >> verifyVal1;
+ EXPECT_EQ(val1, verifyVal1);
+
+ inStream >> verifyVal2;
+ EXPECT_EQ(val2, verifyVal2);
+ }
+}
+
+TEST_F(OutputStreamTest, WritesStrings) {
+ const char* signature = "sss";
+ message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature);
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+
+ std::string val1 = "hai";
+ std::string val2 = "ciao";
+ std::string val3 = "salut";
+
+ //sizes of the strings + terminating null-bytes (each 1 byte) + length-fields (each 4 bytes)
+ outStream.reserveMemory(val1.size() + val2.size() + val3.size() + 3 + 3 * 4);
+ outStream << val1 << val2 << val3;
+ outStream.flush();
+
+ //Length fields + actual strings + terminating '\0's + 3(padding)
+ EXPECT_EQ(3*4 + 3 + 4 + 5 + 3 + 3, message.getBodyLength());
+
+ CommonAPI::DBus::DBusInputStream inStream(message);
+
+ std::string verifyVal1;
+ std::string verifyVal2;
+ std::string verifyVal3;
+ std::string verifySignature;
+
+ inStream >> verifyVal1;
+ inStream >> verifyVal2;
+ inStream >> verifyVal3;
+
+ EXPECT_EQ(val1, verifyVal1);
+ EXPECT_EQ(val2, verifyVal2);
+ EXPECT_EQ(val3, verifyVal3);
+}
+
+namespace bmw {
+namespace test {
+
+struct myStruct: CommonAPI::SerializableStruct {
+ ~myStruct();
+
+ uint32_t a;
+ int16_t b;
+ bool c;
+ std::string d;
+ double e;
+
+ virtual void readFromInputStream(CommonAPI::InputStream& inputMessageStream);
+ virtual void writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const;
+};
+
+myStruct::~myStruct() {
+}
+
+void myStruct::readFromInputStream(CommonAPI::InputStream& inputMessageStream) {
+ inputMessageStream >> a >> b >> c >> d >> e;
+}
+
+void myStruct::writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const {
+ outputMessageStream << a << b << c << d << e;
+}
+
+} //namespace test
+} //namespace bmw
+
+TEST_F(OutputStreamTest, WritesStructs) {
+ const char* signature = "(unbsd)";
+ message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature);
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+
+ bmw::test::myStruct testStruct;
+ testStruct.a = 15;
+ testStruct.b = -32;
+ testStruct.c = FALSE;
+ testStruct.d = "Hello all";
+ testStruct.e = 3.414;
+
+ // 40(byte length of struct) = 4(uint32_t) + 2(int16_t) + 2(padding) + 4(bool) + 4(strlength)
+ // + 9(string) + 1(terminating '\0' of string) + 6(padding) + 8 (double)
+ outStream.reserveMemory(40);
+ outStream << testStruct;
+ outStream.flush();
+
+ EXPECT_EQ(40, message.getBodyLength());
+
+ CommonAPI::DBus::DBusInputStream inStream(message);
+ bmw::test::myStruct verifyStruct;
+ inStream >> verifyStruct;
+
+ EXPECT_EQ(testStruct.a, verifyStruct.a);
+ EXPECT_EQ(testStruct.b, verifyStruct.b);
+ EXPECT_EQ(testStruct.c, verifyStruct.c);
+ EXPECT_EQ(testStruct.d, verifyStruct.d);
+ EXPECT_EQ(testStruct.e, verifyStruct.e);
+}
+
+TEST_F(OutputStreamTest, WritesArrays) {
+ const char* signature = "ai";
+ message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature);
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+
+ std::vector<int32_t> testVector;
+ int32_t val1 = 0xffffffff;
+ int32_t val2 = 0x7fffffff;
+ for (int i = 0; i < numOfElements; i += 2) {
+ testVector.push_back(val1);
+ testVector.push_back(val2);
+ }
+
+ outStream.reserveMemory(numOfElements * 4 + 4);
+ outStream << testVector;
+ outStream.flush();
+
+ EXPECT_EQ(numOfElements*4 + 4, message.getBodyLength());
+
+ CommonAPI::DBus::DBusInputStream inStream(message);
+ std::vector<int32_t> verifyVector;
+ inStream >> verifyVector;
+
+ int32_t res1;
+ int32_t res2;
+ for (int i = 0; i < numOfElements; i += 2) {
+ res1 = verifyVector[i];
+ EXPECT_EQ(val1, res1);
+ res2 = verifyVector[i + 1];
+ EXPECT_EQ(val2, res2);
+ }
+}
+
+TEST_F(OutputStreamTest, WritesArraysOfStrings) {
+ const char* signature = "as";
+ message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature);
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+
+ std::vector<std::string> testVector;
+ std::string val1 = "Hai";
+ std::string val2 = "Ciao";
+ for (int i = 0; i < numOfElements; i += 2) {
+ testVector.push_back(val1);
+ testVector.push_back(val2);
+ }
+
+ // 101 = 4(lengthFieldOfArray) +
+ // 4*(4(lengthField1) + 4(string1 mit \0-byte) + 4(lengthField2) + 5(string2 mit \0-byte) + 3(paddingTo4)) +
+ // (4(lengthField1) + 4(string1 mit \0-byte) + 4(lengthField2) + 5(string2 mit \0-byte))
+ size_t vectorLength = 101;
+ outStream.reserveMemory(vectorLength);
+ outStream << testVector;
+ outStream.flush();
+
+ EXPECT_EQ(vectorLength, message.getBodyLength());
+
+ CommonAPI::DBus::DBusInputStream inStream(message);
+ std::vector<std::string> verifyVector;
+ inStream >> verifyVector;
+
+ std::string res1;
+ std::string res2;
+ for (int i = 0; i < numOfElements; i += 2) {
+ res1 = verifyVector[i];
+ EXPECT_EQ(val1, res1);
+ res2 = verifyVector[i + 1];
+ EXPECT_EQ(val2, res2);
+ }
+}
+
+TEST_F(OutputStreamTest, WritesArraysInArrays) {
+ const char* signature = "aai";
+ message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature);
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+
+ std::vector<std::vector<int32_t>> testVector;
+ int32_t val1 = 0xffffffff;
+ int32_t val2 = 0x7fffffff;
+ for (int i = 0; i < numOfElements; i++) {
+ std::vector<int32_t> inner;
+ for (int j = 0; j < numOfElements; j += 2) {
+ inner.push_back(val1);
+ inner.push_back(val2);
+ }
+ testVector.push_back(inner);
+ }
+
+ outStream.reserveMemory(numOfElements * numOfElements * 4 + numOfElements * 4 + 4);
+ outStream << testVector;
+ outStream.flush();
+
+ EXPECT_EQ(numOfElements*numOfElements*4 + numOfElements*4 + 4, message.getBodyLength());
+
+ CommonAPI::DBus::DBusInputStream inStream(message);
+ std::vector<std::vector<int32_t>> verifyVector;
+ inStream >> verifyVector;
+
+ int32_t res1;
+ int32_t res2;
+ for (int i = 0; i < numOfElements; i++) {
+ std::vector<int32_t> innerVerify = verifyVector[i];
+ for (int j = 0; j < numOfElements; j += 2) {
+ res1 = innerVerify[j];
+ EXPECT_EQ(val1, res1);
+ res2 = innerVerify[j + 1];
+ EXPECT_EQ(val2, res2);
+ }
+ }
+}
+
+namespace com {
+namespace bmw {
+namespace test {
+
+struct TestStruct: CommonAPI::SerializableStruct {
+ TestStruct();
+ TestStruct(int32_t v1, double v2, double v3, std::string v4);
+ ~TestStruct();
+
+ int32_t val1;
+ double val2;
+ double val3;
+ std::string val4;
+
+ virtual void readFromInputStream(CommonAPI::InputStream& inputMessageStream);
+ virtual void writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const;
+};
+
+typedef std::vector<TestStruct> TestStructList;
+
+TestStruct::TestStruct() :
+ val1(0), val2(0), val3(0), val4("") {
+}
+
+TestStruct::TestStruct(int32_t v1, double v2, double v3, std::string v4) :
+ val1(v1), val2(v2), val3(v3), val4(v4) {
+}
+
+TestStruct::~TestStruct() {
+}
+
+void TestStruct::readFromInputStream(CommonAPI::InputStream& inputMessageStream) {
+ inputMessageStream >> val1 >> val2 >> val3 >> val4;
+}
+
+void TestStruct::writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const {
+ outputMessageStream << val1 << val2 << val3 << val4;
+}
+
+} // namespace test
+} // namespace bmw
+} // namespace com
+
+
+TEST_F(OutputStreamTest, WritesTestStructs) {
+ const char* signature = "(idds)";
+ message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature);
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+
+ com::bmw::test::TestStruct testStruct(1, 12.6, 1e40, "XXXXXXXXXXXXXXXXXXXX");
+
+ //4(int32_t) + 4(padding) + 8(double) + 8(double) + 4(str_length) + 20(string) + 1(null-termination)
+ uint32_t expectedSize = 49;
+ outStream.reserveMemory(expectedSize);
+ outStream << testStruct;
+ outStream.flush();
+
+ EXPECT_EQ(expectedSize, message.getBodyLength());
+
+ CommonAPI::DBus::DBusInputStream inStream(message);
+ com::bmw::test::TestStruct verifyStruct;
+ inStream >> verifyStruct;
+
+ EXPECT_EQ(testStruct.val1, verifyStruct.val1);
+ EXPECT_EQ(testStruct.val2, verifyStruct.val2);
+ EXPECT_EQ(testStruct.val3, verifyStruct.val3);
+ EXPECT_EQ(testStruct.val4, verifyStruct.val4);
+}
+
+TEST_F(OutputStreamTest, WritesTestStructLists) {
+ const char* signature = "a(idds)";
+ message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature);
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+
+ com::bmw::test::TestStructList testList;
+ for (int i = 0; i < numOfElements; i++) {
+ testList.emplace_back(1, 12.6, 1e40, "XXXXXXXXXXXXXXXXXXXX");
+ }
+
+ //struct size: 49 = 4(int32_t) + 4(padding) + 8(double) + 8(double) + 4(str_length) + 20(string) + 1(null-termination)
+ //array size: 4(array_length) + 4(struct_padding) + (numElements-1)*(49(struct) + 7(struct_padding)) + 49(struct)
+ uint32_t expectedSize = 8 + (numOfElements - 1) * (49 + 7) + 49;
+ outStream.reserveMemory(expectedSize);
+ outStream << testList;
+ outStream.flush();
+
+ EXPECT_EQ(expectedSize, message.getBodyLength());
+
+ CommonAPI::DBus::DBusInputStream inStream(message);
+ com::bmw::test::TestStructList verifyList;
+ inStream >> verifyList;
+
+ EXPECT_EQ(numOfElements, verifyList.size());
+}
+
+
+
+namespace com {
+namespace bmw {
+namespace test {
+
+struct ArrayStruct: CommonAPI::SerializableStruct {
+ ArrayStruct();
+ ArrayStruct(std::vector<int64_t> v1, std::vector<std::string> v2, std::vector<double> v3, std::vector<std::string> v4, std::vector<uint16_t> v5);
+ ~ArrayStruct();
+
+ std::vector<int64_t> val1;
+ std::vector<std::string> val2;
+ std::vector<double> val3;
+ std::vector<std::string> val4;
+ std::vector<uint16_t> val5;
+
+ virtual void readFromInputStream(CommonAPI::InputStream& inputMessageStream);
+ virtual void writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const;
+};
+
+typedef std::vector<TestStruct> TestStructList;
+
+ArrayStruct::ArrayStruct() {
+}
+
+ArrayStruct::ArrayStruct(std::vector<int64_t> v1, std::vector<std::string> v2, std::vector<double> v3, std::vector<std::string> v4, std::vector<uint16_t> v5) :
+ val1(v1), val2(v2), val3(v3), val4(v4), val5(v5) {
+}
+
+ArrayStruct::~ArrayStruct() {
+}
+
+void ArrayStruct::readFromInputStream(CommonAPI::InputStream& inputMessageStream) {
+ inputMessageStream >> val1 >> val2 >> val3 >> val4 >> val5;
+}
+
+void ArrayStruct::writeToOutputStream(CommonAPI::OutputStream& outputMessageStream) const {
+ outputMessageStream << val1 << val2 << val3 << val4 << val5;
+}
+
+} // namespace test
+} // namespace bmw
+} // namespace com
+
+
+TEST_F(OutputStreamTest, WritesStructsOfArraysWithSthBefore) {
+ const char* signature = "(axasadasaq)";
+ message = CommonAPI::DBus::DBusMessage::createMethodCall(busName, objectPath, interfaceName, methodName, signature);
+ CommonAPI::DBus::DBusOutputStream outStream(message);
+
+ com::bmw::test::ArrayStruct arrayStruct;
+ for (int i = 0; i < numOfElements; i++) {
+ arrayStruct.val1.push_back(i*50);
+ arrayStruct.val2.push_back("Hai");
+ arrayStruct.val3.push_back(3.414);
+ arrayStruct.val4.push_back("Ciao");
+ arrayStruct.val5.push_back(i*5);
+ }
+ uint16_t frontValue = 0;
+
+ // 2(uint16) + 6(padding) --> 8
+ // 4(LengthField) + 4(padding) + 10 * 8(int64) --> 88 --> 96
+ // 4(LengthField) + 10 * (4(LengthField) + 4("Hai\0")) --> 84 --> 180
+ // 4(LengthField) + 10 * 8(double) --> 84 --> 264
+ // 4(LengthField) + 10 * (4(LengthField) + 5("Ciao\0") + 3(padding)) --> 124 --> 388
+ // 4(LengthField) + 10 * 2(uint16) --> 24 --> 412
+ size_t structLength = 412;
+ outStream.reserveMemory(structLength);
+ outStream << frontValue << arrayStruct;
+ outStream.flush();
+
+ EXPECT_EQ(structLength, message.getBodyLength());
+
+ CommonAPI::DBus::DBusInputStream inStream(message);
+ com::bmw::test::ArrayStruct verifyStruct;
+
+ uint16_t frontVerification;
+ inStream >> frontVerification >> verifyStruct;
+
+ EXPECT_EQ(frontValue, frontVerification);
+
+ int64_t res1;
+ std::string res2;
+ double res3;
+ std::string res4;
+ uint16_t res5;
+
+ for (int i = 0; i < numOfElements; i++) {
+ res1 = verifyStruct.val1[i];
+ res2 = verifyStruct.val2[i];
+ res3 = verifyStruct.val3[i];
+ res4 = verifyStruct.val4[i];
+ res5 = verifyStruct.val5[i];
+
+ EXPECT_EQ(i*50, res1);
+ EXPECT_EQ(std::string("Hai"), res2);
+ EXPECT_EQ(3.414, res3);
+ EXPECT_EQ(std::string("Ciao"), res4);
+ EXPECT_EQ(i*5, res5);
+ }
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <dbus/dbus.h>
+#include <CommonAPI/DBus/DBusInputStream.h>
+#include <CommonAPI/DBus/DBusMessage.h>
+#include <CommonAPI/DBus/DBusProxy.h>
+#include <CommonAPI/DBus/DBusConnection.h>
+#include <CommonAPI/DBus/DBusStubAdapter.h>
+#include <stdint.h>
+#include <vector>
+#include <gtest/gtest.h>
+#include <iostream>
+#include <algorithm>
+#include <string>
+
+
+class TestProxy: public CommonAPI::DBus::DBusProxy {
+public:
+ TestProxy(const std::shared_ptr<CommonAPI::DBus::DBusConnection>& dbusConnection);
+ ~TestProxy() = default;
+
+protected:
+ void getOwnVersion(uint16_t& ownVersionMajor, uint16_t& ownVersionMinor) const;
+
+};
+
+class TestStubAdapter: public CommonAPI::DBus::DBusStubAdapter {
+public:
+ TestStubAdapter(const std::shared_ptr<CommonAPI::DBus::DBusConnection>& dbusConnection);
+protected:
+ bool onInterfaceDBusMessage(const CommonAPI::DBus::DBusMessage& dbusMessage);
+ const char* getMethodsDBusIntrospectionXmlData() const;
+};
+
+const char* TestStubAdapter::getMethodsDBusIntrospectionXmlData() const {
+ return "";
+}
+
+bool TestStubAdapter::onInterfaceDBusMessage(const CommonAPI::DBus::DBusMessage& dbusMessage) {
+ return true;
+}
+
+TestStubAdapter::TestStubAdapter(const std::shared_ptr<CommonAPI::DBus::DBusConnection>& dbusConnection) :
+ CommonAPI::DBus::DBusStubAdapter(
+ "com.bmw.test.Echo",
+ "/com/bmw/test/Echo",
+ "com.bmw.test.Echo",
+ dbusConnection) {
+}
+
+TestProxy::TestProxy(const std::shared_ptr<CommonAPI::DBus::DBusConnection>& dbusConnection) :
+ CommonAPI::DBus::DBusProxy(
+ "com.bmw.test.Echo",
+ "/com/bmw/test/Echo",
+ "com.bmw.test.Echo",
+ dbusConnection) {
+}
+
+void TestProxy::getOwnVersion(uint16_t& ownVersionMajor, uint16_t& ownVersionMinor) const {
+}
+
+
+const static std::string ID = "com.bmw.test.Echo";
+
+
+class ProxyTest: public ::testing::Test {
+protected:
+
+ virtual void TearDown() {
+ dbusConnection_->disconnect();
+ }
+
+ void SetUp() {
+ dbusConnection_ = CommonAPI::DBus::DBusConnection::getSessionBus();
+ ASSERT_TRUE(dbusConnection_->connect());
+ proxy_ = std::make_shared<TestProxy>(dbusConnection_);
+ }
+
+ std::shared_ptr<CommonAPI::DBus::DBusConnection> dbusConnection_;
+ std::shared_ptr<TestProxy> proxy_;
+};
+
+TEST_F(ProxyTest, HasCorrectBusName) {
+ std::string actualName = proxy_->getDBusBusName();
+ EXPECT_EQ("com.bmw.test.Echo", actualName);
+}
+
+TEST_F(ProxyTest, HasCorrectObjectPath) {
+ std::string actualPath = proxy_->getDBusObjectPath();
+ EXPECT_EQ("/com/bmw/test/Echo", actualPath);
+}
+
+TEST_F(ProxyTest, HasCorrectInterfaceName) {
+ std::string actualName = proxy_->getInterfaceName();
+ EXPECT_EQ("com.bmw.test.Echo", actualName);
+}
+
+TEST_F(ProxyTest, IsNotAvailable) {
+ bool isAvailable = proxy_->isAvailable();
+ EXPECT_FALSE(isAvailable);
+}
+
+TEST_F(ProxyTest, ServiceRegistry) {
+ std::shared_ptr<CommonAPI::DBus::DBusProxyConnection> connection = proxy_->getDBusConnection();
+ auto registry = connection->getDBusServiceRegistry();
+ ASSERT_FALSE(!registry);
+}
+
+TEST_F(ProxyTest, ServiceStatus) {
+ std::shared_ptr<TestStubAdapter> stub_ = std::make_shared<TestStubAdapter>(dbusConnection_);
+ stub_->init();
+ dbusConnection_->requestServiceNameAndBlock(ID);
+
+ std::vector<std::string> actuallyAvailableServices;
+
+
+ actuallyAvailableServices = dbusConnection_->getDBusServiceRegistry()->getAvailableServiceInstances("com.bmw.test.Echo",
+ "local");
+
+ std::string toFind = "com.bmw.test.Echo";
+ auto found = std::find(actuallyAvailableServices.begin(), actuallyAvailableServices.end(), toFind);
+
+ ASSERT_TRUE(actuallyAvailableServices.begin() != actuallyAvailableServices.end());
+}
+
+TEST_F(ProxyTest, IsAvailableBlocking) {
+ std::shared_ptr<TestStubAdapter> stub = std::make_shared<TestStubAdapter>(dbusConnection_);
+ stub->init();
+ dbusConnection_->requestServiceNameAndBlock(ID);
+
+ bool isAvailable = proxy_->isAvailableBlocking();
+ EXPECT_TRUE(isAvailable);
+}
+
+TEST_F(ProxyTest, HasNecessaryAttributesAndEvents) {
+ CommonAPI::InterfaceVersionAttribute& versionAttribute = (proxy_->getInterfaceVersionAttribute());
+ CommonAPI::ProxyStatusEvent& statusEvent = (proxy_->getProxyStatusEvent());
+}
+
+TEST_F(ProxyTest, IsConnected) {
+ ASSERT_TRUE(proxy_->getDBusConnection()->isConnected());
+}
+
+TEST_F(ProxyTest, TestInterfaceVersionAttribute) {
+ CommonAPI::InterfaceVersionAttribute& versionAttribute = proxy_->getInterfaceVersionAttribute();
+ CommonAPI::Version version;
+ CommonAPI::CallStatus status = versionAttribute.getValue(version);
+ ASSERT_EQ(CommonAPI::CallStatus::NOT_AVAILABLE, status);
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <gtest/gtest.h>
+
+#include <cstring>
+
+#include <CommonAPI/DBus/DBusRuntime.h>
+#include <CommonAPI/DBus/DBusFactory.h>
+
+
+
+class DBusRuntimeTest: public ::testing::Test {
+ protected:
+ virtual void SetUp() {
+ }
+
+ virtual void TearDown() {
+ }
+};
+
+
+
+TEST_F(DBusRuntimeTest, LoadsDefaultStaticallyLinkedDBusLibrary) {
+ std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load();
+ ASSERT_TRUE((bool)runtime);
+ CommonAPI::DBus::DBusRuntime* dbusRuntime = dynamic_cast<CommonAPI::DBus::DBusRuntime*>(&(*runtime));
+ ASSERT_TRUE(dbusRuntime != NULL);
+}
+
+
+TEST_F(DBusRuntimeTest, LoadsSpecifiedStaticallyLinkedDBusLibrary) {
+ std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus");
+ ASSERT_TRUE((bool)runtime);
+ CommonAPI::DBus::DBusRuntime* dbusRuntime = dynamic_cast<CommonAPI::DBus::DBusRuntime*>(&(*runtime));
+ ASSERT_TRUE(dbusRuntime != NULL);
+}
+
+
+TEST_F(DBusRuntimeTest, LoadsDBusLibraryAsSingleton) {
+ std::shared_ptr<CommonAPI::Runtime> runtime1 = CommonAPI::Runtime::load("DBus");
+ std::shared_ptr<CommonAPI::Runtime> runtime2 = CommonAPI::Runtime::load("DBus");
+ ASSERT_TRUE((bool)runtime1);
+ ASSERT_TRUE((bool)runtime2);
+
+ CommonAPI::DBus::DBusRuntime* dbusRuntime1 = dynamic_cast<CommonAPI::DBus::DBusRuntime*>(&(*runtime1));
+ CommonAPI::DBus::DBusRuntime* dbusRuntime2 = dynamic_cast<CommonAPI::DBus::DBusRuntime*>(&(*runtime2));
+ ASSERT_TRUE(dbusRuntime1 != NULL);
+ ASSERT_TRUE(dbusRuntime2 != NULL);
+
+ ASSERT_TRUE(dbusRuntime1 == dbusRuntime2);
+}
+
+
+TEST_F(DBusRuntimeTest, ReturnsEmptyPointerOnRequestForUnknownMiddleware) {
+ std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("UnknownMiddlewareId");
+ ASSERT_FALSE((bool)runtime);
+}
+
+
+TEST_F(DBusRuntimeTest, DBusRuntimeLoadsDBusFactory) {
+ std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("DBus");
+ ASSERT_TRUE((bool)runtime);
+ CommonAPI::DBus::DBusRuntime* dbusRuntime = dynamic_cast<CommonAPI::DBus::DBusRuntime*>(&(*runtime));
+ ASSERT_TRUE(dbusRuntime != NULL);
+
+ std::shared_ptr<CommonAPI::Factory> proxyFactory = runtime->createFactory();
+ ASSERT_TRUE((bool)proxyFactory);
+ CommonAPI::DBus::DBusFactory* dbusProxyFactory = dynamic_cast<CommonAPI::DBus::DBusFactory*>(&(*proxyFactory));
+ ASSERT_TRUE(dbusProxyFactory != NULL);
+}
+
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <iostream>
+
+#include <common-api-dbus/dbus-message.h>
+
+#include "TestDBusSerializableStruct.h"
+
+
+#define COMMON_API_TEST_TEST_STRUCT_SIGNATURE "(ud)"
+#define COMMON_API_TEST_TEST_STRUCT_ARRAY_SIGNATURE "a" COMMON_API_TEST_TEST_STRUCT_SIGNATURE
+
+#define COMMON_API_TEST_TEST_STRUCT_EXTENDED_SIGNATURE "(uds)"
+#define COMMON_API_TEST_TEST_STRUCT_EXTENDED_ARRAY_SIGNATURE "a" COMMON_API_TEST_TEST_STRUCT_EXTENDED_SIGNATURE
+
+
+namespace common {
+namespace api {
+namespace test {
+
+
+TestStruct::TestStruct(const uint32_t& fromIntValue, const double& fromDoubleValue):
+ intValue(fromIntValue),
+ doubleValue(fromDoubleValue) {
+}
+
+common::api::dbus::DBusInputMessageStream& TestStruct::readFromDBusInputMessageStream(
+ common::api::dbus::DBusInputMessageStream& inputMessageStream) {
+ return inputMessageStream >> intValue
+ >> doubleValue;
+}
+
+common::api::dbus::DBusOutputMessageStream& TestStruct::writeToDBusOutputMessageStream(
+ common::api::dbus::DBusOutputMessageStream& outputMessageStream) const {
+ return outputMessageStream << intValue
+ << doubleValue;
+}
+
+
+TestStructExtended::TestStructExtended(const uint32_t& fromIntValue, const double& fromDoubleValue, const std::string& fromStringValue):
+ TestStruct(fromIntValue, fromDoubleValue),
+ stringValue(fromStringValue) {
+}
+
+common::api::dbus::DBusInputMessageStream& TestStructExtended::readFromDBusInputMessageStream(
+ common::api::dbus::DBusInputMessageStream& inputMessageStream) {
+ return TestStruct::readFromDBusInputMessageStream(inputMessageStream) >> stringValue;
+}
+
+common::api::dbus::DBusOutputMessageStream& TestStructExtended::writeToDBusOutputMessageStream(
+ common::api::dbus::DBusOutputMessageStream& outputMessageStream) const {
+ return TestStruct::writeToDBusOutputMessageStream(outputMessageStream) << stringValue;
+}
+
+} //namespace test
+} //namespace api
+} //namespace common
+
+
+int main(void) {
+ using namespace common::api::test;
+
+ TestStructExtended testStructExtended(123, 456.789, "TestStructExtended");
+
+ common::api::dbus::DBusMessage message = common::api::dbus::DBusMessage::createMethodCall(
+ "com.bmw.test.TestStruct",
+ "/com/bmw/test/TestStruct",
+ "com.bmw.test.TestStruct",
+ "SingleTestStruct",
+ COMMON_API_TEST_TEST_STRUCT_EXTENDED_SIGNATURE);
+
+ common::api::dbus::DBusOutputMessageStream outStream(message);
+ outStream << testStructExtended;
+ outStream.flush();
+}
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef DEMO_POSITIONING_H_
+#define DEMO_POSITIONING_H_
+
+
+#include <common-api-dbus/dbus-serializable-struct.h>
+#include <vector>
+
+
+namespace common {
+namespace api {
+namespace test {
+
+
+struct TestStruct: public common::api::dbus::SerializableStruct {
+ TestStruct() = default;
+ TestStruct(const uint32_t& fromIntValue, const double& fromDoubleValue);
+
+ virtual common::api::dbus::DBusInputMessageStream& readFromDBusInputMessageStream(
+ common::api::dbus::DBusInputMessageStream& inputMessageStream);
+
+ virtual common::api::dbus::DBusOutputMessageStream& writeToDBusOutputMessageStream(
+ common::api::dbus::DBusOutputMessageStream& outputMessageStream) const;
+
+ uint32_t intValue;
+ double doubleValue;
+};
+
+
+struct TestStructExtended: public TestStruct {
+ TestStructExtended() = default;
+
+ TestStructExtended(const uint32_t& fromIntValue, const double& fromDoubleValue, const std::string& fromStringValue);
+
+ virtual common::api::dbus::DBusInputMessageStream& readFromDBusInputMessageStream(
+ common::api::dbus::DBusInputMessageStream& inputMessageStream);
+
+ virtual common::api::dbus::DBusOutputMessageStream& writeToDBusOutputMessageStream(
+ common::api::dbus::DBusOutputMessageStream& outputMessageStream) const;
+
+ std::string stringValue;
+};
+
+
+typedef std::vector<TestStruct> TestStructArray;
+typedef std::vector<TestStructExtended> TestStructExtendedArray;
+
+
+} //namespace test
+
+namespace dbus {
+
+template<>
+struct Alignment<common::api::test::TestStruct>: SizeConstant<8> { };
+
+template<>
+struct Alignment<common::api::test::TestStructExtended>: SizeConstant<8> { };
+
+} //namespace dbus
+} //namespace api
+} //namespace common
+
+#endif /* DEMO_POSITIONING_H_ */
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <CommonAPI/Runtime.h>
+
+
+//#define ASSERT_DBUSMESSAGE_EQ(_dbusMessage1, _dbusMessage2) \
+// ASSERT_FALSE(_dbusMessage1.getSignatureString() == NULL); \
+// ASSERT_FALSE(_dbusMessage2.getSignatureString() == NULL); \
+// ASSERT_STREQ(_dbusMessage1.getSignatureString(), _dbusMessage2.getSignatureString()); \
+// ASSERT_EQ(_dbusMessage1.getBodyLength(), _dbusMessage2.getBodyLength()); \
+// ASSERT_FALSE(_dbusMessage1.getBodyData() == NULL); \
+// ASSERT_FALSE(_dbusMessage2.getBodyData() == NULL); \
+// ASSERT_EQ(memcmp(_dbusMessage1.getBodyData(), _dbusMessage2.getBodyData(), _dbusMessage1.getBodyLength()), 0)
+//
+//
+//namespace {
+//
+//class DBusConnectionTest: public ::testing::Test {
+// protected:
+// virtual void SetUp() {
+// }
+//
+// virtual void TearDown() {
+// }
+//};
+//
+//
+//TEST_F(DBusConnectionTest, CanBeConstructed) {
+// std::shared_ptr<CommonAPI::Runtime> runtime = CommonAPI::Runtime::load("");
+// std::shared_ptr<CommonAPI::ProxyFactory> proxyFactory_ = runtime->createProxyFactory();
+//}
+//
+//}
+
+
+int main() {
+
+}
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include <CommonAPI/DBus/DBusFunctionalHash.h>
+#include <CommonAPI/DBus/DBusStubAdapterHelper.h>
+
+#include <cassert>
+#include <iostream>
+#include <tuple>
+
+static uint32_t dispatchedMessageCount;
+
+class TestStubRemoteEventHandler {
+ public:
+ virtual ~TestStubRemoteEventHandler() { }
+
+ virtual bool onRemoteSetTestAttribute(int32_t testValue) = 0;
+
+ virtual void onRemoteTestAttributeChanged() = 0;
+};
+
+class TestStubAdapter: virtual public CommonAPI::StubAdapter {
+ public:
+ virtual void fireTestAttributeChanged(const int32_t& testValue) = 0;
+};
+
+class TestStub: public CommonAPI::Stub<TestStubAdapter, TestStubRemoteEventHandler> {
+ public:
+ TestStub(): remoteEventHandler_(this) {
+ }
+
+ virtual TestStubRemoteEventHandler* initStubAdapter(const std::shared_ptr<TestStubAdapter>& stubAdapter) {
+ return &remoteEventHandler_;
+ }
+
+ void getEmptyResponse() {
+ std::cout << "onGetEmptyResponse()\n";
+ dispatchedMessageCount++;
+ }
+
+ void getDeepCopy(int32_t inValue, int32_t& outValue) {
+ outValue = inValue;
+ std::cout << "getDeepCopy(inValue=" << inValue << ", outValue=" << outValue << ")\n";
+ dispatchedMessageCount++;
+ }
+
+ void getDeepCopies(std::vector<int32_t> inValues, std::vector<int32_t>& outValues) {
+ outValues = inValues;
+ std::cout << "getDeepCopies(inValues=" << inValues.size() << ", outValues=" << outValues.size() << ")\n";
+ dispatchedMessageCount++;
+ }
+
+ void getShallowCopy(int32_t inValue, int32_t& outValue) {
+ outValue = inValue;
+ std::cout << "getShallowCopy(inValue=" << inValue << ", outValue=" << outValue << ")\n";
+ dispatchedMessageCount++;
+ }
+
+ void getShallowCopies(std::vector<int32_t> inValues, std::vector<int32_t>& outValues) {
+ outValues = inValues;
+ std::cout << "getShallowCopies(inValues=" << inValues.size() << ", outValues=" << outValues.size() << ")\n";
+ dispatchedMessageCount++;
+ }
+
+ const int32_t& getTestAttribute() {
+ return testAttributeValue_;
+ }
+
+ private:
+ class RemoteEventHandler: public TestStubRemoteEventHandler {
+ public:
+ RemoteEventHandler(TestStub* stub): stub_(stub) {
+ }
+
+ virtual bool onRemoteSetTestAttribute(int32_t testValue) {
+ std::cout << "RemoteEventHandler::onRemoteSetTestAttribute(" << testValue << "): oldValue = " << stub_->testAttributeValue_ << "\n";
+ const bool valueChanged = (stub_->testAttributeValue_ != testValue);
+ stub_->testAttributeValue_ = testValue;
+ return valueChanged;
+ }
+
+ virtual void onRemoteTestAttributeChanged() {
+ std::cout << "RemoteEventHandler::onRemoteTestAttributeChanged()\n";
+ }
+
+ private:
+ TestStub* stub_;
+ };
+
+ RemoteEventHandler remoteEventHandler_;
+ int32_t testAttributeValue_;
+};
+
+typedef CommonAPI::DBus::DBusStubAdapterHelper<TestStub> TestStubAdapterHelper;
+
+class TestDBusStubAdapter: public TestStubAdapter, public TestStubAdapterHelper {
+ public:
+ TestDBusStubAdapter(const std::string& dbusBusName,
+ const std::string& dbusObjectPath,
+ const std::shared_ptr<CommonAPI::DBus::DBusConnection>& dbusConnection,
+ const std::shared_ptr<TestStub>& testStub) :
+ TestStubAdapterHelper(
+ dbusBusName,
+ dbusObjectPath,
+ "org.genivi.CommonAPI.DBus.TestInterface",
+ dbusConnection,
+ testStub) {
+ }
+
+ virtual void fireTestAttributeChanged(const int32_t& testValue) {
+ std::cout << "TestDBusStubAdapter::fireTestAttributeChanged(" << testValue << ")\n";
+ }
+
+ protected:
+ virtual const char* getMethodsDBusIntrospectionXmlData() const;
+};
+
+const char* TestDBusStubAdapter::getMethodsDBusIntrospectionXmlData() const {
+ return "<method name=\"GetEmptyResponse\">\n"
+ "</method>\n"
+ "<method name=\"GetDeepCopy\">\n"
+ "<arg type=\"i\" name=\"int32InValue\" direction=\"in\"/>\n"
+ "<arg type=\"i\" name=\"int32OutValue\" direction=\"out\"/>\n"
+ "</method>\n"
+ "<method name=\"GetDeepCopies\">\n"
+ "<arg type=\"ai\" name=\"int32InValues\" direction=\"in\"/>\n"
+ "<arg type=\"ai\" name=\"int32OutValues\" direction=\"out\"/>\n"
+ "</method>\n"
+ "<method name=\"GetShallowCopy\">\n"
+ "<arg type=\"i\" name=\"int32InValue\" direction=\"in\"/>\n"
+ "<arg type=\"i\" name=\"int32OutValue\" direction=\"out\"/>\n"
+ "</method>\n"
+ "<method name=\"GetShallowCopies\">\n"
+ "<arg type=\"ai\" name=\"int32InValues\" direction=\"in\"/>\n"
+ "<arg type=\"ai\" name=\"int32OutValues\" direction=\"out\"/>\n"
+ "</method>"
+ "<method name=\"SetTestAttribute\">\n"
+ "<arg type=\"i\" name=\"value\" direction=\"in\"/>\n"
+ "<arg type=\"i\" name=\"value\" direction=\"out\"/>\n"
+ "</method>"
+ ;
+}
+
+namespace {
+static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher<
+ TestStub,
+ std::tuple<>,
+ std::tuple<> > getEmptyResponseStubDispatcher(&TestStub::getEmptyResponse, "");
+static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher<
+ TestStub,
+ std::tuple<int32_t>,
+ std::tuple<int32_t> > getDeepCopyStubDispatcher(&TestStub::getDeepCopy, "i");
+static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher<
+ TestStub,
+ std::tuple<std::vector<int32_t>>,
+ std::tuple<std::vector<int32_t>> > getDeepCopiesStubDispatcher(&TestStub::getDeepCopies, "ai");
+static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher<
+ TestStub,
+ std::tuple<int32_t>,
+ std::tuple<int32_t> > getShallowCopyStubDispatcher(&TestStub::getShallowCopy, "i");
+static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher<
+ TestStub,
+ std::tuple<std::vector<int32_t>>,
+ std::tuple<std::vector<int32_t>> > getShallowCopiesStubDispatcher(&TestStub::getShallowCopies, "ai");
+static CommonAPI::DBus::DBusSetObservableAttributeStubDispatcher<TestStub, int32_t> setTestAttributeStubDispatcher(
+ &TestStub::getTestAttribute,
+ &TestStubRemoteEventHandler::onRemoteSetTestAttribute,
+ &TestStubRemoteEventHandler::onRemoteTestAttributeChanged,
+ &TestStubAdapter::fireTestAttributeChanged,
+ "i");
+}
+
+template<>
+const TestStubAdapterHelper::StubDispatcherTable TestStubAdapterHelper::stubDispatcherTable_ = {
+ { {"GetEmptyResponse", ""}, &getEmptyResponseStubDispatcher },
+ { {"GetDeepCopy", "i"}, &getDeepCopyStubDispatcher },
+ { {"GetDeepCopies", "ai"}, &getDeepCopiesStubDispatcher },
+ { {"GetShallowCopy", "i"}, &getShallowCopyStubDispatcher },
+ { {"GetShallowCopies", "ai"}, &getShallowCopiesStubDispatcher },
+ { {"SetTestAttribute", "i"}, &setTestAttributeStubDispatcher }
+};
+
+int main(void) {
+ auto dbusConnection = CommonAPI::DBus::DBusConnection::getSessionBus();
+
+ if (!dbusConnection->isConnected())
+ dbusConnection->connect();
+
+ assert(dbusConnection->isConnected());
+
+ const bool serviceNameAcquired = dbusConnection->requestServiceNameAndBlock(
+ "org.genivi.CommonAPI.DBus.TestDBusInterfaceAdapter");
+ assert(serviceNameAcquired);
+
+ auto testStub = std::make_shared<TestStub>();
+ auto testStubAdapter = std::make_shared<TestDBusStubAdapter>(
+ "org.genivi.CommonAPI.DBus.TestDBusInterfaceAdapter",
+ "/common/api/dbus/TestDBusInterfaceAdapter",
+ dbusConnection,
+ testStub);
+ testStubAdapter->init();
+
+ auto dbusMessageCall = CommonAPI::DBus::DBusMessage::createMethodCall(
+ "org.genivi.CommonAPI.DBus.TestDBusInterfaceAdapter",
+ testStubAdapter->getObjectPath().c_str(),
+ testStubAdapter->getServiceId().c_str(),
+ "GetEmptyResponse");
+
+ const bool messageSent = dbusConnection->sendDBusMessage(dbusMessageCall);
+ assert(messageSent);
+
+ for (int i = 0; i < 10; i++)
+ dbusConnection->readWriteDispatch(100);
+
+// while (dbusConnection->readWriteDispatch(100))
+// ;
+
+ assert(dispatchedMessageCount > 0);
+
+ return 0;
+}
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include <iostream>
+#include <string>
+#include <tuple>
+#include <type_traits>
+
+template <typename _SearchType, typename _CurrentType, typename... _RestTypes>
+struct VariantTypeSelector: VariantTypeSelector<_SearchType, _RestTypes...> {
+};
+
+template <typename _SearchType, typename... _RestTypes>
+struct VariantTypeSelector<_SearchType, _SearchType, _RestTypes...> {
+ typedef _SearchType type;
+};
+
+template <typename... _Types>
+class Variant {
+ private:
+ typedef std::tuple_size<std::tuple<_Types...>> TypesTupleSize;
+
+ public:
+ Variant(): valueType_(TypesTupleSize::value) {
+ }
+
+ Variant(const Variant& fromVariant):
+ valueType_(fromVariant.valueType_),
+ valueStorage_(fromVariant.valueStorage_) {
+ }
+
+ Variant(Variant&& fromVariant):
+ valueType_(std::move(fromVariant.valueType_)),
+ valueStorage_(std::move(fromVariant.valueStorage_)) {
+ fromVariant.valueType_ = TypesTupleSize::value;
+ }
+
+ ~Variant() {
+ if (hasValue()) {
+ // TODO call value destructor
+ }
+ }
+
+ Variant& operator=(const Variant& fromVariant) {
+ // TODO
+ return *this;
+ }
+
+ Variant& operator=(Variant&& fromVariant) {
+ // TODO
+ return *this;
+ }
+
+ // TODO use std::enable_if
+ template <typename _Type>
+ Variant(const _Type& value) {
+ // TODO index by type
+ valueType_ = 0;
+ new (&valueStorage_) _Type(value);
+ }
+
+ // TODO use std::enable_if
+ template <typename _Type>
+ Variant(_Type && value) {
+ // TODO index by type
+ valueType_ = 0;
+ new (&valueStorage_) typename std::remove_reference<_Type>::type(std::move(value));
+ }
+
+ template <typename _Type>
+ const typename VariantTypeSelector<_Type, _Types...>::type & get(bool& success) const {
+ // TODO assert _Type in _Types
+ success = true;
+ return *(reinterpret_cast<const _Type *>(&valueStorage_));
+ }
+
+ private:
+ inline bool hasValue() const {
+ return valueType_ < TypesTupleSize::value;
+ }
+
+ size_t valueType_;
+ // TODO calculate maximum storage
+ std::aligned_storage<80>::type valueStorage_;
+};
+
+
+
+int main(int argc, char** argv) {
+ int fromInt = 5;
+ Variant<int, double, double, std::string> myVariant(fromInt);
+ bool success;
+ const int& myInt = myVariant.get<int>(success);
+// const float& myFloat = myVariant.get<float>(success);
+
+ std::cout << "myInt = " << myInt << " (" << std::boolalpha << success << ")\n";
+ return 0;
+}
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "DerivedTypeCollection.h"
+
+namespace commonapi {
+namespace tests {
+namespace DerivedTypeCollection {
+
+TestStruct::TestStruct(const PredefinedTypeCollection::TestString& testStringValue, const uint16_t& uintValueValue):
+ testString(testStringValue),
+ uintValue(uintValueValue)
+{
+}
+
+bool operator==(const TestStruct& lhs, const TestStruct& rhs) {
+ if (&lhs == &rhs)
+ return true;
+
+ return
+ lhs.testString == rhs.testString &&
+ lhs.uintValue == rhs.uintValue
+ ;
+}
+
+void TestStruct::readFromInputStream(CommonAPI::InputStream& inputStream) {
+ inputStream >> testString;
+ inputStream >> uintValue;
+}
+
+void TestStruct::writeToOutputStream(CommonAPI::OutputStream& outputStream) const {
+ outputStream << testString;
+ outputStream << uintValue;
+}
+TestStructExtended::TestStructExtended(const PredefinedTypeCollection::TestString& testStringValue, const uint16_t& uintValueValue, const TestEnumExtended2& testEnumExtended2Value):
+ TestStruct(testStringValue, uintValueValue),
+ testEnumExtended2(testEnumExtended2Value)
+{
+}
+
+bool operator==(const TestStructExtended& lhs, const TestStructExtended& rhs) {
+ if (&lhs == &rhs)
+ return true;
+
+ return
+ static_cast<TestStructExtended::TestStruct>(lhs) == static_cast<TestStructExtended::TestStruct>(rhs) &&
+ lhs.testEnumExtended2 == rhs.testEnumExtended2
+ ;
+}
+
+void TestStructExtended::readFromInputStream(CommonAPI::InputStream& inputStream) {
+ TestStruct::readFromInputStream(inputStream);
+ inputStream >> testEnumExtended2;
+}
+
+void TestStructExtended::writeToOutputStream(CommonAPI::OutputStream& outputStream) const {
+ TestStruct::writeToOutputStream(outputStream);
+ outputStream << testEnumExtended2;
+}
+
+} // namespace DerivedTypeCollection
+} // namespace tests
+} // namespace commonapi
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_TESTS_DERIVED_TYPE_COLLECTION_H_
+#define COMMONAPI_TESTS_DERIVED_TYPE_COLLECTION_H_
+
+#include <CommonAPI/InputStream.h>
+#include <CommonAPI/OutputStream.h>
+#include <CommonAPI/SerializableStruct.h>
+#include <CommonAPI/types.h>
+#include "PredefinedTypeCollection.h"
+#include <cstdint>
+#include <unordered_map>
+#include <vector>
+
+namespace commonapi {
+namespace tests {
+
+namespace DerivedTypeCollection {
+
+enum class TestEnum: int32_t {
+ E_UNKNOWN = 0,
+ E_OK = 1,
+ E_OUT_OF_RANGE = 2,
+ E_NOT_USED = 3
+};
+
+// XXX Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1
+struct TestEnumComparator;
+
+enum class TestEnumMissingValue: int32_t {
+ E1 = 10,
+ E2,
+ E3 = 2
+};
+
+// XXX Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1
+struct TestEnumMissingValueComparator;
+
+enum class TestEnumExtended: int32_t {
+ E_UNKNOWN = TestEnum::E_UNKNOWN,
+ E_OK = TestEnum::E_OK,
+ E_OUT_OF_RANGE = TestEnum::E_OUT_OF_RANGE,
+ E_NOT_USED = TestEnum::E_NOT_USED
+ ,
+ E_NEW = 4
+};
+
+// XXX Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1
+struct TestEnumExtendedComparator;
+
+enum class TestEnumExtended2: int32_t {
+ E_UNKNOWN = TestEnum::E_UNKNOWN,
+ E_OK = TestEnum::E_OK,
+ E_OUT_OF_RANGE = TestEnum::E_OUT_OF_RANGE,
+ E_NOT_USED = TestEnum::E_NOT_USED,
+
+ E_NEW = TestEnumExtended::E_NEW
+ ,
+ E_NEW2 = 5
+};
+
+// XXX Definition of a comparator still is necessary for GCC 4.4.1, topic is fixed since 4.5.1
+struct TestEnumExtended2Comparator;
+
+struct TestStruct: CommonAPI::SerializableStruct {
+ PredefinedTypeCollection::TestString testString;
+ uint16_t uintValue;
+
+ TestStruct() = default;
+ TestStruct(const PredefinedTypeCollection::TestString& testString, const uint16_t& uintValue);
+
+ virtual void readFromInputStream(CommonAPI::InputStream& inputStream);
+ virtual void writeToOutputStream(CommonAPI::OutputStream& outputStream) const;
+};
+
+struct TestStructExtended: TestStruct {
+ TestEnumExtended2 testEnumExtended2;
+
+ TestStructExtended() = default;
+ TestStructExtended(const PredefinedTypeCollection::TestString& testString, const uint16_t& uintValue, const TestEnumExtended2& testEnumExtended2);
+
+ virtual void readFromInputStream(CommonAPI::InputStream& inputStream);
+ virtual void writeToOutputStream(CommonAPI::OutputStream& outputStream) const;
+};
+
+typedef std::vector<uint64_t> TestArrayUInt64;
+
+typedef std::vector<TestStruct> TestArrayTestStruct;
+
+typedef std::unordered_map<uint32_t, TestArrayTestStruct> TestMap;
+
+inline CommonAPI::InputStream& operator>>(CommonAPI::InputStream& inputStream, TestEnum& enumValue) {
+ return inputStream.readEnumValue<int32_t>(enumValue);
+}
+
+inline CommonAPI::OutputStream& operator<<(CommonAPI::OutputStream& outputStream, const TestEnum& enumValue) {
+ return outputStream.writeEnumValue(static_cast<int32_t>(enumValue));
+}
+
+struct TestEnumComparator {
+ inline bool operator()(const TestEnum& lhs, const TestEnum& rhs) const {
+ return static_cast<int32_t>(lhs) < static_cast<int32_t>(rhs);
+ }
+};
+
+inline CommonAPI::InputStream& operator>>(CommonAPI::InputStream& inputStream, TestEnumMissingValue& enumValue) {
+ return inputStream.readEnumValue<int32_t>(enumValue);
+}
+
+inline CommonAPI::OutputStream& operator<<(CommonAPI::OutputStream& outputStream, const TestEnumMissingValue& enumValue) {
+ return outputStream.writeEnumValue(static_cast<int32_t>(enumValue));
+}
+
+struct TestEnumMissingValueComparator {
+ inline bool operator()(const TestEnumMissingValue& lhs, const TestEnumMissingValue& rhs) const {
+ return static_cast<int32_t>(lhs) < static_cast<int32_t>(rhs);
+ }
+};
+
+inline CommonAPI::InputStream& operator>>(CommonAPI::InputStream& inputStream, TestEnumExtended& enumValue) {
+ return inputStream.readEnumValue<int32_t>(enumValue);
+}
+
+inline CommonAPI::OutputStream& operator<<(CommonAPI::OutputStream& outputStream, const TestEnumExtended& enumValue) {
+ return outputStream.writeEnumValue(static_cast<int32_t>(enumValue));
+}
+
+struct TestEnumExtendedComparator {
+ inline bool operator()(const TestEnumExtended& lhs, const TestEnumExtended& rhs) const {
+ return static_cast<int32_t>(lhs) < static_cast<int32_t>(rhs);
+ }
+};
+
+
+inline bool operator==(const TestEnumExtended& lhs, const TestEnum& rhs) {
+ return static_cast<int32_t>(lhs) == static_cast<int32_t>(rhs);
+}
+inline bool operator==(const TestEnum& lhs, const TestEnumExtended& rhs) {
+ return static_cast<int32_t>(lhs) == static_cast<int32_t>(rhs);
+}
+inline bool operator!=(const TestEnumExtended& lhs, const TestEnum& rhs) {
+ return static_cast<int32_t>(lhs) != static_cast<int32_t>(rhs);
+}
+inline bool operator!=(const TestEnum& lhs, const TestEnumExtended& rhs) {
+ return static_cast<int32_t>(lhs) != static_cast<int32_t>(rhs);
+}
+inline CommonAPI::InputStream& operator>>(CommonAPI::InputStream& inputStream, TestEnumExtended2& enumValue) {
+ return inputStream.readEnumValue<int32_t>(enumValue);
+}
+
+inline CommonAPI::OutputStream& operator<<(CommonAPI::OutputStream& outputStream, const TestEnumExtended2& enumValue) {
+ return outputStream.writeEnumValue(static_cast<int32_t>(enumValue));
+}
+
+struct TestEnumExtended2Comparator {
+ inline bool operator()(const TestEnumExtended2& lhs, const TestEnumExtended2& rhs) const {
+ return static_cast<int32_t>(lhs) < static_cast<int32_t>(rhs);
+ }
+};
+
+
+inline bool operator==(const TestEnumExtended2& lhs, const TestEnum& rhs) {
+ return static_cast<int32_t>(lhs) == static_cast<int32_t>(rhs);
+}
+inline bool operator==(const TestEnum& lhs, const TestEnumExtended2& rhs) {
+ return static_cast<int32_t>(lhs) == static_cast<int32_t>(rhs);
+}
+inline bool operator!=(const TestEnumExtended2& lhs, const TestEnum& rhs) {
+ return static_cast<int32_t>(lhs) != static_cast<int32_t>(rhs);
+}
+inline bool operator!=(const TestEnum& lhs, const TestEnumExtended2& rhs) {
+ return static_cast<int32_t>(lhs) != static_cast<int32_t>(rhs);
+}
+
+inline bool operator==(const TestEnumExtended2& lhs, const TestEnumExtended& rhs) {
+ return static_cast<int32_t>(lhs) == static_cast<int32_t>(rhs);
+}
+inline bool operator==(const TestEnumExtended& lhs, const TestEnumExtended2& rhs) {
+ return static_cast<int32_t>(lhs) == static_cast<int32_t>(rhs);
+}
+inline bool operator!=(const TestEnumExtended2& lhs, const TestEnumExtended& rhs) {
+ return static_cast<int32_t>(lhs) != static_cast<int32_t>(rhs);
+}
+inline bool operator!=(const TestEnumExtended& lhs, const TestEnumExtended2& rhs) {
+ return static_cast<int32_t>(lhs) != static_cast<int32_t>(rhs);
+}
+bool operator==(const TestStruct& lhs, const TestStruct& rhs);
+inline bool operator!=(const TestStruct& lhs, const TestStruct& rhs) {
+ return !(lhs == rhs);
+}
+bool operator==(const TestStructExtended& lhs, const TestStructExtended& rhs);
+inline bool operator!=(const TestStructExtended& lhs, const TestStructExtended& rhs) {
+ return !(lhs == rhs);
+}
+
+
+static inline const char* getTypeCollectionName() {
+ return "commonapi.tests.DerivedTypeCollection";
+}
+
+
+} // namespace DerivedTypeCollection
+
+} // namespace tests
+} // namespace commonapi
+
+#endif // COMMONAPI_TESTS_DERIVED_TYPE_COLLECTION_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_TESTS_PREDEFINED_TYPE_COLLECTION_H_
+#define COMMONAPI_TESTS_PREDEFINED_TYPE_COLLECTION_H_
+
+#include <CommonAPI/ByteBuffer.h>
+#include <CommonAPI/types.h>
+#include <cstdint>
+#include <string>
+
+namespace commonapi {
+namespace tests {
+
+namespace PredefinedTypeCollection {
+
+typedef uint8_t TestUInt8;
+
+typedef uint16_t TestUInt16;
+
+typedef uint32_t TestUInt32;
+
+typedef uint64_t TestUInt64;
+
+typedef int8_t TestInt8;
+
+typedef int16_t TestInt16;
+
+typedef int32_t TestInt32;
+
+typedef int64_t TestInt64;
+
+typedef bool TestBoolean;
+
+typedef CommonAPI::ByteBuffer TestByteBuffer;
+
+typedef double TestDouble;
+
+typedef float TestFloat;
+
+typedef std::string TestString;
+
+
+
+static inline const char* getTypeCollectionName() {
+ return "commonapi.tests.PredefinedTypeCollection";
+}
+
+
+} // namespace PredefinedTypeCollection
+
+} // namespace tests
+} // namespace commonapi
+
+#endif // COMMONAPI_TESTS_PREDEFINED_TYPE_COLLECTION_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_TESTS_TEST_INTERFACE_H_
+#define COMMONAPI_TESTS_TEST_INTERFACE_H_
+
+#include <CommonAPI/types.h>
+
+namespace commonapi {
+namespace tests {
+
+class TestInterface {
+ public:
+ virtual ~TestInterface() { }
+
+ static inline const char* getInterfaceName();
+ static inline CommonAPI::Version getInterfaceVersion();
+};
+
+const char* TestInterface::getInterfaceName() {
+ return "commonapi.tests.TestInterface";
+}
+
+CommonAPI::Version TestInterface::getInterfaceVersion() {
+ return CommonAPI::Version(1, 0);
+}
+
+
+} // namespace tests
+} // namespace commonapi
+
+#endif // COMMONAPI_TESTS_TEST_INTERFACE_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "TestInterfaceDBusProxy.h"
+
+namespace commonapi {
+namespace tests {
+
+std::shared_ptr<CommonAPI::DBus::DBusProxy> createTestInterfaceDBusProxy(const char* busName,
+ const char* objectPath,
+ std::shared_ptr<CommonAPI::DBus::DBusProxyConnection> dbusProxyConnection) {
+ return std::make_shared<TestInterfaceDBusProxy>(busName, objectPath, dbusProxyConnection);
+}
+
+__attribute__((constructor)) void registerTestInterfaceDBusProxy(void) {
+ CommonAPI::DBus::DBusFactory::registerProxyFactoryMethod(TestInterface::getInterfaceName(),
+ &createTestInterfaceDBusProxy);
+}
+
+TestInterfaceDBusProxy::TestInterfaceDBusProxy(const std::string& busName, const std::string& objectPath, const std::shared_ptr<CommonAPI::DBus::DBusProxyConnection>& dbusProxyconnection):
+ CommonAPI::DBus::DBusProxy(busName, objectPath, TestInterface::getInterfaceName(), dbusProxyconnection)
+, testPredefinedTypeAttribute_(*this, "onTestPredefinedTypeAttributeAttributeChanged", "setTestPredefinedTypeAttributeAttribute", "u", "getTestPredefinedTypeAttributeAttribute"),
+ testDerivedStructAttribute_(*this, "onTestDerivedStructAttributeAttributeChanged", "setTestDerivedStructAttributeAttribute", "(sqi)", "getTestDerivedStructAttributeAttribute"),
+ testDerivedArrayAttribute_(*this, "onTestDerivedArrayAttributeAttributeChanged", "setTestDerivedArrayAttributeAttribute", "at", "getTestDerivedArrayAttributeAttribute")
+, testPredefinedTypeBroadcast_(*this, "TestPredefinedTypeBroadcast", "us")
+ {
+}
+
+TestInterfaceDBusProxy::TestPredefinedTypeAttributeAttribute& TestInterfaceDBusProxy::getTestPredefinedTypeAttributeAttribute() {
+ return testPredefinedTypeAttribute_;
+}
+TestInterfaceDBusProxy::TestDerivedStructAttributeAttribute& TestInterfaceDBusProxy::getTestDerivedStructAttributeAttribute() {
+ return testDerivedStructAttribute_;
+}
+TestInterfaceDBusProxy::TestDerivedArrayAttributeAttribute& TestInterfaceDBusProxy::getTestDerivedArrayAttributeAttribute() {
+ return testDerivedArrayAttribute_;
+}
+
+TestInterfaceDBusProxy::TestPredefinedTypeBroadcastEvent& TestInterfaceDBusProxy::getTestPredefinedTypeBroadcastEvent() {
+ return testPredefinedTypeBroadcast_;
+}
+
+void TestInterfaceDBusProxy::testVoidPredefinedTypeMethod(const uint32_t& uint32Value, const std::string& stringValue, CommonAPI::CallStatus& callStatus) {
+ CommonAPI::DBus::DBusProxyHelper<CommonAPI::DBus::DBusSerializableArguments<uint32_t, std::string>,
+ CommonAPI::DBus::DBusSerializableArguments<> >::callMethodWithReply(
+ *this,
+ "testVoidPredefinedTypeMethod",
+ "us",
+ uint32Value, stringValue,
+ callStatus
+ );
+}
+std::future<CommonAPI::CallStatus> TestInterfaceDBusProxy::testVoidPredefinedTypeMethodAsync(const uint32_t& uint32Value, const std::string& stringValue, TestVoidPredefinedTypeMethodAsyncCallback callback) {
+ return CommonAPI::DBus::DBusProxyHelper<CommonAPI::DBus::DBusSerializableArguments<uint32_t, std::string>,
+ CommonAPI::DBus::DBusSerializableArguments<> >::callMethodAsync(
+ *this,
+ "testVoidPredefinedTypeMethod",
+ "us",
+ uint32Value, stringValue,
+ std::move(callback));
+}
+void TestInterfaceDBusProxy::testPredefinedTypeMethod(const uint32_t& uint32InValue, const std::string& stringInValue, CommonAPI::CallStatus& callStatus, uint32_t& uint32OutValue, std::string& stringOutValue) {
+ CommonAPI::DBus::DBusProxyHelper<CommonAPI::DBus::DBusSerializableArguments<uint32_t, std::string>,
+ CommonAPI::DBus::DBusSerializableArguments<uint32_t, std::string> >::callMethodWithReply(
+ *this,
+ "testPredefinedTypeMethod",
+ "us",
+ uint32InValue, stringInValue,
+ callStatus
+ , uint32OutValue, stringOutValue);
+}
+std::future<CommonAPI::CallStatus> TestInterfaceDBusProxy::testPredefinedTypeMethodAsync(const uint32_t& uint32InValue, const std::string& stringInValue, TestPredefinedTypeMethodAsyncCallback callback) {
+ return CommonAPI::DBus::DBusProxyHelper<CommonAPI::DBus::DBusSerializableArguments<uint32_t, std::string>,
+ CommonAPI::DBus::DBusSerializableArguments<uint32_t, std::string> >::callMethodAsync(
+ *this,
+ "testPredefinedTypeMethod",
+ "us",
+ uint32InValue, stringInValue,
+ std::move(callback));
+}
+void TestInterfaceDBusProxy::testVoidDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, CommonAPI::CallStatus& callStatus) {
+ CommonAPI::DBus::DBusProxyHelper<CommonAPI::DBus::DBusSerializableArguments<DerivedTypeCollection::TestEnumExtended2, DerivedTypeCollection::TestMap>,
+ CommonAPI::DBus::DBusSerializableArguments<> >::callMethodWithReply(
+ *this,
+ "testVoidDerivedTypeMethod",
+ "ia{ua(sq)}",
+ testEnumExtended2Value, testMapValue,
+ callStatus
+ );
+}
+std::future<CommonAPI::CallStatus> TestInterfaceDBusProxy::testVoidDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, TestVoidDerivedTypeMethodAsyncCallback callback) {
+ return CommonAPI::DBus::DBusProxyHelper<CommonAPI::DBus::DBusSerializableArguments<DerivedTypeCollection::TestEnumExtended2, DerivedTypeCollection::TestMap>,
+ CommonAPI::DBus::DBusSerializableArguments<> >::callMethodAsync(
+ *this,
+ "testVoidDerivedTypeMethod",
+ "ia{ua(sq)}",
+ testEnumExtended2Value, testMapValue,
+ std::move(callback));
+}
+void TestInterfaceDBusProxy::testDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, CommonAPI::CallStatus& callStatus, DerivedTypeCollection::TestEnumExtended2& testEnumExtended2OutValue, DerivedTypeCollection::TestMap& testMapOutValue) {
+ CommonAPI::DBus::DBusProxyHelper<CommonAPI::DBus::DBusSerializableArguments<DerivedTypeCollection::TestEnumExtended2, DerivedTypeCollection::TestMap>,
+ CommonAPI::DBus::DBusSerializableArguments<DerivedTypeCollection::TestEnumExtended2, DerivedTypeCollection::TestMap> >::callMethodWithReply(
+ *this,
+ "testDerivedTypeMethod",
+ "ia{ua(sq)}",
+ testEnumExtended2InValue, testMapInValue,
+ callStatus
+ , testEnumExtended2OutValue, testMapOutValue);
+}
+std::future<CommonAPI::CallStatus> TestInterfaceDBusProxy::testDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, TestDerivedTypeMethodAsyncCallback callback) {
+ return CommonAPI::DBus::DBusProxyHelper<CommonAPI::DBus::DBusSerializableArguments<DerivedTypeCollection::TestEnumExtended2, DerivedTypeCollection::TestMap>,
+ CommonAPI::DBus::DBusSerializableArguments<DerivedTypeCollection::TestEnumExtended2, DerivedTypeCollection::TestMap> >::callMethodAsync(
+ *this,
+ "testDerivedTypeMethod",
+ "ia{ua(sq)}",
+ testEnumExtended2InValue, testMapInValue,
+ std::move(callback));
+}
+
+void TestInterfaceDBusProxy::getOwnVersion(uint16_t& ownVersionMajor, uint16_t& ownVersionMinor) const {
+ ownVersionMajor = 1;
+ ownVersionMinor = 0;
+}
+
+} // namespace tests
+} // namespace commonapi
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_TESTS_TEST_INTERFACE_DBUS_PROXY_H_
+#define COMMONAPI_TESTS_TEST_INTERFACE_DBUS_PROXY_H_
+
+#include "TestInterfaceProxyBase.h"
+#include <CommonAPI/DBus/DBusFactory.h>
+#include <CommonAPI/DBus/DBusProxy.h>
+#include <CommonAPI/DBus/DBusAttribute.h>
+#include <CommonAPI/DBus/DBusEvent.h>
+
+#include <string>
+
+namespace commonapi {
+namespace tests {
+
+class TestInterfaceDBusProxy: virtual public TestInterfaceProxyBase, virtual public CommonAPI::DBus::DBusProxy {
+ public:
+ TestInterfaceDBusProxy(const std::string& busName, const std::string& objectPath, const std::shared_ptr<CommonAPI::DBus::DBusProxyConnection>& dbusProxyconnection);
+
+ virtual TestPredefinedTypeAttributeAttribute& getTestPredefinedTypeAttributeAttribute();
+ virtual TestDerivedStructAttributeAttribute& getTestDerivedStructAttributeAttribute();
+ virtual TestDerivedArrayAttributeAttribute& getTestDerivedArrayAttributeAttribute();
+
+ virtual TestPredefinedTypeBroadcastEvent& getTestPredefinedTypeBroadcastEvent();
+
+
+ virtual void testVoidPredefinedTypeMethod(const uint32_t& uint32Value, const std::string& stringValue, CommonAPI::CallStatus& callStatus);
+ virtual std::future<CommonAPI::CallStatus> testVoidPredefinedTypeMethodAsync(const uint32_t& uint32Value, const std::string& stringValue, TestVoidPredefinedTypeMethodAsyncCallback callback);
+
+ virtual void testPredefinedTypeMethod(const uint32_t& uint32InValue, const std::string& stringInValue, CommonAPI::CallStatus& callStatus, uint32_t& uint32OutValue, std::string& stringOutValue);
+ virtual std::future<CommonAPI::CallStatus> testPredefinedTypeMethodAsync(const uint32_t& uint32InValue, const std::string& stringInValue, TestPredefinedTypeMethodAsyncCallback callback);
+
+ virtual void testVoidDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, CommonAPI::CallStatus& callStatus);
+ virtual std::future<CommonAPI::CallStatus> testVoidDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, TestVoidDerivedTypeMethodAsyncCallback callback);
+
+ virtual void testDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, CommonAPI::CallStatus& callStatus, DerivedTypeCollection::TestEnumExtended2& testEnumExtended2OutValue, DerivedTypeCollection::TestMap& testMapOutValue);
+ virtual std::future<CommonAPI::CallStatus> testDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, TestDerivedTypeMethodAsyncCallback callback);
+
+ virtual void getOwnVersion(uint16_t& ownVersionMajor, uint16_t& ownVersionMinor) const;
+
+ private:
+ CommonAPI::DBus::DBusObservableAttribute<CommonAPI::DBus::DBusAttribute<TestPredefinedTypeAttributeAttribute>> testPredefinedTypeAttribute_;
+ CommonAPI::DBus::DBusObservableAttribute<CommonAPI::DBus::DBusAttribute<TestDerivedStructAttributeAttribute>> testDerivedStructAttribute_;
+ CommonAPI::DBus::DBusObservableAttribute<CommonAPI::DBus::DBusAttribute<TestDerivedArrayAttributeAttribute>> testDerivedArrayAttribute_;
+
+ CommonAPI::DBus::DBusEvent<TestPredefinedTypeBroadcastEvent> testPredefinedTypeBroadcast_;
+};
+
+} // namespace tests
+} // namespace commonapi
+
+#endif // COMMONAPI_TESTS_TEST_INTERFACE_DBUS_PROXY_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "TestInterfaceDBusStubAdapter.h"
+#include "TestInterface.h"
+
+namespace commonapi {
+namespace tests {
+
+std::shared_ptr<CommonAPI::DBus::DBusStubAdapter> createTestInterfaceDBusStubAdapter(std::string busName,
+ std::string objectPath,
+ std::shared_ptr<CommonAPI::DBus::DBusProxyConnection> dbusProxyConnection,
+ std::shared_ptr<CommonAPI::StubBase> stubBase) {
+ return std::make_shared<TestInterfaceDBusStubAdapter>(busName, objectPath, dbusProxyConnection, stubBase);
+}
+
+__attribute__((constructor)) void registerTestInterfaceDBusStubAdapter(void) {
+ CommonAPI::DBus::DBusFactory::registerAdapterFactoryMethod(TestInterface::getInterfaceName(),
+ &createTestInterfaceDBusStubAdapter);
+}
+
+TestInterfaceDBusStubAdapter::TestInterfaceDBusStubAdapter(
+ const std::string& dbusBusName,
+ const std::string& dbusObjectPath,
+ const std::shared_ptr<CommonAPI::DBus::DBusProxyConnection>& dbusConnection,
+ const std::shared_ptr<CommonAPI::StubBase>& stub):
+ TestInterfaceDBusStubAdapterHelper(dbusBusName, dbusObjectPath, TestInterface::getInterfaceName(), dbusConnection, std::dynamic_pointer_cast<TestInterfaceStub>(stub)) {
+}
+
+const char* TestInterfaceDBusStubAdapter::getMethodsDBusIntrospectionXmlData() const {
+ return
+ "<method name=\"getTestPredefinedTypeAttributeAttribute\">\n"
+ "<arg name=\"value\" type=\"u\" direction=\"out\" />"
+ "</method>\n"
+ "<method name=\"setTestPredefinedTypeAttributeAttribute\">\n"
+ "<arg name=\"requestedValue\" type=\"u\" direction=\"in\" />\n"
+ "<arg name=\"setValue\" type=\"u\" direction=\"out\" />\n"
+ "</method>\n"
+ "<signal name=\"onTestPredefinedTypeAttributeAttributeChanged\">\n"
+ "<arg name=\"changedValue\" type=\"u\" />\n"
+ "</signal>\n"
+ "<method name=\"getTestDerivedStructAttributeAttribute\">\n"
+ "<arg name=\"value\" type=\"(sqi)\" direction=\"out\" />"
+ "</method>\n"
+ "<method name=\"setTestDerivedStructAttributeAttribute\">\n"
+ "<arg name=\"requestedValue\" type=\"(sqi)\" direction=\"in\" />\n"
+ "<arg name=\"setValue\" type=\"(sqi)\" direction=\"out\" />\n"
+ "</method>\n"
+ "<signal name=\"onTestDerivedStructAttributeAttributeChanged\">\n"
+ "<arg name=\"changedValue\" type=\"(sqi)\" />\n"
+ "</signal>\n"
+ "<method name=\"getTestDerivedArrayAttributeAttribute\">\n"
+ "<arg name=\"value\" type=\"at\" direction=\"out\" />"
+ "</method>\n"
+ "<method name=\"setTestDerivedArrayAttributeAttribute\">\n"
+ "<arg name=\"requestedValue\" type=\"at\" direction=\"in\" />\n"
+ "<arg name=\"setValue\" type=\"at\" direction=\"out\" />\n"
+ "</method>\n"
+ "<signal name=\"onTestDerivedArrayAttributeAttributeChanged\">\n"
+ "<arg name=\"changedValue\" type=\"at\" />\n"
+ "</signal>\n"
+ "<signal name=\"TestPredefinedTypeBroadcast\">\n"
+ "<arg name=\"uint32Value\" type=\"u\" />\n"
+ "<arg name=\"stringValue\" type=\"s\" />\n"
+ "</signal>\n"
+ "<method name=\"testVoidPredefinedTypeMethod\">\n"
+ "<arg name=\"uint32Value\" type=\"u\" direction=\"in\" />\n"
+ "<arg name=\"stringValue\" type=\"s\" direction=\"in\" />\n"
+ "<arg name=\"uint32Value\" type=\"u\" direction=\"out\" />\n"
+ "<arg name=\"stringValue\" type=\"s\" direction=\"out\" />\n"
+ "</method>\n"
+ "<method name=\"testPredefinedTypeMethod\">\n"
+ "<arg name=\"uint32InValue\" type=\"u\" direction=\"in\" />\n"
+ "<arg name=\"stringInValue\" type=\"s\" direction=\"in\" />\n"
+ "<arg name=\"uint32InValue\" type=\"u\" direction=\"out\" />\n"
+ "<arg name=\"stringInValue\" type=\"s\" direction=\"out\" />\n"
+ "</method>\n"
+ "<method name=\"testVoidDerivedTypeMethod\">\n"
+ "<arg name=\"testEnumExtended2Value\" type=\"i\" direction=\"in\" />\n"
+ "<arg name=\"testMapValue\" type=\"a{ua(sq)}\" direction=\"in\" />\n"
+ "<arg name=\"testEnumExtended2Value\" type=\"i\" direction=\"out\" />\n"
+ "<arg name=\"testMapValue\" type=\"a{ua(sq)}\" direction=\"out\" />\n"
+ "</method>\n"
+ "<method name=\"testDerivedTypeMethod\">\n"
+ "<arg name=\"testEnumExtended2InValue\" type=\"i\" direction=\"in\" />\n"
+ "<arg name=\"testMapInValue\" type=\"a{ua(sq)}\" direction=\"in\" />\n"
+ "<arg name=\"testEnumExtended2InValue\" type=\"i\" direction=\"out\" />\n"
+ "<arg name=\"testMapInValue\" type=\"a{ua(sq)}\" direction=\"out\" />\n"
+ "</method>\n"
+ ;
+}
+
+
+static CommonAPI::DBus::DBusGetAttributeStubDispatcher<
+ TestInterfaceStub,
+ uint32_t
+ > getTestPredefinedTypeAttributeAttributeStubDispatcher(&TestInterfaceStub::getTestPredefinedTypeAttributeAttribute, "u");
+static CommonAPI::DBus::DBusSetObservableAttributeStubDispatcher<
+ TestInterfaceStub,
+ uint32_t
+ > setTestPredefinedTypeAttributeAttributeStubDispatcher(
+ &TestInterfaceStub::getTestPredefinedTypeAttributeAttribute,
+ &TestInterfaceStubRemoteEvent::onRemoteSetTestPredefinedTypeAttributeAttribute,
+ &TestInterfaceStubRemoteEvent::onRemoteTestPredefinedTypeAttributeAttributeChanged,
+ &TestInterfaceStubAdapter::fireTestPredefinedTypeAttributeAttributeChanged,
+ "u");
+
+static CommonAPI::DBus::DBusGetAttributeStubDispatcher<
+ TestInterfaceStub,
+ DerivedTypeCollection::TestStructExtended
+ > getTestDerivedStructAttributeAttributeStubDispatcher(&TestInterfaceStub::getTestDerivedStructAttributeAttribute, "(sqi)");
+static CommonAPI::DBus::DBusSetObservableAttributeStubDispatcher<
+ TestInterfaceStub,
+ DerivedTypeCollection::TestStructExtended
+ > setTestDerivedStructAttributeAttributeStubDispatcher(
+ &TestInterfaceStub::getTestDerivedStructAttributeAttribute,
+ &TestInterfaceStubRemoteEvent::onRemoteSetTestDerivedStructAttributeAttribute,
+ &TestInterfaceStubRemoteEvent::onRemoteTestDerivedStructAttributeAttributeChanged,
+ &TestInterfaceStubAdapter::fireTestDerivedStructAttributeAttributeChanged,
+ "(sqi)");
+
+static CommonAPI::DBus::DBusGetAttributeStubDispatcher<
+ TestInterfaceStub,
+ DerivedTypeCollection::TestArrayUInt64
+ > getTestDerivedArrayAttributeAttributeStubDispatcher(&TestInterfaceStub::getTestDerivedArrayAttributeAttribute, "at");
+static CommonAPI::DBus::DBusSetObservableAttributeStubDispatcher<
+ TestInterfaceStub,
+ DerivedTypeCollection::TestArrayUInt64
+ > setTestDerivedArrayAttributeAttributeStubDispatcher(
+ &TestInterfaceStub::getTestDerivedArrayAttributeAttribute,
+ &TestInterfaceStubRemoteEvent::onRemoteSetTestDerivedArrayAttributeAttribute,
+ &TestInterfaceStubRemoteEvent::onRemoteTestDerivedArrayAttributeAttributeChanged,
+ &TestInterfaceStubAdapter::fireTestDerivedArrayAttributeAttributeChanged,
+ "at");
+
+
+static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher<
+ TestInterfaceStub,
+ std::tuple<uint32_t, std::string>,
+ std::tuple<>
+ > testVoidPredefinedTypeMethodStubDispatcher(&TestInterfaceStub::testVoidPredefinedTypeMethod, "");
+
+static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher<
+ TestInterfaceStub,
+ std::tuple<uint32_t, std::string>,
+ std::tuple<uint32_t, std::string>
+ > testPredefinedTypeMethodStubDispatcher(&TestInterfaceStub::testPredefinedTypeMethod, "us");
+
+static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher<
+ TestInterfaceStub,
+ std::tuple<DerivedTypeCollection::TestEnumExtended2, DerivedTypeCollection::TestMap>,
+ std::tuple<>
+ > testVoidDerivedTypeMethodStubDispatcher(&TestInterfaceStub::testVoidDerivedTypeMethod, "");
+
+static CommonAPI::DBus::DBusMethodWithReplyStubDispatcher<
+ TestInterfaceStub,
+ std::tuple<DerivedTypeCollection::TestEnumExtended2, DerivedTypeCollection::TestMap>,
+ std::tuple<DerivedTypeCollection::TestEnumExtended2, DerivedTypeCollection::TestMap>
+ > testDerivedTypeMethodStubDispatcher(&TestInterfaceStub::testDerivedTypeMethod, "ia{ua(sq)}");
+
+
+template<>
+const TestInterfaceDBusStubAdapterHelper::StubDispatcherTable TestInterfaceDBusStubAdapterHelper::stubDispatcherTable_ = {
+ { { "getTestPredefinedTypeAttributeAttribute", "" }, &commonapi::tests::getTestPredefinedTypeAttributeAttributeStubDispatcher }
+ , { { "setTestPredefinedTypeAttributeAttribute", "u" }, &commonapi::tests::setTestPredefinedTypeAttributeAttributeStubDispatcher },
+ { { "getTestDerivedStructAttributeAttribute", "" }, &commonapi::tests::getTestDerivedStructAttributeAttributeStubDispatcher }
+ , { { "setTestDerivedStructAttributeAttribute", "(sqi)" }, &commonapi::tests::setTestDerivedStructAttributeAttributeStubDispatcher },
+ { { "getTestDerivedArrayAttributeAttribute", "" }, &commonapi::tests::getTestDerivedArrayAttributeAttributeStubDispatcher }
+ , { { "setTestDerivedArrayAttributeAttribute", "at" }, &commonapi::tests::setTestDerivedArrayAttributeAttributeStubDispatcher }
+ ,
+ { { "testVoidPredefinedTypeMethod", "us" }, &commonapi::tests::testVoidPredefinedTypeMethodStubDispatcher },
+ { { "testPredefinedTypeMethod", "us" }, &commonapi::tests::testPredefinedTypeMethodStubDispatcher },
+ { { "testVoidDerivedTypeMethod", "ia{ua(sq)}" }, &commonapi::tests::testVoidDerivedTypeMethodStubDispatcher },
+ { { "testDerivedTypeMethod", "ia{ua(sq)}" }, &commonapi::tests::testDerivedTypeMethodStubDispatcher }
+};
+
+void TestInterfaceDBusStubAdapter::fireTestPredefinedTypeAttributeAttributeChanged(const uint32_t& value) {
+ CommonAPI::DBus::DBusStubSignalHelper<CommonAPI::DBus::DBusSerializableArguments<uint32_t>>
+ ::sendSignal(
+ *this,
+ "onTestPredefinedTypeAttributeAttributeChanged",
+ "u",
+ value
+ );
+}
+void TestInterfaceDBusStubAdapter::fireTestDerivedStructAttributeAttributeChanged(const DerivedTypeCollection::TestStructExtended& value) {
+ CommonAPI::DBus::DBusStubSignalHelper<CommonAPI::DBus::DBusSerializableArguments<DerivedTypeCollection::TestStructExtended>>
+ ::sendSignal(
+ *this,
+ "onTestDerivedStructAttributeAttributeChanged",
+ "(sqi)",
+ value
+ );
+}
+void TestInterfaceDBusStubAdapter::fireTestDerivedArrayAttributeAttributeChanged(const DerivedTypeCollection::TestArrayUInt64& value) {
+ CommonAPI::DBus::DBusStubSignalHelper<CommonAPI::DBus::DBusSerializableArguments<DerivedTypeCollection::TestArrayUInt64>>
+ ::sendSignal(
+ *this,
+ "onTestDerivedArrayAttributeAttributeChanged",
+ "at",
+ value
+ );
+}
+
+void TestInterfaceDBusStubAdapter::fireTestPredefinedTypeBroadcastEvent(const uint32_t& uint32Value, const std::string& stringValue) {
+ CommonAPI::DBus::DBusStubSignalHelper<CommonAPI::DBus::DBusSerializableArguments<uint32_t, std::string>>
+ ::sendSignal(
+ *this,
+ "TestPredefinedTypeBroadcast",
+ "us",
+ uint32Value, stringValue
+ );
+}
+
+} // namespace tests
+} // namespace commonapi
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_TESTS_TEST_INTERFACE_DBUS_STUB_ADAPTER_H_
+#define COMMONAPI_TESTS_TEST_INTERFACE_DBUS_STUB_ADAPTER_H_
+
+#include "TestInterfaceStub.h"
+
+#include <CommonAPI/DBus/DBusStubAdapterHelper.h>
+#include <CommonAPI/DBus/DBusFactory.h>
+
+namespace commonapi {
+namespace tests {
+
+typedef CommonAPI::DBus::DBusStubAdapterHelper<TestInterfaceStub> TestInterfaceDBusStubAdapterHelper;
+
+class TestInterfaceDBusStubAdapter: public TestInterfaceStubAdapter, public TestInterfaceDBusStubAdapterHelper {
+ public:
+ TestInterfaceDBusStubAdapter(
+ const std::string& dbusBusName,
+ const std::string& dbusObjectPath,
+ const std::shared_ptr<CommonAPI::DBus::DBusProxyConnection>& dbusConnection,
+ const std::shared_ptr<CommonAPI::StubBase>& stub);
+
+ void fireTestPredefinedTypeAttributeAttributeChanged(const uint32_t& value);
+ void fireTestDerivedStructAttributeAttributeChanged(const DerivedTypeCollection::TestStructExtended& value);
+ void fireTestDerivedArrayAttributeAttributeChanged(const DerivedTypeCollection::TestArrayUInt64& value);
+
+ void fireTestPredefinedTypeBroadcastEvent(const uint32_t& uint32Value, const std::string& stringValue);
+
+ protected:
+ virtual const char* getMethodsDBusIntrospectionXmlData() const;
+};
+
+} // namespace tests
+} // namespace commonapi
+
+#endif // COMMONAPI_TESTS_TEST_INTERFACE_DBUS_STUB_ADAPTER_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_TESTS_TEST_INTERFACE_PROXY_H_
+#define COMMONAPI_TESTS_TEST_INTERFACE_PROXY_H_
+
+#include "TestInterfaceProxyBase.h"
+#include <CommonAPI/AttributeExtension.h>
+
+namespace commonapi {
+namespace tests {
+
+template <typename ... _AttributeExtensions>
+class TestInterfaceProxy: virtual public TestInterface, virtual public TestInterfaceProxyBase, public _AttributeExtensions... {
+ public:
+ TestInterfaceProxy(std::shared_ptr<CommonAPI::Proxy> delegate);
+ ~TestInterfaceProxy();
+
+ virtual TestPredefinedTypeAttributeAttribute& getTestPredefinedTypeAttributeAttribute();
+ virtual TestDerivedStructAttributeAttribute& getTestDerivedStructAttributeAttribute();
+ virtual TestDerivedArrayAttributeAttribute& getTestDerivedArrayAttributeAttribute();
+
+ virtual TestPredefinedTypeBroadcastEvent& getTestPredefinedTypeBroadcastEvent();
+
+
+ virtual void testVoidPredefinedTypeMethod(const uint32_t& uint32Value, const std::string& stringValue, CommonAPI::CallStatus& callStatus);
+ virtual std::future<CommonAPI::CallStatus> testVoidPredefinedTypeMethodAsync(const uint32_t& uint32Value, const std::string& stringValue, TestVoidPredefinedTypeMethodAsyncCallback callback);
+
+ virtual void testPredefinedTypeMethod(const uint32_t& uint32InValue, const std::string& stringInValue, CommonAPI::CallStatus& callStatus, uint32_t& uint32OutValue, std::string& stringOutValue);
+ virtual std::future<CommonAPI::CallStatus> testPredefinedTypeMethodAsync(const uint32_t& uint32InValue, const std::string& stringInValue, TestPredefinedTypeMethodAsyncCallback callback);
+
+ virtual void testVoidDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, CommonAPI::CallStatus& callStatus);
+ virtual std::future<CommonAPI::CallStatus> testVoidDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, TestVoidDerivedTypeMethodAsyncCallback callback);
+
+ virtual void testDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, CommonAPI::CallStatus& callStatus, DerivedTypeCollection::TestEnumExtended2& testEnumExtended2OutValue, DerivedTypeCollection::TestMap& testMapOutValue);
+ virtual std::future<CommonAPI::CallStatus> testDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, TestDerivedTypeMethodAsyncCallback callback);
+
+ virtual std::string getAddress() const;
+ virtual const std::string& getDomain() const;
+ virtual const std::string& getServiceId() const;
+ virtual const std::string& getInstanceId() const;
+ virtual bool isAvailable() const;
+ virtual CommonAPI::ProxyStatusEvent& getProxyStatusEvent();
+ virtual CommonAPI::InterfaceVersionAttribute& getInterfaceVersionAttribute();
+
+ private:
+ std::shared_ptr<TestInterfaceProxyBase> delegate_;
+};
+
+namespace TestInterfaceExtensions {
+ template <template <typename > class _ExtensionType>
+ class TestPredefinedTypeAttributeAttributeExtension {
+ public:
+ typedef _ExtensionType<TestInterfaceProxyBase::TestPredefinedTypeAttributeAttribute> extension_type;
+
+ static_assert(std::is_base_of<typename CommonAPI::AttributeExtension<TestInterfaceProxyBase::TestPredefinedTypeAttributeAttribute>, extension_type>::value,
+ "Not CommonAPI Attribute Extension!");
+
+ TestPredefinedTypeAttributeAttributeExtension(TestInterfaceProxyBase& proxy): attributeExtension_(proxy.getTestPredefinedTypeAttributeAttribute()) {
+ }
+
+ inline extension_type& getTestPredefinedTypeAttributeAttributeExtension() {
+ return attributeExtension_;
+ }
+
+ private:
+ extension_type attributeExtension_;
+ };
+
+ template <template <typename > class _ExtensionType>
+ class TestDerivedStructAttributeAttributeExtension {
+ public:
+ typedef _ExtensionType<TestInterfaceProxyBase::TestDerivedStructAttributeAttribute> extension_type;
+
+ static_assert(std::is_base_of<typename CommonAPI::AttributeExtension<TestInterfaceProxyBase::TestDerivedStructAttributeAttribute>, extension_type>::value,
+ "Not CommonAPI Attribute Extension!");
+
+ TestDerivedStructAttributeAttributeExtension(TestInterfaceProxyBase& proxy): attributeExtension_(proxy.getTestDerivedStructAttributeAttribute()) {
+ }
+
+ inline extension_type& getTestDerivedStructAttributeAttributeExtension() {
+ return attributeExtension_;
+ }
+
+ private:
+ extension_type attributeExtension_;
+ };
+
+ template <template <typename > class _ExtensionType>
+ class TestDerivedArrayAttributeAttributeExtension {
+ public:
+ typedef _ExtensionType<TestInterfaceProxyBase::TestDerivedArrayAttributeAttribute> extension_type;
+
+ static_assert(std::is_base_of<typename CommonAPI::AttributeExtension<TestInterfaceProxyBase::TestDerivedArrayAttributeAttribute>, extension_type>::value,
+ "Not CommonAPI Attribute Extension!");
+
+ TestDerivedArrayAttributeAttributeExtension(TestInterfaceProxyBase& proxy): attributeExtension_(proxy.getTestDerivedArrayAttributeAttribute()) {
+ }
+
+ inline extension_type& getTestDerivedArrayAttributeAttributeExtension() {
+ return attributeExtension_;
+ }
+
+ private:
+ extension_type attributeExtension_;
+ };
+
+} // namespace TestInterfaceExtensions
+
+//
+// TestInterfaceProxy Implementation
+//
+template <typename ... _AttributeExtensions>
+TestInterfaceProxy<_AttributeExtensions...>::TestInterfaceProxy(std::shared_ptr<CommonAPI::Proxy> delegate):
+ delegate_(std::dynamic_pointer_cast<TestInterfaceProxyBase>(delegate)),
+ _AttributeExtensions(*(std::dynamic_pointer_cast<TestInterfaceProxyBase>(delegate)))... {
+}
+
+template <typename ... _AttributeExtensions>
+TestInterfaceProxy<_AttributeExtensions...>::~TestInterfaceProxy() {
+}
+
+template <typename ... _AttributeExtensions>
+typename TestInterfaceProxy<_AttributeExtensions...>::TestPredefinedTypeAttributeAttribute& TestInterfaceProxy<_AttributeExtensions...>::getTestPredefinedTypeAttributeAttribute() {
+ return delegate_->getTestPredefinedTypeAttributeAttribute();
+}
+
+template <typename ... _AttributeExtensions>
+typename TestInterfaceProxy<_AttributeExtensions...>::TestDerivedStructAttributeAttribute& TestInterfaceProxy<_AttributeExtensions...>::getTestDerivedStructAttributeAttribute() {
+ return delegate_->getTestDerivedStructAttributeAttribute();
+}
+
+template <typename ... _AttributeExtensions>
+typename TestInterfaceProxy<_AttributeExtensions...>::TestDerivedArrayAttributeAttribute& TestInterfaceProxy<_AttributeExtensions...>::getTestDerivedArrayAttributeAttribute() {
+ return delegate_->getTestDerivedArrayAttributeAttribute();
+}
+
+
+template <typename ... _AttributeExtensions>
+typename TestInterfaceProxy<_AttributeExtensions...>::TestPredefinedTypeBroadcastEvent& TestInterfaceProxy<_AttributeExtensions...>::getTestPredefinedTypeBroadcastEvent() {
+ return delegate_->getTestPredefinedTypeBroadcastEvent();
+}
+
+
+template <typename ... _AttributeExtensions>
+void TestInterfaceProxy<_AttributeExtensions...>::testVoidPredefinedTypeMethod(const uint32_t& uint32Value, const std::string& stringValue, CommonAPI::CallStatus& callStatus) {
+ delegate_->testVoidPredefinedTypeMethod(uint32Value, stringValue, callStatus);
+}
+
+template <typename ... _AttributeExtensions>
+std::future<CommonAPI::CallStatus> TestInterfaceProxy<_AttributeExtensions...>::testVoidPredefinedTypeMethodAsync(const uint32_t& uint32Value, const std::string& stringValue, TestVoidPredefinedTypeMethodAsyncCallback callback) {
+ return delegate_->testVoidPredefinedTypeMethodAsync(uint32Value, stringValue, callback);
+}
+
+template <typename ... _AttributeExtensions>
+void TestInterfaceProxy<_AttributeExtensions...>::testPredefinedTypeMethod(const uint32_t& uint32InValue, const std::string& stringInValue, CommonAPI::CallStatus& callStatus, uint32_t& uint32OutValue, std::string& stringOutValue) {
+ delegate_->testPredefinedTypeMethod(uint32InValue, stringInValue, callStatus, uint32OutValue, stringOutValue);
+}
+
+template <typename ... _AttributeExtensions>
+std::future<CommonAPI::CallStatus> TestInterfaceProxy<_AttributeExtensions...>::testPredefinedTypeMethodAsync(const uint32_t& uint32InValue, const std::string& stringInValue, TestPredefinedTypeMethodAsyncCallback callback) {
+ return delegate_->testPredefinedTypeMethodAsync(uint32InValue, stringInValue, callback);
+}
+
+template <typename ... _AttributeExtensions>
+void TestInterfaceProxy<_AttributeExtensions...>::testVoidDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, CommonAPI::CallStatus& callStatus) {
+ delegate_->testVoidDerivedTypeMethod(testEnumExtended2Value, testMapValue, callStatus);
+}
+
+template <typename ... _AttributeExtensions>
+std::future<CommonAPI::CallStatus> TestInterfaceProxy<_AttributeExtensions...>::testVoidDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, TestVoidDerivedTypeMethodAsyncCallback callback) {
+ return delegate_->testVoidDerivedTypeMethodAsync(testEnumExtended2Value, testMapValue, callback);
+}
+
+template <typename ... _AttributeExtensions>
+void TestInterfaceProxy<_AttributeExtensions...>::testDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, CommonAPI::CallStatus& callStatus, DerivedTypeCollection::TestEnumExtended2& testEnumExtended2OutValue, DerivedTypeCollection::TestMap& testMapOutValue) {
+ delegate_->testDerivedTypeMethod(testEnumExtended2InValue, testMapInValue, callStatus, testEnumExtended2OutValue, testMapOutValue);
+}
+
+template <typename ... _AttributeExtensions>
+std::future<CommonAPI::CallStatus> TestInterfaceProxy<_AttributeExtensions...>::testDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, TestDerivedTypeMethodAsyncCallback callback) {
+ return delegate_->testDerivedTypeMethodAsync(testEnumExtended2InValue, testMapInValue, callback);
+}
+
+
+template <typename ... _AttributeExtensions>
+std::string TestInterfaceProxy<_AttributeExtensions...>::getAddress() const {
+ return delegate_->getAddress();
+}
+
+template <typename ... _AttributeExtensions>
+const std::string& TestInterfaceProxy<_AttributeExtensions...>::getDomain() const {
+ return delegate_->getDomain();
+}
+
+template <typename ... _AttributeExtensions>
+const std::string& TestInterfaceProxy<_AttributeExtensions...>::getServiceId() const {
+ return delegate_->getServiceId();
+}
+
+template <typename ... _AttributeExtensions>
+const std::string& TestInterfaceProxy<_AttributeExtensions...>::getInstanceId() const {
+ return delegate_->getInstanceId();
+}
+
+template <typename ... _AttributeExtensions>
+bool TestInterfaceProxy<_AttributeExtensions...>::isAvailable() const {
+ return delegate_->isAvailable();
+}
+
+template <typename ... _AttributeExtensions>
+CommonAPI::ProxyStatusEvent& TestInterfaceProxy<_AttributeExtensions...>::getProxyStatusEvent() {
+ return delegate_->getProxyStatusEvent();
+}
+
+template <typename ... _AttributeExtensions>
+CommonAPI::InterfaceVersionAttribute& TestInterfaceProxy<_AttributeExtensions...>::getInterfaceVersionAttribute() {
+ return delegate_->getInterfaceVersionAttribute();
+}
+
+} // namespace tests
+} // namespace commonapi
+
+namespace CommonAPI {
+template<template<typename > class _AttributeExtension>
+struct DefaultAttributeProxyFactoryHelper<commonapi::tests::TestInterfaceProxy,
+ _AttributeExtension> {
+ typedef typename commonapi::tests::TestInterfaceProxy<
+ commonapi::tests::TestInterfaceExtensions::TestPredefinedTypeAttributeAttributeExtension<_AttributeExtension>,
+ commonapi::tests::TestInterfaceExtensions::TestDerivedStructAttributeAttributeExtension<_AttributeExtension>,
+ commonapi::tests::TestInterfaceExtensions::TestDerivedArrayAttributeAttributeExtension<_AttributeExtension>
+ > class_t;
+};
+}
+
+
+#endif // COMMONAPI_TESTS_TEST_INTERFACE_PROXY_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_TESTS_TEST_INTERFACE_PROXY_BASE_H_
+#define COMMONAPI_TESTS_TEST_INTERFACE_PROXY_BASE_H_
+
+#include "TestInterface.h"
+#include <unordered_map>
+#include <cstdint>
+#include "DerivedTypeCollection.h"
+#include <CommonAPI/InputStream.h>
+#include <vector>
+#include <CommonAPI/OutputStream.h>
+#include <CommonAPI/Attribute.h>
+#include <CommonAPI/Event.h>
+#include <CommonAPI/Proxy.h>
+#include <functional>
+#include <future>
+
+namespace commonapi {
+namespace tests {
+
+class TestInterfaceProxyBase: virtual public CommonAPI::Proxy {
+ public:
+ typedef CommonAPI::ObservableAttribute<uint32_t> TestPredefinedTypeAttributeAttribute;
+ typedef CommonAPI::ObservableAttribute<DerivedTypeCollection::TestStructExtended> TestDerivedStructAttributeAttribute;
+ typedef CommonAPI::ObservableAttribute<DerivedTypeCollection::TestArrayUInt64> TestDerivedArrayAttributeAttribute;
+ typedef CommonAPI::Event<uint32_t, std::string> TestPredefinedTypeBroadcastEvent;
+ typedef std::function<void(const CommonAPI::CallStatus&)> TestVoidPredefinedTypeMethodAsyncCallback;
+ typedef std::function<void(const CommonAPI::CallStatus&, const uint32_t&, const std::string&)> TestPredefinedTypeMethodAsyncCallback;
+ typedef std::function<void(const CommonAPI::CallStatus&)> TestVoidDerivedTypeMethodAsyncCallback;
+ typedef std::function<void(const CommonAPI::CallStatus&, const DerivedTypeCollection::TestEnumExtended2&, const DerivedTypeCollection::TestMap&)> TestDerivedTypeMethodAsyncCallback;
+
+ virtual TestPredefinedTypeAttributeAttribute& getTestPredefinedTypeAttributeAttribute() = 0;
+ virtual TestDerivedStructAttributeAttribute& getTestDerivedStructAttributeAttribute() = 0;
+ virtual TestDerivedArrayAttributeAttribute& getTestDerivedArrayAttributeAttribute() = 0;
+
+ virtual TestPredefinedTypeBroadcastEvent& getTestPredefinedTypeBroadcastEvent() = 0;
+
+
+ virtual void testVoidPredefinedTypeMethod(const uint32_t& uint32Value, const std::string& stringValue, CommonAPI::CallStatus& callStatus) = 0;
+ virtual std::future<CommonAPI::CallStatus> testVoidPredefinedTypeMethodAsync(const uint32_t& uint32Value, const std::string& stringValue, TestVoidPredefinedTypeMethodAsyncCallback callback) = 0;
+
+ virtual void testPredefinedTypeMethod(const uint32_t& uint32InValue, const std::string& stringInValue, CommonAPI::CallStatus& callStatus, uint32_t& uint32OutValue, std::string& stringOutValue) = 0;
+ virtual std::future<CommonAPI::CallStatus> testPredefinedTypeMethodAsync(const uint32_t& uint32InValue, const std::string& stringInValue, TestPredefinedTypeMethodAsyncCallback callback) = 0;
+
+ virtual void testVoidDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, CommonAPI::CallStatus& callStatus) = 0;
+ virtual std::future<CommonAPI::CallStatus> testVoidDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2Value, const DerivedTypeCollection::TestMap& testMapValue, TestVoidDerivedTypeMethodAsyncCallback callback) = 0;
+
+ virtual void testDerivedTypeMethod(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, CommonAPI::CallStatus& callStatus, DerivedTypeCollection::TestEnumExtended2& testEnumExtended2OutValue, DerivedTypeCollection::TestMap& testMapOutValue) = 0;
+ virtual std::future<CommonAPI::CallStatus> testDerivedTypeMethodAsync(const DerivedTypeCollection::TestEnumExtended2& testEnumExtended2InValue, const DerivedTypeCollection::TestMap& testMapInValue, TestDerivedTypeMethodAsyncCallback callback) = 0;
+};
+
+
+} // namespace tests
+} // namespace commonapi
+
+#endif // COMMONAPI_TESTS_TEST_INTERFACE_PROXY_BASE_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_TESTS_TEST_INTERFACE_STUB_H_
+#define COMMONAPI_TESTS_TEST_INTERFACE_STUB_H_
+
+#include <unordered_map>
+#include <cstdint>
+#include "DerivedTypeCollection.h"
+#include <CommonAPI/InputStream.h>
+#include <vector>
+#include <CommonAPI/OutputStream.h>
+#include "TestInterface.h"
+#include <CommonAPI/Stub.h>
+
+namespace commonapi {
+namespace tests {
+
+class TestInterfaceStubAdapter: virtual public CommonAPI::StubAdapter, public TestInterface {
+ public:
+ virtual void fireTestPredefinedTypeAttributeAttributeChanged(const uint32_t& TestPredefinedTypeAttribute) = 0;
+ virtual void fireTestDerivedStructAttributeAttributeChanged(const DerivedTypeCollection::TestStructExtended& TestDerivedStructAttribute) = 0;
+ virtual void fireTestDerivedArrayAttributeAttributeChanged(const DerivedTypeCollection::TestArrayUInt64& TestDerivedArrayAttribute) = 0;
+
+ virtual void fireTestPredefinedTypeBroadcastEvent(const uint32_t& uint32Value, const std::string& stringValue) = 0;
+};
+
+
+class TestInterfaceStubRemoteEvent {
+ public:
+ virtual ~TestInterfaceStubRemoteEvent() { }
+
+ virtual bool onRemoteSetTestPredefinedTypeAttributeAttribute(uint32_t TestPredefinedTypeAttribute) = 0;
+ virtual void onRemoteTestPredefinedTypeAttributeAttributeChanged() = 0;
+
+ virtual bool onRemoteSetTestDerivedStructAttributeAttribute(DerivedTypeCollection::TestStructExtended TestDerivedStructAttribute) = 0;
+ virtual void onRemoteTestDerivedStructAttributeAttributeChanged() = 0;
+
+ virtual bool onRemoteSetTestDerivedArrayAttributeAttribute(DerivedTypeCollection::TestArrayUInt64 TestDerivedArrayAttribute) = 0;
+ virtual void onRemoteTestDerivedArrayAttributeAttributeChanged() = 0;
+
+};
+
+
+class TestInterfaceStub : public CommonAPI::Stub<TestInterfaceStubAdapter , TestInterfaceStubRemoteEvent> {
+ public:
+ virtual const uint32_t& getTestPredefinedTypeAttributeAttribute() = 0;
+ virtual const DerivedTypeCollection::TestStructExtended& getTestDerivedStructAttributeAttribute() = 0;
+ virtual const DerivedTypeCollection::TestArrayUInt64& getTestDerivedArrayAttributeAttribute() = 0;
+
+ virtual void testVoidPredefinedTypeMethod(uint32_t uint32Value, std::string stringValue) = 0;
+
+ virtual void testPredefinedTypeMethod(uint32_t uint32InValue, std::string stringInValue, uint32_t& uint32OutValue, std::string& stringOutValue) = 0;
+
+ virtual void testVoidDerivedTypeMethod(DerivedTypeCollection::TestEnumExtended2 testEnumExtended2Value, DerivedTypeCollection::TestMap testMapValue) = 0;
+
+ virtual void testDerivedTypeMethod(DerivedTypeCollection::TestEnumExtended2 testEnumExtended2InValue, DerivedTypeCollection::TestMap testMapInValue, DerivedTypeCollection::TestEnumExtended2& testEnumExtended2OutValue, DerivedTypeCollection::TestMap& testMapOutValue) = 0;
+
+};
+
+} // namespace tests
+} // namespace commonapi
+
+#endif // COMMONAPI_TESTS_TEST_INTERFACE_STUB_H_
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "TestInterfaceStubDefault.h"
+
+namespace commonapi {
+namespace tests {
+
+TestInterfaceStubDefault::TestInterfaceStubDefault():
+ remoteEventHandler_(this) {
+}
+
+TestInterfaceStubRemoteEvent* TestInterfaceStubDefault::initStubAdapter(const std::shared_ptr<TestInterfaceStubAdapter>& stubAdapter) {
+ stubAdapter_ = stubAdapter;
+ return &remoteEventHandler_;
+}
+
+const uint32_t& TestInterfaceStubDefault::getTestPredefinedTypeAttributeAttribute() {
+ return testPredefinedTypeAttributeAttributeValue_;
+}
+
+void TestInterfaceStubDefault::setTestPredefinedTypeAttributeAttribute(uint32_t value) {
+ const bool valueChanged = trySetTestPredefinedTypeAttributeAttribute(std::move(value));
+ if (valueChanged)
+ stubAdapter_->fireTestPredefinedTypeAttributeAttributeChanged(testPredefinedTypeAttributeAttributeValue_);
+}
+
+void TestInterfaceStubDefault::onRemoteTestPredefinedTypeAttributeAttributeChanged() {
+ // No operation in default
+}
+
+bool TestInterfaceStubDefault::trySetTestPredefinedTypeAttributeAttribute(uint32_t value) {
+ if (!validateTestPredefinedTypeAttributeAttributeRequestedValue(value))
+ return false;
+
+ const bool valueChanged = (testPredefinedTypeAttributeAttributeValue_ != value);
+ testPredefinedTypeAttributeAttributeValue_ = std::move(value);
+ return valueChanged;
+}
+
+bool TestInterfaceStubDefault::validateTestPredefinedTypeAttributeAttributeRequestedValue(const uint32_t& value) {
+ return true;
+}
+
+const DerivedTypeCollection::TestStructExtended& TestInterfaceStubDefault::getTestDerivedStructAttributeAttribute() {
+ return testDerivedStructAttributeAttributeValue_;
+}
+
+void TestInterfaceStubDefault::setTestDerivedStructAttributeAttribute(DerivedTypeCollection::TestStructExtended value) {
+ const bool valueChanged = trySetTestDerivedStructAttributeAttribute(std::move(value));
+ if (valueChanged)
+ stubAdapter_->fireTestDerivedStructAttributeAttributeChanged(testDerivedStructAttributeAttributeValue_);
+}
+
+void TestInterfaceStubDefault::onRemoteTestDerivedStructAttributeAttributeChanged() {
+ // No operation in default
+}
+
+bool TestInterfaceStubDefault::trySetTestDerivedStructAttributeAttribute(DerivedTypeCollection::TestStructExtended value) {
+ if (!validateTestDerivedStructAttributeAttributeRequestedValue(value))
+ return false;
+
+ const bool valueChanged = (testDerivedStructAttributeAttributeValue_ != value);
+ testDerivedStructAttributeAttributeValue_ = std::move(value);
+ return valueChanged;
+}
+
+bool TestInterfaceStubDefault::validateTestDerivedStructAttributeAttributeRequestedValue(const DerivedTypeCollection::TestStructExtended& value) {
+ return true;
+}
+
+const DerivedTypeCollection::TestArrayUInt64& TestInterfaceStubDefault::getTestDerivedArrayAttributeAttribute() {
+ return testDerivedArrayAttributeAttributeValue_;
+}
+
+void TestInterfaceStubDefault::setTestDerivedArrayAttributeAttribute(DerivedTypeCollection::TestArrayUInt64 value) {
+ const bool valueChanged = trySetTestDerivedArrayAttributeAttribute(std::move(value));
+ if (valueChanged)
+ stubAdapter_->fireTestDerivedArrayAttributeAttributeChanged(testDerivedArrayAttributeAttributeValue_);
+}
+
+void TestInterfaceStubDefault::onRemoteTestDerivedArrayAttributeAttributeChanged() {
+ // No operation in default
+}
+
+bool TestInterfaceStubDefault::trySetTestDerivedArrayAttributeAttribute(DerivedTypeCollection::TestArrayUInt64 value) {
+ if (!validateTestDerivedArrayAttributeAttributeRequestedValue(value))
+ return false;
+
+ const bool valueChanged = (testDerivedArrayAttributeAttributeValue_ != value);
+ testDerivedArrayAttributeAttributeValue_ = std::move(value);
+ return valueChanged;
+}
+
+bool TestInterfaceStubDefault::validateTestDerivedArrayAttributeAttributeRequestedValue(const DerivedTypeCollection::TestArrayUInt64& value) {
+ return true;
+}
+
+
+void TestInterfaceStubDefault::testVoidPredefinedTypeMethod(uint32_t uint32Value, std::string stringValue) {
+ // No operation in default
+}
+
+void TestInterfaceStubDefault::testPredefinedTypeMethod(uint32_t uint32InValue, std::string stringInValue, uint32_t& uint32OutValue, std::string& stringOutValue) {
+ // No operation in default
+}
+
+void TestInterfaceStubDefault::testVoidDerivedTypeMethod(DerivedTypeCollection::TestEnumExtended2 testEnumExtended2Value, DerivedTypeCollection::TestMap testMapValue) {
+ // No operation in default
+}
+
+void TestInterfaceStubDefault::testDerivedTypeMethod(DerivedTypeCollection::TestEnumExtended2 testEnumExtended2InValue, DerivedTypeCollection::TestMap testMapInValue, DerivedTypeCollection::TestEnumExtended2& testEnumExtended2OutValue, DerivedTypeCollection::TestMap& testMapOutValue) {
+ // No operation in default
+}
+
+void TestInterfaceStubDefault::firePredefinedBroadcast(uint32_t value, std::string& sValue) {
+ stubAdapter_->fireTestPredefinedTypeBroadcastEvent(value, sValue);
+}
+
+
+TestInterfaceStubDefault::RemoteEventHandler::RemoteEventHandler(TestInterfaceStubDefault* defaultStub):
+ defaultStub_(defaultStub) {
+}
+
+bool TestInterfaceStubDefault::RemoteEventHandler::onRemoteSetTestPredefinedTypeAttributeAttribute(uint32_t value) {
+ return defaultStub_->trySetTestPredefinedTypeAttributeAttribute(std::move(value));
+}
+
+void TestInterfaceStubDefault::RemoteEventHandler::onRemoteTestPredefinedTypeAttributeAttributeChanged() {
+ defaultStub_->onRemoteTestPredefinedTypeAttributeAttributeChanged();
+}
+
+bool TestInterfaceStubDefault::RemoteEventHandler::onRemoteSetTestDerivedStructAttributeAttribute(DerivedTypeCollection::TestStructExtended value) {
+ return defaultStub_->trySetTestDerivedStructAttributeAttribute(std::move(value));
+}
+
+void TestInterfaceStubDefault::RemoteEventHandler::onRemoteTestDerivedStructAttributeAttributeChanged() {
+ defaultStub_->onRemoteTestDerivedStructAttributeAttributeChanged();
+}
+
+bool TestInterfaceStubDefault::RemoteEventHandler::onRemoteSetTestDerivedArrayAttributeAttribute(DerivedTypeCollection::TestArrayUInt64 value) {
+ return defaultStub_->trySetTestDerivedArrayAttributeAttribute(std::move(value));
+}
+
+void TestInterfaceStubDefault::RemoteEventHandler::onRemoteTestDerivedArrayAttributeAttributeChanged() {
+ defaultStub_->onRemoteTestDerivedArrayAttributeAttributeChanged();
+}
+
+
+} // namespace tests
+} // namespace commonapi
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef COMMONAPI_TESTS_TEST_INTERFACE_STUB_DEFAULT_H_
+#define COMMONAPI_TESTS_TEST_INTERFACE_STUB_DEFAULT_H_
+
+#include "TestInterfaceStub.h"
+
+namespace commonapi {
+namespace tests {
+
+class TestInterfaceStubDefault : public TestInterfaceStub {
+ public:
+ TestInterfaceStubDefault();
+
+ TestInterfaceStubRemoteEvent* initStubAdapter(const std::shared_ptr<TestInterfaceStubAdapter>& stubAdapter);
+
+ virtual const uint32_t& getTestPredefinedTypeAttributeAttribute();
+ void setTestPredefinedTypeAttributeAttribute(uint32_t value);
+
+ virtual const DerivedTypeCollection::TestStructExtended& getTestDerivedStructAttributeAttribute();
+ void setTestDerivedStructAttributeAttribute(DerivedTypeCollection::TestStructExtended value);
+
+ virtual const DerivedTypeCollection::TestArrayUInt64& getTestDerivedArrayAttributeAttribute();
+ void setTestDerivedArrayAttributeAttribute(DerivedTypeCollection::TestArrayUInt64 value);
+
+
+ virtual void testVoidPredefinedTypeMethod(uint32_t uint32Value, std::string stringValue);
+
+ virtual void testPredefinedTypeMethod(uint32_t uint32InValue, std::string stringInValue, uint32_t& uint32OutValue, std::string& stringOutValue);
+
+ virtual void testVoidDerivedTypeMethod(DerivedTypeCollection::TestEnumExtended2 testEnumExtended2Value, DerivedTypeCollection::TestMap testMapValue);
+
+ virtual void testDerivedTypeMethod(DerivedTypeCollection::TestEnumExtended2 testEnumExtended2InValue, DerivedTypeCollection::TestMap testMapInValue, DerivedTypeCollection::TestEnumExtended2& testEnumExtended2OutValue, DerivedTypeCollection::TestMap& testMapOutValue);
+
+ virtual void firePredefinedBroadcast(uint32_t value, std::string& sValue);
+
+ protected:
+ void onRemoteTestPredefinedTypeAttributeAttributeChanged();
+ bool trySetTestPredefinedTypeAttributeAttribute(uint32_t value);
+ bool validateTestPredefinedTypeAttributeAttributeRequestedValue(const uint32_t& value);
+
+ void onRemoteTestDerivedStructAttributeAttributeChanged();
+ bool trySetTestDerivedStructAttributeAttribute(DerivedTypeCollection::TestStructExtended value);
+ bool validateTestDerivedStructAttributeAttributeRequestedValue(const DerivedTypeCollection::TestStructExtended& value);
+
+ void onRemoteTestDerivedArrayAttributeAttributeChanged();
+ bool trySetTestDerivedArrayAttributeAttribute(DerivedTypeCollection::TestArrayUInt64 value);
+ bool validateTestDerivedArrayAttributeAttributeRequestedValue(const DerivedTypeCollection::TestArrayUInt64& value);
+
+
+ private:
+ class RemoteEventHandler: public TestInterfaceStubRemoteEvent {
+ public:
+ RemoteEventHandler(TestInterfaceStubDefault* defaultStub);
+
+ virtual bool onRemoteSetTestPredefinedTypeAttributeAttribute(uint32_t value);
+ virtual void onRemoteTestPredefinedTypeAttributeAttributeChanged();
+
+ virtual bool onRemoteSetTestDerivedStructAttributeAttribute(DerivedTypeCollection::TestStructExtended value);
+ virtual void onRemoteTestDerivedStructAttributeAttributeChanged();
+
+ virtual bool onRemoteSetTestDerivedArrayAttributeAttribute(DerivedTypeCollection::TestArrayUInt64 value);
+ virtual void onRemoteTestDerivedArrayAttributeAttributeChanged();
+
+
+ private:
+ TestInterfaceStubDefault* defaultStub_;
+ };
+
+ RemoteEventHandler remoteEventHandler_;
+ std::shared_ptr<TestInterfaceStubAdapter> stubAdapter_;
+
+ uint32_t testPredefinedTypeAttributeAttributeValue_;
+ DerivedTypeCollection::TestStructExtended testDerivedStructAttributeAttributeValue_;
+ DerivedTypeCollection::TestArrayUInt64 testDerivedArrayAttributeAttributeValue_;
+};
+
+} // namespace tests
+} // namespace commonapi
+
+#endif // COMMONAPI_TESTS_TEST_INTERFACE_STUB_DEFAULT_H_