staticlib_io  1.2.11
 All Classes Namespaces Files Functions Variables
hex_source.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2018, alex at staticlibs.net
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * File: hex_source.hpp
19  * Author: alex
20  *
21  * Created on June 2, 2018, 10:31 PM
22  */
23 
24 #ifndef STATICLIB_IO_HEX_SOURCE_HPP
25 #define STATICLIB_IO_HEX_SOURCE_HPP
26 
27 #include <cerrno>
28 #include <cstdlib>
29 #include <array>
30 #include <ios>
31 
32 #include "staticlib/config.hpp"
33 
37 #include "staticlib/io/span.hpp"
38 
39 namespace staticlib {
40 namespace io {
41 
45 template<typename Source>
46 class hex_source {
54  std::array<char, 3> hbuf;
55 
56 public:
63  explicit hex_source(Source&& src) :
64  src(make_buffered_source(std::move(src))) {
65  hbuf[0] = '\0';
66  hbuf[1] = '\0';
67  hbuf[2] = '\0';
68  }
69 
75  hex_source(const hex_source&) = delete;
76 
83  hex_source& operator=(const hex_source&) = delete;
84 
90  hex_source(hex_source&& other) STATICLIB_NOEXCEPT :
91  src(std::move(other.src)),
92  hbuf(std::move(other.hbuf)) { }
93 
100  hex_source& operator=(hex_source&& other) STATICLIB_NOEXCEPT {
101  src = std::move(other.src);
102  hbuf = std::move(other.hbuf);
103  return *this;
104  }
105 
112  std::streamsize read(span<char> span) {
113  size_t idx = 0;
114  while (idx < span.size()) {
115  auto read = read_all(src, {hbuf.data(), 2});
116  if (2 == read) {
117  char* end = nullptr;
118  errno = 0;
119  char byte = static_cast<char> (strtol(hbuf.data(), std::addressof(end), 16));
120  if (errno == ERANGE || end != hbuf.data() + 2) {
121  throw io_exception(TRACEMSG("Error parsing byte from HEX-pair: [" + std::string(hbuf.data(), 2) + "]"));
122  }
123  span.data()[idx] = byte;
124  idx += 1;
125  } else if (1 == read) {
126  throw io_exception(TRACEMSG("Invalid non-even number of bytes available in HEX source"));
127  } else if (0 == read) {
128  break;
129  } else {
130  throw io_exception(TRACEMSG("Invalid hex decoder state"));
131  }
132  }
133  if (idx > 0) {
134  return static_cast<std::streamsize>(idx);
135  }
136  return std::char_traits<char>::eof();
137  }
138 
144  Source& get_source() {
145  return src.get_source();
146  }
147 
148 };
149 
157 template <typename Source,
158  class = typename std::enable_if<!std::is_lvalue_reference<Source>::value>::type>
160  return hex_source<Source>(std::move(source));
161 }
162 
170 template <typename Source>
173 }
174 
175 } // namespace
176 }
177 
178 
179 #endif /* STATICLIB_IO_HEX_SOURCE_HPP */
180