15 #include <type_traits>
20 #include "comms/details/tag.h"
48 using AccessSelectTypeItself =
typename std::decay<T>::type;
51 using AccessSelectIntType =
53 std::is_signed<T>::value
54 >::template Type<int, unsigned>;
57 using AccessOptimisedValueType =
58 typename comms::util::LazyShallowConditional<
59 sizeof(T) >=
sizeof(
int)
61 AccessSelectTypeItself,
66 template <
typename TUn
signedByteType,
typename T>
67 typename std::decay<T>::type signExtCommon(T value, std::size_t size)
69 using ValueType =
typename std::decay<T>::type;
70 static_assert(std::is_unsigned<ValueType>::value,
"Type T must be unsigned");
71 static_assert(std::is_unsigned<TUnsignedByteType>::value,
72 "Type TUnsignedByteType must be unsigned");
74 static const std::size_t BinDigits =
75 std::numeric_limits<TUnsignedByteType>::digits;
76 static_assert(BinDigits % 8 == 0,
"Byte size assumption is not valid");
79 static_cast<ValueType
>(
static_cast<ValueType
>(1) << ((size * BinDigits) - 1));
81 return static_cast<ValueType
>(value | (~((mask << 1) - 1)));
86 template <
typename...>
89 template <
typename... TParams>
90 using FullSize = comms::details::tag::Tag1<>;
92 template <
typename... TParams>
93 using PartialSize = comms::details::tag::Tag2<>;
96 template <std::
size_t TSize,
typename TByteType,
typename T>
97 static typename std::decay<T>::type value(T val)
99 using ValueType =
typename std::decay<T>::type;
101 typename comms::util::LazyShallowConditional<
102 sizeof(ValueType) == TSize
108 return valueInternal<TSize, TByteType>(val, Tag());
113 template <std::size_t TSize,
typename TByteType,
typename T,
typename... TParams>
114 static typename std::decay<T>::type valueInternal(T val, FullSize<TParams...>)
119 template <std::size_t TSize,
typename TByteType,
typename T,
typename... TParams>
120 static typename std::decay<T>::type valueInternal(T val, PartialSize<TParams...>)
122 using ValueType =
typename std::decay<T>::type;
123 using UnsignedValueType =
typename std::make_unsigned<ValueType>::type;
124 static_assert(std::is_integral<ValueType>::value,
"T must be integer type");
125 using UnsignedByteType =
typename std::make_unsigned<TByteType>::type;
127 auto castedValue =
static_cast<UnsignedValueType
>(val);
128 return static_cast<ValueType
>(
129 signExtCommon<UnsignedByteType>(castedValue, TSize));
133 template <
typename TIter>
134 using AccessIteratorByteType =
typename std::iterator_traits<typename std::decay<TIter>::type>::value_type;
136 template <
typename TIter>
137 struct AccessContainerByteTypeDetector
139 using Type = AccessIteratorByteType<TIter>;
142 template <
typename TContainer>
143 struct AccessContainerByteTypeDetector<std::back_insert_iterator<TContainer> >
145 using Type =
typename TContainer::value_type;
148 template <
typename TContainer>
149 struct AccessContainerByteTypeDetector<std::insert_iterator<TContainer> >
151 using Type =
typename TContainer::value_type;
154 template <
typename TContainer>
155 struct AccessContainerByteTypeDetector<std::front_insert_iterator<TContainer> >
157 using Type =
typename TContainer::value_type;
160 template <
typename TIter>
161 using AccessContainerByteType =
162 typename AccessContainerByteTypeDetector<typename std::decay<TIter>::type>::Type;
164 template <
typename TIter>
165 using AccessByteType =
166 typename comms::util::LazyShallowConditional<
167 std::is_void<AccessIteratorByteType<TIter> >::value
169 AccessContainerByteType,
170 AccessIteratorByteType,
174 template <
typename T,
typename TIter>
175 void writeBigUnsigned(T value, std::size_t size, TIter& iter)
177 using ValueType =
typename std::decay<T>::type;
178 static_assert(std::is_unsigned<ValueType>::value,
"T type must be unsigned");
179 static_assert(std::is_integral<ValueType>::value,
"T must be integral type");
181 using ByteType = AccessByteType<TIter>;
182 static_assert(!std::is_void<ByteType>::value,
"Invalid byte type");
183 using UnsignedByteType =
typename std::make_unsigned<ByteType>::type;
184 static const std::size_t BinDigits =
185 std::numeric_limits<UnsignedByteType>::digits;
186 static_assert(BinDigits % 8 == 0,
"Byte size assumption is not valid");
188 std::size_t remainingSize = size;
189 while (remainingSize > 0) {
190 std::size_t remaingShift = ((remainingSize - 1) * BinDigits);
191 auto byte =
static_cast<ByteType
>(value >> remaingShift);
198 template <
typename T,
typename TIter>
199 void writeLittleUnsigned(T value, std::size_t size, TIter& iter)
201 using ValueType =
typename std::decay<T>::type;
202 static_assert(std::is_integral<ValueType>::value,
"T must be integral type");
203 static_assert(std::is_unsigned<ValueType>::value,
"T type must be unsigned");
205 using ByteType = AccessByteType<TIter>;
206 static_assert(!std::is_void<ByteType>::value,
"Invalid byte type");
207 using UnsignedByteType =
typename std::make_unsigned<ByteType>::type;
208 static const std::size_t BinDigits =
209 std::numeric_limits<UnsignedByteType>::digits;
210 static_assert(BinDigits % 8 == 0,
"Byte size assumption is not valid");
212 std::size_t remainingSize = size;
213 while (remainingSize > 0) {
214 std::size_t remaingShift = ((size - remainingSize) * BinDigits);
216 auto byte =
static_cast<ByteType
>(value >> remaingShift);
223 template <
typename TEndian>
224 struct WriteUnsignedFuncWrapper;
227 struct WriteUnsignedFuncWrapper<traits::
endian::Big>
229 template <
typename T,
typename TIter>
230 static void write(T value, std::size_t size, TIter& iter)
232 writeBigUnsigned(value, size, iter);
239 template <
typename T,
typename TIter>
240 static void write(T value, std::size_t size, TIter& iter)
242 writeLittleUnsigned(value, size, iter);
246 template <
typename TEndian,
typename T,
typename TIter>
247 void write(T value, std::size_t size, TIter& iter)
249 using ValueType =
typename std::decay<T>::type;
250 static_assert(std::is_integral<ValueType>::value,
"T must be integral type");
251 using UnsignedType =
typename std::make_unsigned<ValueType>::type;
252 UnsignedType unsignedValue =
static_cast<UnsignedType
>(value);
253 WriteUnsignedFuncWrapper<TEndian>::write(unsignedValue, size, iter);
256 template <
typename TEndian,
typename T,
typename TIter>
257 void writeRandomAccess(T value, std::size_t size, TIter& iter)
259 using ValueType =
typename std::decay<T>::type;
261 static_assert(std::is_integral<ValueType>::value,
"T must be integral type");
264 typename std::iterator_traits<TIter>::iterator_category,
265 std::random_access_iterator_tag
267 "TIter must be random access iterator");
269 using ByteType = AccessByteType<TIter>;
270 static_assert(!std::is_void<ByteType>::value,
"Invalid byte type");
271 using UnsignedByteType =
typename std::make_unsigned<ByteType>::type;
272 static_assert(!std::is_const<UnsignedByteType>::value,
"Value must be updatable");
274 auto startPtr =
reinterpret_cast<UnsignedByteType*
>(&(*iter));
275 auto endPtr = startPtr;
276 write<TEndian>(value, size, endPtr);
277 iter += (endPtr - startPtr);
280 template <
typename...>
283 template <
typename... TParams>
284 using RandomAccessTag = comms::details::tag::Tag1<>;
286 template <
typename... TParams>
287 using RegularTag = comms::details::tag::Tag2<>;
289 template <
typename TIter>
290 using RandomAccessOrPointerTag =
291 typename comms::util::LazyShallowConditional<
292 std::is_pointer<TIter>::value &&
293 std::is_unsigned<AccessByteType<TIter> >::value
299 template <
typename TIter>
301 typename comms::util::LazyShallowConditional<
303 typename std::iterator_traits<TIter>::iterator_category,
304 std::random_access_iterator_tag
307 RandomAccessOrPointerTag,
312 template <
typename TEndian,
typename T,
typename TIter,
typename... TParams>
313 static void writeInternal(T value, std::size_t size, TIter& iter, RandomAccessTag<TParams...>)
315 writeRandomAccess<TEndian>(value, size, iter);
318 template <
typename TEndian,
typename T,
typename TIter,
typename... TParams>
319 static void writeInternal(T value, std::size_t size, TIter& iter, RegularTag<TParams...>)
321 details::write<TEndian>(value, size, iter);
325 template <
typename TEndian,
typename T,
typename TIter>
326 static void write(T value, std::size_t size, TIter& iter)
328 using ValueType =
typename std::decay<T>::type;
329 using AccessOptimisedValueType = details::AccessOptimisedValueType<ValueType>;
331 return writeInternal<TEndian>(
static_cast<AccessOptimisedValueType
>(value), size, iter, Tag<TIter>());
335 template <
typename T,
typename TIter>
336 T readBigUnsigned(std::size_t size, TIter& iter)
338 using ValueType =
typename std::decay<T>::type;
339 static_assert(std::is_integral<ValueType>::value,
"T must be integral type");
340 static_assert(std::is_unsigned<ValueType>::value,
"T type must be unsigned");
342 using ByteType = AccessByteType<TIter>;
343 static_assert(!std::is_void<ByteType>::value,
"Invalid byte type");
344 using UnsignedByteType =
typename std::make_unsigned<ByteType>::type;
345 static const std::size_t BinDigits =
346 std::numeric_limits<UnsignedByteType>::digits;
347 static_assert(BinDigits % 8 == 0,
"Byte size assumption is not valid");
350 std::size_t remainingSize = size;
351 while (remainingSize > 0) {
353 value =
static_cast<ValueType
>(value << BinDigits);
354 value |=
static_cast<decltype(value)
>(
static_cast<UnsignedByteType
>(byte));
361 template <
typename T,
typename TIter>
362 T readLittleUnsigned(std::size_t size, TIter& iter)
364 using ValueType =
typename std::decay<T>::type;
365 static_assert(std::is_integral<ValueType>::value,
"T must be integral type");
366 static_assert(std::is_unsigned<ValueType>::value,
"T type must be unsigned");
368 using ByteType = AccessByteType<TIter>;
369 static_assert(!std::is_void<ByteType>::value,
"Invalid byte type");
370 using UnsignedByteType =
typename std::make_unsigned<ByteType>::type;
371 static const std::size_t BinDigits =
372 std::numeric_limits<UnsignedByteType>::digits;
373 static_assert(BinDigits % 8 == 0,
"Byte size assumption is not valid");
376 std::size_t remainingSize = size;
377 while (remainingSize > 0) {
379 value |=
static_cast<ValueType
>(
static_cast<UnsignedByteType
>(byte)) <<
380 ((size - remainingSize) * BinDigits);
385 return static_cast<T
>(value);
388 template <
typename TEndian>
389 struct ReadUnsignedFuncWrapper;
392 struct ReadUnsignedFuncWrapper<traits::
endian::Big>
394 template <
typename T,
typename TIter>
395 static T read(std::size_t size, TIter& iter)
397 return readBigUnsigned<T>(size, iter);
404 template <
typename T,
typename TIter>
405 static T read(std::size_t size, TIter& iter)
407 return readLittleUnsigned<T>(size, iter);
411 template <
typename TEndian,
typename T,
typename TIter>
412 T read(std::size_t size, TIter& iter)
414 using ValueType =
typename std::decay<T>::type;
416 static_assert(std::is_integral<ValueType>::value,
"T must be integral type");
418 using UnsignedType =
typename std::make_unsigned<ValueType>::type;
419 auto value = ReadUnsignedFuncWrapper<TEndian>::template read<UnsignedType>(size, iter);
420 return static_cast<T
>(
static_cast<ValueType
>(value));
423 template <
typename TEndian,
typename T,
typename TIter>
424 T readFromPointerToSigned(std::size_t size, TIter& iter)
426 using ValueType =
typename std::decay<T>::type;
428 static_assert(std::is_integral<ValueType>::value,
"T must be integral type");
431 typename std::iterator_traits<TIter>::iterator_category,
432 std::random_access_iterator_tag
434 "TIter must be random access iterator");
436 using ByteType = AccessByteType<TIter>;
437 static_assert(!std::is_void<ByteType>::value,
"Invalid byte type");
438 using UnsignedByteType =
typename std::make_unsigned<ByteType>::type;
440 auto startPtr =
reinterpret_cast<const UnsignedByteType*
>(&(*iter));
441 auto endPtr = startPtr;
442 auto value = details::read<TEndian, ValueType>(size, endPtr);
443 iter += (endPtr - startPtr);
444 return static_cast<T
>(
static_cast<ValueType
>(value));
447 template <
typename...>
450 template <
typename... TParams>
451 using PointerToSignedTag = comms::details::tag::Tag1<>;
453 template <
typename... TParams>
454 using OtherTag = comms::details::tag::Tag2<>;
456 template <
typename TIter>
457 using PointerCheckTag =
458 typename comms::util::LazyShallowConditional<
459 std::is_const<AccessByteType<TIter> >::value &&
460 std::is_unsigned<AccessByteType<TIter> >::value
466 template <
typename TIter>
468 typename comms::util::LazyShallowConditional<
469 std::is_pointer<TIter>::value
476 template <
typename TEndian,
typename T,
typename TIter,
typename... TParams>
477 static T readInternal(std::size_t size, TIter& iter, PointerToSignedTag<TParams...>)
479 return readFromPointerToSigned<TEndian, T>(size, iter);
482 template <
typename TEndian,
typename T,
typename TIter,
typename... TParams>
483 static T readInternal(std::size_t size, TIter& iter, OtherTag<TParams...>)
485 return details::read<TEndian, T>(size, iter);
489 template <
typename TEndian,
typename T,
typename TIter>
490 static T read(std::size_t size, TIter& iter)
492 using ValueType =
typename std::decay<T>::type;
493 using AccessOptimisedValueType = details::AccessOptimisedValueType<ValueType>;
495 static_cast<ValueType
>(
496 readInternal<TEndian, AccessOptimisedValueType>(size, iter, Tag<TIter>()));
499 template <
typename TEndian,
typename T, std::
size_t TSize,
typename TIter>
500 static T read(TIter& iter)
502 using ValueType =
typename std::decay<T>::type;
503 using ByteType = details::AccessByteType<TIter>;
504 static_assert(!std::is_void<ByteType>::value,
"Invalid byte type");
505 static_assert(TSize <=
sizeof(ValueType),
"Precondition failure");
506 auto retval = read<TEndian, ValueType>(TSize, iter);
507 if (std::is_signed<ValueType>::value) {
508 retval = details::SignExt<>::template value<TSize, ByteType>(retval);
510 return static_cast<T
>(retval);
525 template <std::
size_t TSize,
typename T,
typename TIter>
528 details::WriteHelper<>::template write<traits::endian::Big>(value, TSize, iter);
540 template <
typename T,
typename TIter>
541 void writeBig(T value, std::size_t size, TIter& iter)
543 details::WriteHelper<>::template write<traits::endian::Big>(value, size, iter);
553 template <
typename T,
typename TIter>
556 using ValueType =
typename std::decay<T>::type;
557 writeBig<sizeof(ValueType)>(
static_cast<ValueType
>(value), iter);
570 template <
typename T, std::
size_t TSize,
typename TIter>
573 return details::ReadHelper<>::template read<traits::endian::Big, T, TSize>(iter);
584 template <
typename T,
typename TIter>
587 using ValueType =
typename std::decay<T>::type;
588 return static_cast<T
>(readBig<ValueType, sizeof(ValueType)>(iter));
600 template <
typename T,
typename TIter>
603 return details::ReadHelper<>::template read<traits::endian::Big, T>(size, iter);
615 template <std::
size_t TSize,
typename T,
typename TIter>
618 details::WriteHelper<>::template write<traits::endian::Little>(value, TSize, iter);
630 template <
typename T,
typename TIter>
633 details::WriteHelper<>::template write<traits::endian::Little>(value, size, iter);
643 template <
typename T,
typename TIter>
646 using ValueType =
typename std::decay<T>::type;
647 writeLittle<sizeof(ValueType)>(
static_cast<ValueType
>(value), iter);
660 template <
typename T, std::
size_t TSize,
typename TIter>
663 return details::ReadHelper<>::template read<traits::endian::Little, T, TSize>(iter);
674 template <
typename T,
typename TIter>
677 using ValueType =
typename std::decay<T>::type;
678 return static_cast<T
>(readLittle<ValueType, sizeof(ValueType)>(iter));
690 template <
typename T,
typename TIter>
693 return details::ReadHelper<>::template read<traits::endian::Little, T>(size, iter);
697 template <
typename T,
typename TIter>
703 static_cast<void>(endian);
708 template <std::
size_t TSize,
typename T,
typename TIter>
714 static_cast<void>(endian);
715 writeBig<TSize>(value, iter);
719 template <
typename T,
typename TIter>
726 static_cast<void>(endian);
731 template <
typename T,
typename TIter>
737 static_cast<void>(endian);
742 template <std::
size_t TSize,
typename T,
typename TIter>
748 static_cast<void>(endian);
749 return writeLittle<TSize>(value, iter);
753 template <
typename T,
typename TIter>
760 static_cast<void>(endian);
765 template <
typename T,
typename TIter>
768 static_cast<void>(endian);
769 return readBig<T>(iter);
773 template <
typename T,
typename TIter>
776 static_cast<void>(endian);
777 return readBig<T>(iter, size);
781 template <
typename T, std::
size_t TSize,
typename TIter>
784 static_cast<void>(endian);
785 return readBig<T, TSize>(iter);
789 template <
typename T,
typename TIter>
792 static_cast<void>(endian);
793 return readLittle<T>(iter);
797 template <
typename T, std::
size_t TSize,
typename TIter>
800 static_cast<void>(endian);
801 return readLittle<T, TSize>(iter);
805 template <
typename T,
typename TIter>
808 static_cast<void>(endian);
809 return readLittle<T>(iter, size);
util::traits::endian::Little Little
Empty class used in traits to indicate Little Endian.
Definition: traits.h:31
util::traits::endian::Big Big
Empty class used in traits to indicate Big Endian.
Definition: traits.h:28
void writeLittle(T value, TIter &iter)
Write part of integral value into the output area using little endian notation.
Definition: access.h:616
T readData(TIter &iter, const traits::endian::Big &endian)
Same as readBig<T, TIter>()
Definition: access.h:766
void writeData(T value, TIter &iter, const traits::endian::Big &endian)
Same as writeBig<T, TIter>()
Definition: access.h:698
T readBig(TIter &iter)
Read part of integral value from the input area using big endian notation.
Definition: access.h:571
void writeBig(T value, TIter &iter)
Write part of integral value into the output area using big endian notation.
Definition: access.h:526
T readLittle(TIter &iter)
Read part of integral value from the input area using little endian notation.
Definition: access.h:661
Main namespace for all classes / functions of COMMS library.
Replacement to std::conditional.
Definition: type_traits.h:28
Empty class used in traits to indicate Big Endian.
Definition: access.h:35
Empty class used in traits to indicate Little Endian.
Definition: access.h:38
Replacement to some types from standard type_traits.