libutil++  1.9.3
 All Classes Functions Variables
Binary.cpp
1 /*
2 ** libutil++
3 ** $Id: Binary.cpp 1702 2016-08-13 23:26:06Z sella $
4 ** Copyright (c) 2011-2016 Digital Genesis, LLC. All Rights Reserved.
5 ** Released under the LGPL Version 2.1 License.
6 ** http://www.digitalgenesis.com
7 */
8 
9 static const char rcsid[] __attribute__((used)) = "$Id: Binary.cpp 1702 2016-08-13 23:26:06Z sella $";
10 
11 #include "Binary.h"
12 #include "../util/CommonMacro.h"
13 
14 using namespace sella::variant;
15 
16 Binary::Binary() throw () : Nullable(std::make_shared<std::vector<uint8_t>>()) { }
17 
18 Binary::Binary(const std::string &value) throw (TypeCastException) : Nullable() {
19  if (boost::regex_match(value, Binary::Pattern())) {
20  short unsigned int v;
21  char buf[3] = { 0, 0, 0 };
22  this->value = std::make_shared<std::vector<uint8_t>>();
23 
24  for (auto it = value.begin() + 2, end = value.end(); it != end; ++it, ++it) {
25  buf[0] = *(it + 0);
26  buf[1] = *(it + 1);
27 
28  sscanf(buf, "%hx", &v);
29 
30  (*std::static_pointer_cast<std::vector<uint8_t>>(this->value)).push_back((uint8_t) v);
31  }
32  } else {
33  THROW(TypeCastException, "unable to cast '%s' to a binary value", value.c_str());
34  }
35 }
36 
37 Binary::Binary(const std::vector<uint8_t> &value) throw () : Nullable(std::make_shared<std::vector<uint8_t>>(value)) { }
38 
39 Binary::Binary(const Binary &other) throw () : Nullable() {
40  if (this != &other) {
41  if (!other.isNull()) {
42  if (isNull()) {
43  this->value = std::make_shared<std::vector<uint8_t>>(other.get());
44  } else {
45  *std::static_pointer_cast<std::vector<uint8_t>>(this->value) = *std::static_pointer_cast<std::vector<uint8_t>>(other.value);
46  }
47  } else {
48  this->value.reset();
49  }
50  }
51 }
52 
53 bool Binary::operator==(const Binary &other) const throw () {
54  return (*std::static_pointer_cast<std::vector<uint8_t>>(this->value) == *std::static_pointer_cast<std::vector<uint8_t>>(other.value));
55 }
56 
57 bool Binary::operator!=(const Binary &other) const throw () {
58  return !(*this == other);
59 }
60 
61 Binary& Binary::operator=(const Binary &other) throw () {
62  if (LIKELY(this != &other)) {
63  if (!other.isNull()) {
64  if (isNull()) {
65  this->value = std::make_shared<std::vector<uint8_t>>(other.get());
66  } else {
67  *std::static_pointer_cast<std::vector<uint8_t>>(this->value) = *std::static_pointer_cast<std::vector<uint8_t>>(other.value);
68  }
69  } else {
70  this->value.reset();
71  }
72  }
73 
74  return *this;
75 }
76 
77 Binary::~Binary() throw () { }
78 
79 const std::vector<uint8_t>& Binary::get() const throw (UnsupportedOperatorException) {
80  if (isNull()) {
81  THROW(UnsupportedOperatorException, "unable to take reference of null value");
82  }
83 
84  return *std::static_pointer_cast<std::vector<uint8_t>>(this->value);
85 }
86 
87 std::vector<uint8_t>& Binary::get() throw (UnsupportedOperatorException) {
88  if (isNull()) {
89  THROW(UnsupportedOperatorException, "unable to take reference of null value");
90  }
91 
92  return *std::static_pointer_cast<std::vector<uint8_t>>(this->value);
93 }
94 
95 size_t Binary::size() const throw () {
96  if (isNull()) {
97  return 0;
98  }
99 
100  return get().size();
101 }
102 
103 bool Binary::empty() const throw () {
104  if (isNull()) {
105  return true;
106  }
107 
108  return get().empty();
109 }
110 
111 void Binary::clear() throw() {
112  if (isNull()) {
113  this->value = std::make_shared<std::vector<uint8_t>>();
114  } else {
115  std::static_pointer_cast<std::vector<uint8_t>>(this->value)->clear();
116  }
117 }
118 
119 #if 1
120 void Binary::msgpack(sella::util::MessagePack &mpack, uint32_t &offset) const throw (TypeCastException) {
121  uint32_t c;
122 
123  if (UNLIKELY(isNull())) {
124  c = mpack.append(offset);
125 
126  offset += c;
127 
128  if (UNLIKELY(c == 0)) {
129  THROW(TypeCastException, "Failed to append '%s' at offset %d (buffer length: %d)", str(JSON).c_str(), offset, mpack.length());
130  }
131  } else {
132  auto &vector = this->get();
133 
134  c = mpack.append_vector(offset, vector.size());
135 
136  offset += c;
137 
138  if (UNLIKELY(c == 0)) {
139  THROW(TypeCastException, "Failed to append '%s' at offset %d (buffer length: %d)", str(JSON).c_str(), offset, mpack.length());
140  }
141 
142  for (auto v = vector.begin(), end = vector.end(); v != end; ++v) {
143  c = mpack.append(offset, (uint64_t) *v);
144 
145  offset += c;
146 
147  if (UNLIKELY(c == 0)) {
148  THROW(TypeCastException, "Failed to append '%s' at offset %d (buffer length: %d)", str(JSON).c_str(), offset, mpack.length());
149  }
150  }
151  }
152 }
153 
154 #else
155 uint32_t Binary::msgpack(sella::util::MessagePack &mpack, uint32_t &offset) const throw (TypeCastException) {
156  uint32_t c, o = offset;
157 
158  if (UNLIKELY(isNull())) {
159  if (UNLIKELY((c = mpack.append(offset)) == 0)) {
160  THROW(TypeCastException, "Failed to append '%s' at offset %d (buffer length: %d)", str(JSON).c_str(), offset, mpack.length());
161  }
162 
163  offset += c;
164  } else {
165  auto &vector = this->get();
166 
167  if (UNLIKELY((c = mpack.append_vector(offset, vector.size())) == 0)) {
168  THROW(TypeCastException, "Failed to append '%s' at offset %d (buffer length: %d)", str(JSON).c_str(), offset, mpack.length());
169  }
170 
171  offset += c;
172 
173  for (auto v = vector.begin(), end = vector.end(); v != end; ++v) {
174  if (UNLIKELY((c = mpack.append(offset, (uint64_t) *v)) == 0)) {
175  THROW(TypeCastException, "Failed to append '%s' at offset %d (buffer length: %d)", str(JSON).c_str(), offset, mpack.length());
176  }
177 
178  offset += c;
179  }
180  }
181 
182  return (offset - o);
183 }
184 #endif
185 
186 void Binary::msgpackBufferSize(size_t &size) const throw () {
187  if (UNLIKELY(isNull())) {
188  size += 1;
189 
190  return;
191  }
192 
193  size += 5 + std::static_pointer_cast<std::vector<uint8_t>>(this->value)->size();
194 }
195 
196 std::string Binary::str(int type) const throw () {
197  if (UNLIKELY(isNull())) {
198  return "null";
199  }
200 
201  char buffer[32];
202  std::string output("0x");
203  const std::vector<uint8_t> &data = this->get();
204 
205  for (auto it = data.begin(), end = data.end(); it != end; ++it) {
206  snprintf(buffer, sizeof(buffer), "%02x", *it);
207  output.append(buffer);
208  }
209 
210  return output;
211 }
212 
213 bool Binary::isType(const char *value, size_t size) throw () {
214  if (size < 2 || value[0] != '0' || value[1] != 'x' || size % 2 != 0) { /* Starts with 0x and must be even. */
215  return false;
216  }
217 
218  for (size_t i = 2; i < size; i += 2) {
219  if (!::isxdigit(value[i]) != 0 || !::isxdigit(value[i + 1]) != 0) {
220  return false;
221  }
222  }
223 
224  return true;
225 }
226 
227 /*
228 ** vim: noet ts=3 sw=3
229 */