datasketches-cpp
serde.hpp
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #ifndef DATASKETCHES_SERDE_HPP_
21 #define DATASKETCHES_SERDE_HPP_
22 
23 #include <cstring>
24 #include <iostream>
25 #include <memory>
26 #include <string>
27 #include <exception>
28 
29 #include "memory_operations.hpp"
30 
31 namespace datasketches {
32 
34 template<typename T, typename Enable = void> struct serde {
41  void serialize(std::ostream& os, const T* items, unsigned num) const;
42 
49  void deserialize(std::istream& is, T* items, unsigned num) const;
50 
58  size_t serialize(void* ptr, size_t capacity, const T* items, unsigned num) const;
59 
67  size_t deserialize(const void* ptr, size_t capacity, T* items, unsigned num) const;
68 
74  size_t size_of_item(const T& item) const;
75 };
76 
80 template<typename T>
81 struct serde<T, typename std::enable_if<std::is_arithmetic<T>::value>::type> {
83  void serialize(std::ostream& os, const T* items, unsigned num) const {
84  bool failure = false;
85  try {
86  os.write(reinterpret_cast<const char*>(items), sizeof(T) * num);
87  } catch (std::ostream::failure&) {
88  failure = true;
89  }
90  if (failure || !os.good()) {
91  throw std::runtime_error("error writing to std::ostream with " + std::to_string(num) + " items");
92  }
93  }
94 
95  void deserialize(std::istream& is, T* items, unsigned num) const {
96  bool failure = false;
97  try {
98  is.read((char*)items, sizeof(T) * num);
99  } catch (std::istream::failure&) {
100  failure = true;
101  }
102  if (failure || !is.good()) {
103  throw std::runtime_error("error reading from std::istream with " + std::to_string(num) + " items");
104  }
105  }
106 
108  size_t serialize(void* ptr, size_t capacity, const T* items, unsigned num) const {
109  const size_t bytes_written = sizeof(T) * num;
110  check_memory_size(bytes_written, capacity);
111  memcpy(ptr, items, bytes_written);
112  return bytes_written;
113  }
114 
116  size_t deserialize(const void* ptr, size_t capacity, T* items, unsigned num) const {
117  const size_t bytes_read = sizeof(T) * num;
118  check_memory_size(bytes_read, capacity);
119  memcpy(items, ptr, bytes_read);
120  return bytes_read;
121  }
122 
124  size_t size_of_item(const T& item) const {
125  unused(item);
126  return sizeof(T);
127  }
128 };
129 
135 template<>
136 struct serde<std::string> {
138  void serialize(std::ostream& os, const std::string* items, unsigned num) const {
139  unsigned i = 0;
140  bool failure = false;
141  try {
142  for (; i < num && os.good(); i++) {
143  uint32_t length = static_cast<uint32_t>(items[i].size());
144  os.write((char*)&length, sizeof(length));
145  os.write(items[i].c_str(), length);
146  }
147  } catch (std::ostream::failure&) {
148  failure = true;
149  }
150  if (failure || !os.good()) {
151  throw std::runtime_error("error writing to std::ostream at item " + std::to_string(i));
152  }
153  }
154 
156  void deserialize(std::istream& is, std::string* items, unsigned num) const {
157  unsigned i = 0;
158  bool failure = false;
159  try {
160  for (; i < num; i++) {
161  uint32_t length;
162  is.read((char*)&length, sizeof(length));
163  if (!is.good()) { break; }
164  std::string str;
165  str.reserve(length);
166  for (uint32_t j = 0; j < length; j++) {
167  str.push_back(static_cast<char>(is.get()));
168  }
169  if (!is.good()) { break; }
170  new (&items[i]) std::string(std::move(str));
171  }
172  } catch (std::istream::failure&) {
173  failure = true;
174  }
175  if (failure || !is.good()) {
176  // clean up what we've already allocated
177  for (unsigned j = 0; j < i; ++j) {
178  items[j].~basic_string();
179  }
180  throw std::runtime_error("error reading from std::istream at item " + std::to_string(i));
181  }
182  }
183 
185  size_t serialize(void* ptr, size_t capacity, const std::string* items, unsigned num) const {
186  size_t bytes_written = 0;
187  for (unsigned i = 0; i < num; ++i) {
188  const uint32_t length = static_cast<uint32_t>(items[i].size());
189  const size_t new_bytes = length + sizeof(length);
190  check_memory_size(bytes_written + new_bytes, capacity);
191  memcpy(ptr, &length, sizeof(length));
192  ptr = static_cast<char*>(ptr) + sizeof(uint32_t);
193  memcpy(ptr, items[i].c_str(), length);
194  ptr = static_cast<char*>(ptr) + length;
195  bytes_written += new_bytes;
196  }
197  return bytes_written;
198  }
199 
201  size_t deserialize(const void* ptr, size_t capacity, std::string* items, unsigned num) const {
202  size_t bytes_read = 0;
203  unsigned i = 0;
204  bool failure = false;
205  for (; i < num && !failure; ++i) {
206  uint32_t length;
207  if (bytes_read + sizeof(length) > capacity) {
208  bytes_read += sizeof(length); // we'll use this to report the error
209  failure = true;
210  break;
211  }
212  memcpy(&length, ptr, sizeof(length));
213  ptr = static_cast<const char*>(ptr) + sizeof(uint32_t);
214  bytes_read += sizeof(length);
215 
216  if (bytes_read + length > capacity) {
217  bytes_read += length; // we'll use this to report the error
218  failure = true;
219  break;
220  }
221  new (&items[i]) std::string(static_cast<const char*>(ptr), length);
222  ptr = static_cast<const char*>(ptr) + length;
223  bytes_read += length;
224  }
225 
226  if (failure) {
227  // clean up what we've already allocated
228  for (unsigned j = 0; j < i; ++j)
229  items[j].~basic_string();
230  // using this for a consistent error message
231  check_memory_size(bytes_read, capacity);
232  }
233 
234  return bytes_read;
235  }
236 
238  size_t size_of_item(const std::string& item) const {
239  return sizeof(uint32_t) + item.size();
240  }
241 };
242 
243 } /* namespace datasketches */
244 
245 # endif
DataSketches namespace.
Definition: binomial_bounds.hpp:38
size_t size_of_item(const T &item) const
Size of the given item.
Definition: serde.hpp:124
size_t deserialize(const void *ptr, size_t capacity, T *items, unsigned num) const
Raw bytes deserialization.
Definition: serde.hpp:116
void serialize(std::ostream &os, const T *items, unsigned num) const
Stream serialization.
Definition: serde.hpp:83
size_t serialize(void *ptr, size_t capacity, const T *items, unsigned num) const
Raw bytes serialization.
Definition: serde.hpp:108
void serialize(std::ostream &os, const std::string *items, unsigned num) const
Stream serialization.
Definition: serde.hpp:138
size_t serialize(void *ptr, size_t capacity, const std::string *items, unsigned num) const
Raw bytes serialization.
Definition: serde.hpp:185
size_t size_of_item(const std::string &item) const
Size of the given item.
Definition: serde.hpp:238
size_t deserialize(const void *ptr, size_t capacity, std::string *items, unsigned num) const
Raw bytes deserialization.
Definition: serde.hpp:201
void deserialize(std::istream &is, std::string *items, unsigned num) const
Stream deserialization.
Definition: serde.hpp:156
Interface for serializing and deserializing items.
Definition: serde.hpp:34
size_t size_of_item(const T &item) const
Size of the given item.
size_t deserialize(const void *ptr, size_t capacity, T *items, unsigned num) const
Raw bytes deserialization.
void deserialize(std::istream &is, T *items, unsigned num) const
Stream deserialization.
void serialize(std::ostream &os, const T *items, unsigned num) const
Stream serialization.
size_t serialize(void *ptr, size_t capacity, const T *items, unsigned num) const
Raw bytes serialization.