FastArduino v1.10
C++ library to build fast but small Arduino/AVR projects
Loading...
Searching...
No Matches
functors.h
Go to the documentation of this file.
1// Copyright 2016-2023 Jean-Francois Poilpret
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
16
22#ifndef FUNCTORS_HH
23#define FUNCTORS_HH
24
25#include "utilities.h"
26#include "types_traits.h"
27
37namespace functor
38{
39 // Private class to hide internals used for public API implementation (declared friend)
41 class functor_impl
42 {
43 // Change endianness of a single integer (T must be an integral type)
44 template<typename T> class ChangeEndiannessOneImpl
45 {
46 using T_TRAIT = types_traits::Type_trait<T>;
47 static_assert(T_TRAIT::IS_INT, "T must be an integral type");
48 static_assert(T_TRAIT::SIZE > 1, "T must be at least 2 bytes long");
49 public:
50 using ARG_TYPE = T;
51 using RES_TYPE = T;
52 T operator()(const T& value) const
53 {
54 return utils::change_endianness(value);
55 }
56 };
57
58 // Change endianness of a several integers embedded in another type
59 template<typename T, typename TT> class ChangeEndiannessManyImpl
60 {
61 static_assert(sizeof(T) > sizeof(TT), "T must contain at least 2 TT");
62 using TT_TRAIT = types_traits::Type_trait<TT>;
63 static_assert(TT_TRAIT::IS_INT, "TT must be an integral type");
64 static_assert(TT_TRAIT::SIZE > 1, "TT must be at least 2 bytes long");
65 public:
66 using ARG_TYPE = T;
67 using RES_TYPE = T;
68 T operator()(const T& value) const
69 {
70 constexpr uint8_t COUNT = sizeof(T) / sizeof(TT);
71 T result = value;
72 TT* ptr = reinterpret_cast<TT*>(&result);
73 TT* last = ptr + COUNT;
74 while (ptr < last)
75 utils::swap_bytes(*ptr++);
76 return result;
77 }
78 };
79
80 // Friends
81 template<typename T, typename TT> friend class ChangeEndianness;
82 };
84
90 template<typename T> class Identity
91 {
92 public:
94 using ARG_TYPE = T;
95 using RES_TYPE = T;
96 RES_TYPE operator()(const ARG_TYPE& value) const
97 {
98 return value;
99 }
101 };
102
109 template<typename T, T VAL> class Constant
110 {
111 public:
113 using ARG_TYPE = T;
114 using RES_TYPE = T;
115 RES_TYPE operator()(UNUSED const ARG_TYPE& value) const
116 {
117 return VAL;
118 }
120 };
121
128 template<typename ARG, typename RES> class Cast
129 {
130 public:
132 using ARG_TYPE = ARG;
133 using RES_TYPE = RES;
134 RES_TYPE operator()(const ARG_TYPE& value) const
135 {
136 return (RES_TYPE) value;
137 }
139 };
140
146 template<typename F1, typename F2> class Compose
147 {
148 public:
150 using ARG_TYPE = typename F2::ARG_TYPE;
151 using RES_TYPE = typename F1::RES_TYPE;
152 RES_TYPE operator()(const ARG_TYPE& value) const
153 {
154 F1 f1;
155 F2 f2;
156 return f1(f2(value));
157 }
159 };
160
169 template<typename T, typename TT = T> class ChangeEndianness
170 {
171 public:
173 using ARG_TYPE = T;
174 using RES_TYPE = T;
175 T operator()(const T& value) const
176 {
177 return value;
178 }
180 };
181
183 template<typename T> class ChangeEndianness<T, int16_t> :
184 public functor_impl::ChangeEndiannessManyImpl<T, int16_t>{};
185 template<typename T> class ChangeEndianness<T, uint16_t> :
186 public functor_impl::ChangeEndiannessManyImpl<T, uint16_t>{};
187 template<typename T> class ChangeEndianness<T, int32_t> :
188 public functor_impl::ChangeEndiannessManyImpl<T, int32_t>{};
189 template<typename T> class ChangeEndianness<T, uint32_t> :
190 public functor_impl::ChangeEndiannessManyImpl<T, uint32_t>{};
191 template<typename T> class ChangeEndianness<T, int64_t> :
192 public functor_impl::ChangeEndiannessManyImpl<T, int64_t>{};
193 template<typename T> class ChangeEndianness<T, uint64_t> :
194 public functor_impl::ChangeEndiannessManyImpl<T, uint64_t>{};
195
196 template<> class ChangeEndianness<int16_t, int16_t> :
197 public functor_impl::ChangeEndiannessOneImpl<int16_t>{};
198 template<> class ChangeEndianness<uint16_t, uint16_t> :
199 public functor_impl::ChangeEndiannessOneImpl<uint16_t>{};
200 template<> class ChangeEndianness<int32_t, int32_t> :
201 public functor_impl::ChangeEndiannessOneImpl<int32_t>{};
202 template<> class ChangeEndianness<uint32_t, uint32_t> :
203 public functor_impl::ChangeEndiannessOneImpl<uint32_t>{};
204 template<> class ChangeEndianness<int64_t, int64_t> :
205 public functor_impl::ChangeEndiannessOneImpl<int64_t>{};
206 template<> class ChangeEndianness<uint64_t, uint64_t> :
207 public functor_impl::ChangeEndiannessOneImpl<uint64_t>{};
209
218 template<typename FUNCTOR> struct Functor
219 {
221 using ARG_TYPE = typename FUNCTOR::ARG_TYPE;
222 using RES_TYPE = typename FUNCTOR::RES_TYPE;
223 static RES_TYPE call(const ARG_TYPE& value)
224 {
225 return FUNCTOR{}(value);
226 }
228 };
229}
230
231#endif /* FUNCTORS_HH */
Cast functor: returns its argument of type ARG casted to type RES.
Definition: functors.h:129
Endianness change functor: will change from big to little or little to big endian format on integer t...
Definition: functors.h:170
Composition functor: applies 2 functors one after each other.
Definition: functors.h:147
Constant functor: always returns a constant value.
Definition: functors.h:110
Identity functor: always returns its argument, unchanged.
Definition: functors.h:91
#define UNUSED
Specific GCC attribute to declare an argument or variable unused, so that the compiler does not emit ...
Definition: defines.h:45
This namespace defines a few useful functors.
Definition: functors.h:38
T change_endianness(const T &value)
Change endianness of any integral type (from big to small or small to big).
Definition: utilities.h:560
void swap_bytes(uint16_t &value)
Swap 2 bytes of a 2-bytes integer.
Definition: utilities.h:405
Utility to instantiate and execute a functor from its type.
Definition: functors.h:219
This trait allows static checks (at compile-time) of properties of various types.
Definition: types_traits.h:47
Useful traits for common types.
General utilities API that have broad application in programs.