Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 11:56:18

0001 //=========================================================================
0002 // binaryIO.hh
0003 //
0004 // "Low-level" utility API for reading/writing data in a binary form
0005 // (this particular form is not platform independent). All "geners" I/O
0006 // should be performed through one of the functions defined in this file,
0007 // there should be no direct user manipulation of C++ streams. In this
0008 // way possible future I/O modifications will be isolated and restricted
0009 // to this facility.
0010 //
0011 // I. Volobouev
0012 // April 2009
0013 //=========================================================================
0014 
0015 #ifndef GENERS_BINARYIO_HH_
0016 #define GENERS_BINARYIO_HH_
0017 
0018 #include <memory>
0019 #include "Alignment/Geners/interface/ClassId.hh"
0020 #include "Alignment/Geners/interface/IOException.hh"
0021 
0022 #include <cassert>
0023 #include <iostream>
0024 #include <memory>
0025 #include <vector>
0026 
0027 namespace gs {
0028   // The following functions perform binary I/O of built-in types.
0029   // Note that all of them are "void". It is assumed that the
0030   // top-level code will check the status of the stream after
0031   // several I/O operations.
0032   template <typename T>
0033   inline void write_pod(std::ostream &of, const T &pod) {
0034     of.write(reinterpret_cast<const char *>(&pod), sizeof(T));
0035   }
0036 
0037   template <typename T>
0038   inline void read_pod(std::istream &in, T *pod) {
0039     assert(pod);
0040     in.read(reinterpret_cast<char *>(pod), sizeof(T));
0041   }
0042 
0043   template <typename T>
0044   inline void write_pod_array(std::ostream &of, const T *pod, const unsigned long len) {
0045     if (len) {
0046       assert(pod);
0047       of.write(reinterpret_cast<const char *>(pod), len * sizeof(T));
0048     }
0049   }
0050 
0051   template <typename T>
0052   inline void read_pod_array(std::istream &in, T *pod, const unsigned long len) {
0053     if (len) {
0054       assert(pod);
0055       in.read(reinterpret_cast<char *>(pod), len * sizeof(T));
0056     }
0057   }
0058 
0059   // String is treated as a pod vector. This will be guaranteed
0060   // to work correctly in the C++11 standard (the current standard
0061   // does not specify that the characters must be stored contuguously
0062   // inside the string -- however, this is always true in practice).
0063   template <typename T>
0064   inline void write_string(std::ostream &of, const std::basic_string<T> &v) {
0065     const unsigned long sz = v.size();
0066     write_pod(of, sz);
0067     if (sz)
0068       write_pod_array(of, v.data(), sz);
0069   }
0070 
0071   template <typename T>
0072   inline void read_string(std::istream &in, std::basic_string<T> *pv) {
0073     assert(pv);
0074     unsigned long vlen = 0UL;
0075     read_pod(in, &vlen);
0076     if (vlen) {
0077       pv->resize(vlen);
0078       read_pod_array(in, const_cast<T *>(pv->data()), vlen);
0079     } else
0080       pv->clear();
0081   }
0082 
0083   // Specialization of POD-based I/O functions so that they work
0084   // as if std::string is a POD
0085   template <>
0086   inline void write_pod<std::string>(std::ostream &of, const std::string &s) {
0087     write_string<char>(of, s);
0088   }
0089 
0090   template <>
0091   inline void read_pod<std::string>(std::istream &in, std::string *ps) {
0092     read_string<char>(in, ps);
0093   }
0094 
0095   template <>
0096   inline void write_pod_array<std::string>(std::ostream &of, const std::string *pod, const unsigned long len) {
0097     if (len) {
0098       assert(pod);
0099       for (unsigned long i = 0; i < len; ++i)
0100         write_string<char>(of, pod[i]);
0101     }
0102   }
0103 
0104   template <>
0105   inline void read_pod_array<std::string>(std::istream &in, std::string *pod, const unsigned long len) {
0106     if (len) {
0107       assert(pod);
0108       for (unsigned long i = 0; i < len; ++i)
0109         read_string<char>(in, pod + i);
0110     }
0111   }
0112 
0113   template <typename T>
0114   inline void write_pod_vector(std::ostream &of, const std::vector<T> &v) {
0115     const unsigned long sz = v.size();
0116     write_pod(of, sz);
0117     if (sz)
0118       write_pod_array(of, &v[0], sz);
0119   }
0120 
0121   template <typename T>
0122   inline void read_pod_vector(std::istream &in, std::vector<T> *pv) {
0123     assert(pv);
0124     unsigned long vlen = 0UL;
0125     read_pod(in, &vlen);
0126     if (in.fail())
0127       throw IOReadFailure("In gs::read_pod_vector: input stream failure");
0128     if (vlen) {
0129       pv->resize(vlen);
0130       read_pod_array(in, &((*pv)[0]), vlen);
0131     } else
0132       pv->clear();
0133   }
0134 
0135   // The following functions perform binary I/O on objects
0136   // which have write/read/restore functions. Compared to
0137   // calling the corresponding class methods directly, these
0138   // function take care of writing out the class identifier.
0139   //
0140   template <typename T>
0141   inline bool write_obj(std::ostream &of, const T &obj) {
0142     return obj.classId().write(of) && obj.write(of);
0143   }
0144 
0145   template <typename T>
0146   inline std::unique_ptr<T> read_obj(std::istream &in) {
0147     const ClassId id(in, 1);
0148     return std::unique_ptr<T>(T::read(id, in));
0149   }
0150 
0151   template <typename T>
0152   inline void restore_obj(std::istream &in, T *obj) {
0153     assert(obj);
0154     const ClassId id(in, 1);
0155     T::restore(id, in, obj);
0156   }
0157 
0158   // The following function is templated upon the reader factory
0159   template <typename Reader>
0160   inline std::unique_ptr<typename Reader::value_type> read_base_obj(std::istream &in, const Reader &f) {
0161     typedef typename Reader::value_type T;
0162     const ClassId id(in, 1);
0163     return std::unique_ptr<T>(f.read(id, in));
0164   }
0165 
0166   // The following function assumes that the array contains actual
0167   // objects rather than pointers
0168   template <typename T>
0169   inline bool write_obj_array(std::ostream &of, const T *arr, const unsigned long len) {
0170     bool status = true;
0171     if (len) {
0172       assert(arr);
0173       status = arr[0].classId().write(of);
0174       for (unsigned long i = 0; i < len && status; ++i)
0175         status = arr[i].write(of);
0176     }
0177     return status;
0178   }
0179 
0180   // The following assumes that the array contains actual objects
0181   // and that class T has the "restore" function
0182   template <typename T>
0183   inline void read_placed_obj_array(std::istream &in, T *arr, const unsigned long len) {
0184     if (len) {
0185       assert(arr);
0186       const ClassId id(in, 1);
0187       for (unsigned long i = 0; i < len; ++i)
0188         T::restore(id, in, arr + i);
0189     }
0190   }
0191 
0192   // The following assumes that the array contains a bunch of
0193   // shared pointers and that class T has the "read" function
0194   template <typename T>
0195   inline void read_heap_obj_array(std::istream &in, std::shared_ptr<T> *arr, const unsigned long len) {
0196     if (len) {
0197       assert(arr);
0198       const ClassId id(in, 1);
0199       for (unsigned long i = 0; i < len; ++i) {
0200         T *obj = T::read(id, in);
0201         arr[i] = std::shared_ptr<T>(obj);
0202       }
0203     }
0204   }
0205 
0206   // The following function is templated upon the reader factory
0207   template <typename Reader>
0208   inline void read_base_obj_array(std::istream &in,
0209                                   const Reader &f,
0210                                   std::shared_ptr<typename Reader::value_type> *arr,
0211                                   const unsigned long len) {
0212     typedef typename Reader::value_type T;
0213     if (len) {
0214       assert(arr);
0215       const ClassId id(in, 1);
0216       for (unsigned long i = 0; i < len; ++i) {
0217         T *obj = f.read(id, in);
0218         arr[i] = std::shared_ptr<T>(obj);
0219       }
0220     }
0221   }
0222 
0223   // The following assumes that the vector contains actual objects
0224   template <typename T>
0225   inline bool write_obj_vector(std::ostream &of, const std::vector<T> &v) {
0226     const unsigned long sz = v.size();
0227     write_pod(of, sz);
0228     bool status = !of.fail();
0229     if (sz && status)
0230       status = write_obj_array(of, &v[0], sz);
0231     return status;
0232   }
0233 
0234   // The following assumes that the vector contains actual objects
0235   template <typename T>
0236   inline void read_placed_obj_vector(std::istream &in, std::vector<T> *pv) {
0237     unsigned long vlen = 0UL;
0238     read_pod(in, &vlen);
0239     if (in.fail())
0240       throw IOReadFailure("In gs::read_placed_obj_vector: input stream failure");
0241     assert(pv);
0242     if (vlen) {
0243       pv->resize(vlen);
0244       read_placed_obj_array(in, &(*pv)[0], vlen);
0245     } else
0246       pv->clear();
0247   }
0248 
0249   // The following assumes that the vector contains a bunch of
0250   // shared pointers
0251   template <typename T>
0252   inline void read_heap_obj_vector(std::istream &in, std::vector<std::shared_ptr<T>> *pv) {
0253     unsigned long vlen = 0UL;
0254     read_pod(in, &vlen);
0255     if (in.fail())
0256       throw IOReadFailure("In gs::read_heap_obj_vector: input stream failure");
0257     assert(pv);
0258     if (vlen) {
0259       pv->resize(vlen);
0260       return read_heap_obj_array(in, &(*pv)[0], vlen);
0261     } else
0262       pv->clear();
0263   }
0264 
0265   // The following assumes that the vector contains actual objects.
0266   // This function is less efficient than others, but it has to be
0267   // used sometimes if one wants to have a vector of objects without
0268   // default constructors.
0269   //
0270   template <typename T>
0271   inline void read_heap_obj_vector_as_placed(std::istream &in, std::vector<T> *pv) {
0272     unsigned long vlen = 0UL;
0273     read_pod(in, &vlen);
0274     if (in.fail())
0275       throw IOReadFailure("In gs::read_heap_obj_vector_as_placed: input stream failure");
0276     assert(pv);
0277     pv->clear();
0278     if (vlen) {
0279       const ClassId id(in, 1);
0280       pv->reserve(vlen);
0281       for (unsigned long i = 0; i < vlen; ++i) {
0282         std::unique_ptr<T> obj(T::read(id, in));
0283         pv->push_back(*obj);
0284       }
0285     }
0286   }
0287 
0288   // The following function is templated upon the reader factory
0289   template <typename Reader>
0290   inline void read_base_obj_vector(std::istream &in,
0291                                    const Reader &f,
0292                                    std::vector<std::shared_ptr<typename Reader::value_type>> *pv) {
0293     unsigned long vlen = 0UL;
0294     read_pod(in, &vlen);
0295     if (in.fail())
0296       throw IOReadFailure("In gs::read_base_obj_vector: input stream failure");
0297     assert(pv);
0298     if (vlen) {
0299       pv->resize(vlen);
0300       read_base_obj_array(in, f, &(*pv)[0], vlen);
0301     } else
0302       pv->clear();
0303   }
0304 }  // namespace gs
0305 
0306 #endif  // GENERS_BINARYIO_HH_