fastcgi++  3.1alpha
A C++ FastCGI/Web API
endian.hpp
Go to the documentation of this file.
1 
9 /*******************************************************************************
10 * Copyright (C) 2018 Eddie Carle [eddie@isatec.ca] *
11 * *
12 * This file is part of fastcgi++. *
13 * *
14 * fastcgi++ is free software: you can redistribute it and/or modify it under *
15 * the terms of the GNU Lesser General Public License as published by the Free *
16 * Software Foundation, either version 3 of the License, or (at your option) *
17 * any later version. *
18 * *
19 * fastcgi++ is distributed in the hope that it will be useful, but WITHOUT ANY *
20 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
21 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for *
22 * more details. *
23 * *
24 * You should have received a copy of the GNU Lesser General Public License *
25 * along with fastcgi++. If not, see <http://www.gnu.org/licenses/>. *
26 *******************************************************************************/
27 
28 #ifndef FASTCGIPP_ENDIAN_HPP
29 #define FASTCGIPP_ENDIAN_HPP
30 
31 #include <cstdint>
32 #include <type_traits>
33 
35 namespace Fastcgipp
36 {
38  class BigEndian_base
39  {
40  protected:
42  template<unsigned Size> struct Unsigned;
43 
44  static constexpr void from(
45  const unsigned char* arr,
46  std::uint16_t& v) noexcept
47  {
48  v = static_cast<std::uint16_t>(
49  std::uint16_t{arr[0]} << 8 |
50  std::uint16_t{arr[1]} << 0);
51  }
52  static constexpr void from(
53  const unsigned char* arr,
54  std::uint32_t& v) noexcept
55  {
56  v = static_cast<std::uint32_t>(
57  std::uint32_t{arr[0]} << 24 |
58  std::uint32_t{arr[1]} << 16 |
59  std::uint32_t{arr[2]} << 8 |
60  std::uint32_t{arr[3]} << 0);
61  }
62  static constexpr void from(
63  const unsigned char* arr,
64  std::uint64_t& v) noexcept
65  {
66  v = static_cast<std::uint64_t>(
67  std::uint64_t{arr[0]} << 56 |
68  std::uint64_t{arr[1]} << 48 |
69  std::uint64_t{arr[2]} << 40 |
70  std::uint64_t{arr[3]} << 32 |
71  std::uint64_t{arr[4]} << 24 |
72  std::uint64_t{arr[5]} << 16 |
73  std::uint64_t{arr[6]} << 8 |
74  std::uint64_t{arr[7]} << 0);
75  }
76 
77  static constexpr void to(unsigned char* arr, const std::uint16_t v)
78  {
79  arr[0] = static_cast<unsigned char>((v & 0xff00) >> 8);
80  arr[1] = static_cast<unsigned char>((v & 0x00ff) >> 0);
81  }
82  static constexpr void to(unsigned char* arr, const std::uint32_t v)
83  {
84  arr[0] = static_cast<unsigned char>((v & 0xff000000) >> 24);
85  arr[1] = static_cast<unsigned char>((v & 0x00ff0000) >> 16);
86  arr[2] = static_cast<unsigned char>((v & 0x0000ff00) >> 8);
87  arr[3] = static_cast<unsigned char>((v & 0x000000ff) >> 0);
88  }
89  static constexpr void to(unsigned char* arr, const std::uint64_t v)
90  {
91  arr[0] = static_cast<unsigned char>((v & 0xff00000000000000) >> 56);
92  arr[1] = static_cast<unsigned char>((v & 0x00ff000000000000) >> 48);
93  arr[2] = static_cast<unsigned char>((v & 0x0000ff0000000000) >> 40);
94  arr[3] = static_cast<unsigned char>((v & 0x000000ff00000000) >> 32);
95  arr[4] = static_cast<unsigned char>((v & 0x00000000ff000000) >> 24);
96  arr[5] = static_cast<unsigned char>((v & 0x0000000000ff0000) >> 16);
97  arr[6] = static_cast<unsigned char>((v & 0x000000000000ff00) >> 8);
98  arr[7] = static_cast<unsigned char>((v & 0x00000000000000ff) >> 0);
99  }
100  };
101 
102  template<> struct BigEndian_base::Unsigned<2>
103  {
104  typedef std::uint16_t Type;
105  };
106  template<> struct BigEndian_base::Unsigned<4>
107  {
108  typedef std::uint32_t Type;
109  };
110  template<> struct BigEndian_base::Unsigned<8>
111  {
112  typedef std::uint64_t Type;
113  };
114 
116 
125  template<typename T> class BigEndian: private BigEndian_base
126  {
127  private:
128  static constexpr unsigned s_size = sizeof(T);
129  static_assert(s_size==2||s_size==4||s_size==8, "Fastcgipp::BigEndian"
130  " can only work with types of size 2, 4 or 8.");
131  static_assert(std::is_trivially_copyable<T>::value, "Fastcgipp::"
132  "BigEndian can only work with trivial copyable types.");
133 
135  typedef typename Unsigned<s_size>::Type BaseType;
136 
138  unsigned char m_data[s_size];
139 
141  constexpr void set(T x) noexcept
142  {
143  union {
144  BaseType base;
145  T actual;
146  } u = {.actual = x};
147  to(m_data, u.base);
148  }
149 
150  public:
151  constexpr BigEndian& operator=(T x) noexcept
152  {
153  set(x);
154  return *this;
155  }
156 
157  constexpr BigEndian(T x) noexcept
158  {
159  set(x);
160  }
161 
162  constexpr BigEndian() noexcept
163  {}
164 
165  constexpr operator T() const noexcept
166  {
167  return read(m_data);
168  }
169 
171 
178  static constexpr T read(const unsigned char* source) noexcept
179  {
180  union {
181  BaseType base;
182  T actual;
183  } u = {.base = 0 };
184  from(source, u.base);
185  return u.actual;
186  }
187 
189  static constexpr T read(const char* source) noexcept
190  {
191  return read(reinterpret_cast<const unsigned char*>(source));
192  }
193 
195  constexpr const char* data() const
196  {
197  return reinterpret_cast<const char*>(&m_data);
198  }
199 
201  constexpr unsigned size() const
202  {
203  return s_size;
204  }
205  };
206 }
207 
208 #endif
Fastcgipp::BigEndian::read
static constexpr T read(const unsigned char *source) noexcept
Static function for reading the value out of a data array.
Definition: endian.hpp:195
Fastcgipp::BigEndian_base
De-templated.
Definition: endian.hpp:55
Fastcgipp::BigEndian::data
constexpr const char * data() const
Pointer to start of big endian integer representation.
Definition: endian.hpp:212
Fastcgipp::BigEndian_base::Unsigned
Get unsigned integral type from size.
Definition: endian.hpp:76
Fastcgipp::BigEndian::m_data
unsigned char m_data[s_size]
The raw data of the big endian integer.
Definition: endian.hpp:155
Fastcgipp::BigEndian::size
constexpr unsigned size() const
Size in bytes of value.
Definition: endian.hpp:218
Fastcgipp::BigEndian::s_size
static constexpr unsigned s_size
Definition: endian.hpp:145
Fastcgipp::BigEndian::BaseType
Unsigned< s_size >::Type BaseType
Underlying unsigned integral type.
Definition: endian.hpp:147
Fastcgipp
Topmost namespace for the fastcgi++ library.
Definition: fcgistreambuf.cpp:34
Fastcgipp::BigEndian::operator=
constexpr BigEndian & operator=(T x) noexcept
Definition: endian.hpp:168
Fastcgipp::BigEndian::set
constexpr void set(T x) noexcept
Set the internal data to the passed parameter.
Definition: endian.hpp:158
Fastcgipp::BigEndian_base::to
static constexpr void to(unsigned char *arr, const std::uint16_t v)
Definition: endian.hpp:111
Fastcgipp::BigEndian_base::from
static constexpr void from(const unsigned char *arr, std::uint16_t &v) noexcept
Definition: endian.hpp:78
Fastcgipp::BigEndian::BigEndian
constexpr BigEndian() noexcept
Definition: endian.hpp:179
Fastcgipp::BigEndian
Allows raw storage of types in big endian format.
Definition: endian.hpp:142