YarrPP  0.1
C++ Library for Pirates
at_each_aligned.ipp
1 #include "at_each_aligned.hpp"
2 
4 
5 #include <utility>
6 
7 namespace yarr
8 {
9 
10 namespace detail
11 {
12 
13 template <typename... TFArgs>
15 
16 template <typename TFArg, typename... TFArgRest>
17 struct at_each_aligned_impl<TFArg, TFArgRest...>
18 {
19  static constexpr std::size_t byte_align = sizeof(TFArg);
20 
21  template <typename TChar, typename FApply, typename... FApplyRest>
22  YARR_ALWAYS_INLINE
23  static TChar* step(TChar* first, TChar* last, const FApply& apply, const FApplyRest&... apply_rest)
24  {
25  if (reinterpret_cast<std::uintptr_t>(first) % byte_align == 0
26  && first + byte_align <= last
27  )
28  {
29  apply(reinterpret_cast<TFArg*>(first));
30  return first + byte_align;
31  }
32  else
33  {
34  return at_each_aligned_impl<TFArgRest...>::step(first, last, apply_rest...);
35  }
36  }
37 };
38 
39 template <typename T>
41 {
42  static_assert(sizeof(T) == 1, "You must provide a single byte type to at_each_aligned");
43 
44  template <typename TChar, typename FApply>
45  YARR_ALWAYS_INLINE
46  static TChar* step(TChar* first, TChar*, const FApply& apply)
47  {
48  apply(reinterpret_cast<T*>(first));
49  return first + 1;
50  }
51 };
52 
53 template <typename... TFArgs, typename TChar, typename... FApply>
54 void at_each_aligned(TChar* first, TChar* last, FApply&&... transform)
55 {
56  for ( ; first < last; /* inline */)
57  {
58  first = at_each_aligned_impl<TFArgs...>::step(first, last, transform...);
59  }
60 }
61 
62 }
63 
64 template <typename... TFArgs, typename... FApply>
65 void at_each_aligned(char* first, char* last, FApply&&... transform)
66 {
67  detail::at_each_aligned<TFArgs...>(first, last, std::forward<FApply>(transform)...);
68 }
69 
70 template <typename... TFArgs, typename... FApply>
71 void at_each_aligned(const char* first, const char* last, FApply&&... transform)
72 {
73  detail::at_each_aligned<const TFArgs...>(first, last, std::forward<FApply>(transform)...);
74 }
75 
76 }