Use `URI` all caps in documentation
[iotivity.git] / resource / include / OCUtilities.h
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #ifndef OC_UTILITIES_H_
22 #define OC_UTILITIES_H_
23
24 #include <map>
25 #include <vector>
26 #include <memory>
27 #include <utility>
28 #include <exception>
29 #include <functional>
30
31 #include <OCException.h>
32 #include <StringConstants.h>
33
34 namespace OC {
35     namespace Utilities {
36
37         typedef std::map<std::string, std::string> QueryParamsKeyVal;
38
39         /*
40          * @brief helper function that parses the query parameters component
41          * of a URI into a key-value map.  This function expects the URI
42          * parameter to contain the query parameters component of a URI
43          * (everything after the '?', excluding anything anchors).
44          *
45          * Note that output will not perform URL decoding
46          */
47         QueryParamsKeyVal getQueryParams(const std::string& uri);
48     }
49 }
50
51 /* The C++11 standard unfortunately forgot to provide make_unique<>! However, if we're
52 using C++14 or later, we want to take the standard library's implementation: */
53 namespace OC {
54 #if defined(__cplusplus) && __cplusplus < 201300
55
56     template<typename T, typename ...XS>
57     std::unique_ptr<T> make_unique(XS&& ...xs)
58     {
59         return std::unique_ptr<T>(new T(std::forward<XS>(xs)...));
60     }
61
62 #else
63     using std::make_unique;
64 #endif
65 } // namespace OC
66
67 namespace OC {
68
69     /* Examine an OCStackResult, and either forward its value or raise an exception: */
70     OCStackResult result_guard(const OCStackResult r);
71
72     /* Check for a nullptr, and throw an exception if we see one; otherwise, return the
73     result of the function call: */
74     template <typename PtrT, typename FnT, typename ...ParamTs>
75     auto nil_guard(PtrT&& p, FnT&& fn, ParamTs&& ...params) -> OCStackResult
76     {
77         if(nullptr == p)
78         {
79             throw OCException(OC::Exception::NIL_GUARD_NULL, OC_STACK_INVALID_PARAM);
80         }
81
82         // Note that the parameters are being passed by reference to std::bind. This is not an
83         // issue, as it is this function's parameters that are being passed by reference.  So,
84         // unless the parameters are being passed by reference to here (or to checked_guard),
85         // they won't be modified.
86         return std::bind(fn, p, std::ref(params)...)();
87     }
88
89     /* Check for nullptr and forward the result of an OC function call on success; raise
90     an exception on failure or exceptional result: */
91     template <typename PtrT, typename FnT, typename ...ParamTs>
92     auto checked_guard(PtrT&& p, FnT&& fn, ParamTs&& ...params) -> OCStackResult
93     {
94         return result_guard(nil_guard(p, fn, std::forward<ParamTs>(params)...));
95     }
96
97 } // namespace OC
98
99 namespace OC
100 {
101     template<typename T, typename = void>
102     struct is_vector
103     {
104         BOOST_STATIC_CONSTEXPR bool value = false;
105     };
106
107     template<typename T>
108     struct is_vector<T,
109         typename std::enable_if<
110             std::is_same<T, std::vector<typename T::value_type, typename T::allocator_type> >::value
111         >::type
112     >
113     {
114         BOOST_STATIC_CONSTEXPR bool value = true;
115     };
116
117     // type trait to remove the first type from a parameter-packed list
118     template <typename T>
119     struct remove_first;
120
121     // specialization that does all the work
122     template<template <typename...> class Base, typename T, typename ...Rest>
123     struct remove_first< Base<T, Rest...> >
124     {
125         typedef Base<Rest...> type;
126     };
127
128     // type trait that will only pass if ToTest is in the parameter pack of T2
129     template<typename ToTest, typename T2>
130     struct is_component;
131
132     // specialization to handle the single-item case
133     template<typename ToTest, template <typename...> class Base, typename T>
134     struct is_component<ToTest, Base<T> >
135     {
136         BOOST_STATIC_CONSTEXPR bool value = std::is_same<ToTest, T>::value;
137     };
138
139     // Recursive specialization to handle cases with multiple values
140     template<typename ToTest, template <typename...> class Base, typename T, typename ...Rest>
141     struct is_component<ToTest, Base<T, Rest...> >
142     {
143         BOOST_STATIC_CONSTEXPR bool value = std::is_same<ToTest, T>::value
144             || is_component<ToTest, Base<Rest...> >::value;
145     };
146 } // namespace OC
147
148 #endif
149