Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
//=========================================================================
// CatalogIO.hh
//
// The following functions provide an operational definition of
// the "standard" binary catalog file format
//
// I. Volobouev
// November 2010
//=========================================================================

#ifndef GENERS_CATALOGIO_HH_
#define GENERS_CATALOGIO_HH_

#include <iostream>

#include "Alignment/Geners/interface/AbsCatalog.hh"

namespace gs {
  struct CatalogFormat1 {
    enum { ID = 713265489 };
  };

  // In the following, it is assumed that the catalog is stored
  // in memory and that it has a stream dedicated to it. The
  // function returns "true" on success.
  //
  // Programs which make new catalogs should set "mergeLevel" to 1.
  // Programs which combine existing catalogs should add up the
  // merge levels of those catalogs to come up with the "mergeLevel".
  //
  // "annotations" are arbitrary strings (which should be just combined
  // when catalogs are merged).
  bool writeBinaryCatalog(std::ostream &os,
                          unsigned compressionCode,
                          unsigned mergeLevel,
                          const std::vector<std::string> &annotations,
                          const AbsCatalog &catalog,
                          unsigned formatId = CatalogFormat1::ID);

  // In the following, it is assumed that the Catalog class
  // has a "read" function which builds the catalog on the heap.
  // The "allowReadingByDifferentClass" parameter specifies
  // whether the catalog class is allowed to read something
  // written by another catalog class. This function returns NULL
  // pointer on failure. Note that the user must call "delete"
  // on the returned pointer at some point in the future.
  template <class Catalog>
  Catalog *readBinaryCatalog(std::istream &is,
                             unsigned *compressionCode,
                             unsigned *mergeLevel,
                             std::vector<std::string> *annotations,
                             bool allowReadingByDifferentClass,
                             unsigned formatId = CatalogFormat1::ID);
}  // namespace gs

#include <cassert>
#include <sstream>

#include "Alignment/Geners/interface/IOException.hh"
#include "Alignment/Geners/interface/binaryIO.hh"

namespace gs {
  template <class Catalog>
  Catalog *readBinaryCatalog(std::istream &is,
                             unsigned *compressionCode,
                             unsigned *mergeLevel,
                             std::vector<std::string> *annotations,
                             const bool allowReadingByDifferentClass,
                             const unsigned expectedformatId) {
    assert(compressionCode);
    assert(mergeLevel);
    assert(annotations);

    is.seekg(0, std::ios_base::beg);

    unsigned formatId = 0, endianness = 0;
    unsigned char sizelong = 0;
    read_pod(is, &formatId);
    read_pod(is, &endianness);
    read_pod(is, &sizelong);

    if (is.fail())
      throw IOReadFailure("In gs::readBinaryCatalog: input stream failure");

    if (endianness != 0x01020304 || formatId != expectedformatId || sizelong != sizeof(long))
      throw IOInvalidData(
          "In gs::readBinaryCatalog: not \"geners\" "
          "binary metafile or incompatible system "
          "architecture");

    read_pod(is, compressionCode);
    read_pod(is, mergeLevel);
    read_pod_vector(is, annotations);
    ClassId id(is, 1);
    Catalog *readback = nullptr;

    ClassId catId(ClassId::makeId<Catalog>());
    if (id.name() == catId.name())
      // The reading is done by the same class as the writing.
      // Make sure the "read" function gets the correct class version.
      readback = Catalog::read(id, is);
    else {
      if (!allowReadingByDifferentClass) {
        std::ostringstream os;
        os << "In gs::readBinarCatalog: incompatible "
           << "catalog class: written by \"" << id.name() << "\", but reading is attempted by \"" << catId.name()
           << '"';
        throw IOInvalidData(os.str());
      }

      // The reading is not done by the same class as the writing.
      // All bets are off, and it is up to the user to decide whether
      // this makes sense. However, to maintain compatibility with
      // version 1 archives, we need to pass this version to the
      // catalog read function.
      if (id.version() == 1)
        catId.setVersion(1);

      readback = Catalog::read(catId, is);
    }

    // Catalogs do not necessarily know their size in advance,
    // so that they might read until the end of file is encountered.
    // However, the eof flag on the stream can result in various
    // problems later (for example, in writing to the stream).
    // Remove this flag.
    if (is.eof() && !is.fail() && !is.bad()) {
      is.clear();
      is.seekg(0, std::ios_base::end);
    }

    return readback;
  }
}  // namespace gs

#endif  // GENERS_CATALOGIO_HH_