KJB
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
l_serialization.h
Go to the documentation of this file.
1 /* $Id: l_serialization.h 18301 2014-11-26 19:17:13Z ksimek $ */
2 /* =========================================================================== *
3  |
4  | Copyright (c) 1994-2010 by Kobus Barnard (author)
5  |
6  | Personal and educational use of this code is granted, provided that this
7  | header is kept intact, and that the authorship is not misrepresented, that
8  | its use is acknowledged in publications, and relevant papers are cited.
9  |
10  | For other use contact the author (kobus AT cs DOT arizona DOT edu).
11  |
12  | Please note that the code in this file has not necessarily been adequately
13  | tested. Naturally, there is no guarantee of performance, support, or fitness
14  | for any particular task. Nonetheless, I am interested in hearing about
15  | problems that you encounter.
16  |
17  | Author: Kyle Simek
18  * =========================================================================== */
19 
20 #ifndef KJB_L_SERIALIZATION_H
21 #define KJB_L_SERIALIZATION_H
22 
23 #include <l/l_sys_def.h>
24 #include <l/l_sys_lib.h>
25 #include <l/l_sys_io.h>
26 #include <l_cpp/l_util.h>
27 #include <l_cpp/l_exception.h>
28 #include <l_cpp/l_index.h>
29 
30 #include <string>
31 #include <iterator>
32 #include <fstream>
33 
34 #include <boost/format.hpp>
35 #include <boost/utility/enable_if.hpp>
36 #include <boost/type_traits.hpp>
37 
38 
39 #ifdef KJB_HAVE_BST_SERIAL
40 #include <boost/archive/text_iarchive.hpp>
41 #include <boost/archive/text_oarchive.hpp>
42 #include <boost/archive/binary_iarchive.hpp>
43 #include <boost/archive/binary_oarchive.hpp>
44 #endif
45 
46 #include <boost/concept_check.hpp>
47 #include <boost/concept_archetype.hpp>
48 #include <boost/static_assert.hpp>
49 
50 
51 // boost serialization of most
52 namespace kjb {
53 
54 
81 template <class X>
83 {
85  {
86 #ifdef KJB_HAVE_BST_SERIAL
87 
88  std::ofstream ofs("");
89  std::ifstream ifs("");
90 
91  boost::archive::text_oarchive oa(ofs);
92  boost::archive::text_iarchive ia(ifs);
93 
94  X* i = NULL;
95 
96  oa << *i;
97  ia >> *i;
98 #else
99  static const bool boost_serialization_not_available = true;
100  BOOST_STATIC_ASSERT(boost_serialization_not_available == true);
101 #endif /* KJB_HAVE_BST_SERIAL */
102  }
103 };
104 
116 template <class Archive, class KJB_readable_writable>
117 void kjb_serialize_default(Archive & ar, KJB_readable_writable& obj, const unsigned int /* version */)
118 {
119 #ifdef KJB_HAVE_BST_SERIAL
120  // This is pretty hacky. We basically use the existing "write-to-file"/"read-from-file" semantics to convert the matrix to/from a string and then serialize the string representation.
121 
122  std::string obj_as_string;
123 
124  char tmp_fname[ MAXPATHLEN ];
125 
126  // create a legal and unique temporary file name
127  KJB( ETX( BUFF_GET_TEMP_FILE_NAME( tmp_fname ) ) );
128  // (this solution is not thread-safe
129  // and could result in race conditions. Evenutally, we
130  // should write real serialization methods for vector, matrix, and
131  // everything else that calls this template function. -- Kyle Apr 3, 2011
132 
133  if(Archive::is_saving::value == true)
134  {
135  obj.write(tmp_fname);
136 
137  std::ifstream ifs(tmp_fname);
138 
139  // read entire contents into text
140  obj_as_string.assign(
141  std::istreambuf_iterator<char>(ifs),
142  std::istreambuf_iterator<char>());
143 
144  }
145 
146  // do serialization of the string representation
147  ar & obj_as_string;
148 
149  if(Archive::is_loading::value == true)
150  {
151  {
152  //write entire file
153  std::ofstream ofs(tmp_fname);
154  ofs << obj_as_string;
155  }
156 
157  // read file into m
158  KJB_readable_writable tmp_matrix(tmp_fname);
159  obj.swap(tmp_matrix);
160  }
161 
162  // delete tmp file
163  ETX( kjb_c::kjb_unlink( tmp_fname ) );
164 #else /* KJB_HAVE_BST_SERIAL */
165  KJB_THROW_2(Missing_dependency, "boost::serialization");
166 #endif /* KJB_HAVE_BST_SERIAL */
167 }
168 
169 template <class Archive, class KJB_readable_writable>
170 void kjb_serialize(Archive & ar, KJB_readable_writable& obj, const unsigned int version)
171 {
172  kjb_serialize_default(ar, obj, version);
173 }
174 
199 template <class Serializable>
200 #ifdef KJB_HAVE_BST_SERIAL
201 void load(Serializable& obj, const std::string& fname)
202 #else
203 void load(Serializable&, const std::string&)
204 #endif
205 {
206 #ifdef KJB_HAVE_BST_SERIAL
207  // consider adding load(stream, object), also
208 
209  BOOST_CONCEPT_ASSERT((SerializableConcept<Serializable>));
210 
211  std::ifstream ifs(fname.c_str());
212  if(ifs.fail())
213  {
214  KJB_THROW_3(IO_error, "Error opening %s.", (fname.c_str()));
215  }
216 
217  try
218  {
219  boost::archive::text_iarchive ia(ifs);
220  ia >> obj;
221  }
222  catch(boost::archive::archive_exception& ex)
223  {
224  KJB_THROW_3(IO_error, "Error reading %s. Format may be invalid. Boost error was: %s", (fname.c_str())(ex.what()));
225  }
226 
227 #else
228  KJB_THROW_2(Missing_dependency, "boost::serialization");
229 #endif
230 }
231 
248 template <class SerializableOutputIterator>
249 void load_many(SerializableOutputIterator it, const std::string& fmt_str, const Index_range& indices)
250 {
251  BOOST_CONCEPT_ASSERT((SerializableConcept<
252  typename std::iterator_traits<SerializableOutputIterator>::value_type
253  >));
254 
255  const size_t size = indices.size();
256  boost::format fmt(fmt_str);
257  for(size_t ii = 0; ii < size; ii++)
258  {
259  size_t i = indices[ii];
260 
261  std::string fname = (fmt % i).str();
262  load(*it++, fname);
263  }
264 }
265 
276 template <class SerializableOutputIterator>
277 void load_many(SerializableOutputIterator it, const std::string& fmt_str, size_t num_files, size_t first_index = 0, size_t modulo = 0)
278 {
279  BOOST_CONCEPT_ASSERT((SerializableConcept<
280  typename std::iterator_traits<SerializableOutputIterator>::value_type
281  >));
282 
283  Index_range indices(
284  first_index,
285  first_index + num_files - 1,
286  modulo);
287 
288  load_many(it, fmt_str, indices);
289 }
290 
291 template <class Value_type, class SerializablePtrOutputIterator>
292 void load_many_dynamic_dispatch(Value_type* /* trash */, SerializablePtrOutputIterator it, const std::string& fmt_str, const Index_range& indices )
293 {
294  BOOST_CONCEPT_ASSERT((SerializableConcept<Value_type>));
295 
296  boost::format fmt(fmt_str);
297  const size_t size = indices.size();
298  for(size_t ii = 0; ii < size; ii++)
299  {
300  size_t i = indices[ii];
301 
302  Value_type* ptr = new Value_type();
303 
304  std::string fname = (fmt % i).str();
305  load(*ptr, fname);
306 
307  *it++ = ptr;
308  }
309 }
310 
311 template <class Value_type, class SerializablePtrOutputIterator>
312 void load_many_dynamic_dispatch(typename boost::shared_ptr<Value_type> /* dummy */, SerializablePtrOutputIterator it, const std::string& fmt_str, const Index_range& indices )
313 {
314  BOOST_CONCEPT_ASSERT((SerializableConcept<Value_type>));
315 
316  boost::format fmt(fmt_str);
317  const size_t size = indices.size();
318  for(size_t ii = 0; ii < size; ii++)
319  {
320  size_t i = indices[ii];
321  boost::shared_ptr<Value_type> ptr(new Value_type());
322 
323  std::string fname = (fmt % i).str();
324  load(*ptr.get(), fname);
325 
326  *it++ = ptr;
327  }
328 }
329 
330 
331 template <class SerializablePtrOutputIterator>
332 void load_many_to_ptr(SerializablePtrOutputIterator it, const std::string& fmt_str, size_t num_files, size_t first_index = 0, size_t modulo = 1)
333 {
334  typedef typename std::iterator_traits<SerializablePtrOutputIterator>::value_type Ptr_type;
335 
336  Index_range indices(first_index,
337  first_index + num_files - 1,
338  modulo);
339 
340  load_many_dynamic_dispatch(*it, it, fmt_str, indices);
341 }
342 
351 template <class SerializablePtrOutputIterator, class Index_range_type>
352 typename boost::enable_if<boost::is_convertible<Index_range_type, Index_range>,void>::type
353 load_many_to_ptr(SerializablePtrOutputIterator it, const std::string& fmt_str, const Index_range_type& indices)
354 {
355  typedef typename std::iterator_traits<SerializablePtrOutputIterator>::value_type Ptr_type;
356 
357  load_many_dynamic_dispatch(*it, it, fmt_str, indices);
358 }
359 
360 //
361 //template <class Value_type, class SerializablePtrOutputIterator>
362 //void load_many_dynamic_dispatch(Value_type asdf, SerializablePtrOutputIterator it, const std::string& fmt_str, size_t num_files, size_t first_index)
363 //{
364 // // error
365 //}
366 
367 
378 template <class Serializable>
379 #ifdef KJB_HAVE_BST_SERIAL
380 void save(const Serializable& obj, const std::string& fname)
381 #else
382 void save(const Serializable&, const std::string&)
383 #endif
384 {
385 #ifdef KJB_HAVE_BST_SERIAL
386  // consider adding save(object, stream), also
387  BOOST_CONCEPT_ASSERT((SerializableConcept<Serializable>));
388 
389  std::ofstream ofs(fname.c_str());
390  if(ofs.fail())
391  {
392  KJB_THROW_3(IO_error, "Error opening %s.", (fname.c_str()));
393  }
394 
395  try
396  {
397  boost::archive::text_oarchive oa(ofs);
398  oa << obj;
399  }
400  catch(...)
401  {
402  KJB_THROW_3(IO_error, "Error serializing object to file %s. Probably a bug in the serialization routine.", (fname.c_str()));
403  }
404 #else
405  KJB_THROW_2(Missing_dependency, "boost::serialization");
406 #endif
407 }
408 
409 
410 
411 }
412 
413 #endif
void load_many_to_ptr(SerializablePtrOutputIterator it, const std::string &fmt_str, size_t num_files, size_t first_index=0, size_t modulo=1)
Definition: l_serialization.h:332
#define ETX(a)
Definition: l_exception.h:67
size_t size() const
Definition: l_index.h:273
#define KJB(x)
Definition: l_util.h:9
void kjb_serialize_default(Archive &ar, KJB_readable_writable &obj, const unsigned int)
Implements boost serialization for any object that implements the KjbReadableWritable concept...
Definition: l_serialization.h:117
void kjb_serialize(Archive &ar, KJB_readable_writable &obj, const unsigned int version)
Definition: l_serialization.h:170
BOOST_CONCEPT_USAGE(SerializableConcept)
Definition: l_serialization.h:84
void load(Edge_set &edges, const std::string &fname)
Definition: edge.h:603
void load_many(SerializableOutputIterator it, const std::string &fmt_str, const Index_range &indices)
Definition: l_serialization.h:249
#define KJB_THROW_2(ex, msg)
Definition: l_exception.h:48
void load_many_dynamic_dispatch(Value_type *, SerializablePtrOutputIterator it, const std::string &fmt_str, const Index_range &indices)
Definition: l_serialization.h:292
#define KJB_THROW_3(ex, fmt, params)
Definition: l_exception.h:56
Definition: l_index.h:65
void save(const Edge_set &edges, const std::string &fname)
Definition: edge.h:608
get the indices of edges in each direction for i
Definition: APPgetLargeConnectedEdges.m:48
Object thrown when input or output fails.
Definition: l_exception.h:496
Definition: l_serialization.h:82
Support for error handling exception classes in libKJB.
Object thrown when a program lacks required resources or libraries.
Definition: l_exception.h:539