1/*
2 * Copyright (c) 2015, Intel Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software without
17 * specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30#pragma once
31
32#include <utility>
33#include "Exception.hpp"
34
35namespace parameterFramework
36{
37
38namespace details
39{
40
41static inline bool successTest(bool res)
42{
43    return res;
44}
45
46template <class T>
47static inline bool successTest(T *res)
48{
49    return res != nullptr;
50}
51
52} // namespace details
53
54template <class Base>
55class FailureWrapper : protected Base
56{
57public:
58    /** Forward construction to base. */
59    template <class... Args>
60    FailureWrapper(Args &&... args) : Base(std::forward<Args>(args)...)
61    {
62    }
63
64    /** Wrap a const method that may fail to throw an Exception instead of
65     * retuning a boolean.
66     *
67     * @param[in] method (const) that return a boolean to indicate failure.
68     * @param[in] args parameters to call method call with. */
69    template <class K, class... MArgs, class... Args>
70    void mayFailCall(bool (K::*method)(MArgs...) const, Args &&... args) const
71    {
72        wrapCall<bool>(*this, method, std::forward<Args>(args)...);
73    }
74
75    /** Wrap a method that may fail to throw an Exception instead of retuning a
76     * boolean.
77     *
78     * @param[in] method that return a boolean to indicate failure.
79     * @param[in] args parameters to call method call with. */
80    template <class K, class... MArgs, class... Args>
81    void mayFailCall(bool (K::*method)(MArgs...), Args &&... args)
82    {
83        wrapCall<bool>(*this, method, std::forward<Args>(args)...);
84    }
85
86    /** Wrap a method that may indicate failure by returning a null pointer to
87     * throw an Exception instead of retuning a null pointer.
88     *
89     * @param[in] method that return a nullprt to indicate failure.
90     * @param[in] args parameters to call method call with. */
91    template <class K, class ReturnType, class... MArgs, class... Args>
92    ReturnType *mayFailCall(ReturnType *(K::*method)(MArgs...), Args &&... args)
93    {
94        return wrapCall<ReturnType *>(*this, method, std::forward<Args>(args)...);
95    }
96
97    /** Wrap a const method that may indicate failure by returning a null pointer to
98     * throw an Exception instead of retuning a null pointer.
99     *
100     * @param[in] method that return a nullprt to indicate failure.
101     * @param[in] args parameters to call method call with. */
102    template <class K, class ReturnType, class... MArgs, class... Args>
103    ReturnType *mayFailCall(ReturnType *(K::*method)(MArgs...) const, Args &&... args) const
104    {
105        return wrapCall<ReturnType *>(*this, method, std::forward<Args>(args)...);
106    }
107
108    /** Wrap a getter to return by value and throw an exception on failure. */
109    template <class K, class Value>
110    Value mayFailGet(bool (K::*accessor)(Value &, std::string &) const) const
111    {
112        Value value;
113        wrapCall<bool>(*this, accessor, value);
114        return value;
115    }
116
117    /** Wrap a setter to throw an exception on failure instead of returning a boolean. */
118    template <class K, class Value>
119    void mayFailSet(bool (K::*accessor)(const Value &, std::string &), const Value &value)
120    {
121        wrapCall<bool>(*this, accessor, value);
122    }
123
124private:
125    template <class Ret, class I, class M, class... Args>
126    static Ret wrapCall(I &instance, M method, Args &&... args)
127    {
128        std::string error;
129        auto res = (instance.*method)(std::forward<Args>(args)..., error);
130        if (not details::successTest(res)) {
131            throw Exception(std::move(error));
132        }
133        return res;
134    }
135};
136} // parameterFramework
137