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 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
#ifndef GENERS_IOPTR_HH_
#define GENERS_IOPTR_HH_

#include "Alignment/Geners/interface/IOException.hh"
#include <string>

// "Silent" pointers for the I/O system
namespace gs {
  template <typename T>
  class IOProxy;

  template <typename T>
  class IOPtr {
    template <typename T2>
    friend class IOProxy;

  public:
    typedef T element_type;

    inline IOPtr() : ptr_(0) {}
    inline IOPtr(T *ptr) : ptr_(ptr) {}
    IOPtr(const IOProxy<T> &p);

    IOPtr &operator=(const IOProxy<T> &p);
    inline IOPtr &operator=(const IOPtr &p) {
      ptr_ = p.ptr_;
      return *this;
    }

    // Typical pointer operations
    inline T *get() const { return ptr_; }
    inline T *operator->() const {
      if (!ptr_)
        throw gs::IOInvalidArgument("In gs::IOPtr::operator->: attempt to dereference null pointer");
      return ptr_;
    }
    inline T &operator*() const {
      if (!ptr_)
        throw gs::IOInvalidArgument("In gs::IOPtr::operator*: attempt to dereference null pointer");
      return *ptr_;
    }
    inline IOPtr &operator++() {
      ++ptr_;
      return *this;
    }
    inline void operator++(int) { ++ptr_; }
    inline IOPtr &operator--() {
      --ptr_;
      return *this;
    }
    inline void operator--(int) { --ptr_; }

    // Implicit conversion to "bool"
    inline operator bool() const { return !(ptr_ == 0); }

    // Names are ignored during comparisons
    inline bool operator==(const IOPtr &r) const { return ptr_ == r.ptr_; }
    inline bool operator!=(const IOPtr &r) const { return ptr_ != r.ptr_; }
    bool operator==(const IOProxy<T> &r) const;
    bool operator!=(const IOProxy<T> &r) const;

    // Should be able to work as with bare pointer inside the I/O code
    inline T *&getIOReference() { return ptr_; }
    inline T *const &getIOReference() const {
      if (!ptr_)
        throw gs::IOInvalidArgument(
            "In gs::IOPtr::getIOReference: unusable "
            "const reference to null pointer");
      return ptr_;
    }

  private:
    T *ptr_;
  };

  template <typename T>
  class IOProxy {
    template <typename T2>
    friend class IOPtr;

  public:
    typedef T element_type;

    inline IOProxy() : ptr_(0) {}
    inline IOProxy(T *ptr) : ptr_(ptr) {}
    inline IOProxy(T *ptr, const char *varname) : ptr_(ptr), name_(varname ? varname : "") {}
    inline IOProxy(T *ptr, const std::string &varname) : ptr_(ptr), name_(varname) {}
    inline IOProxy(const IOPtr<T> &p) : ptr_(p.ptr_) {}
    inline IOProxy(const IOPtr<T> &p, const char *varname) : ptr_(p.ptr_), name_(varname ? varname : "") {}
    inline IOProxy(const IOPtr<T> &p, const std::string &varname) : ptr_(p.ptr_), name_(varname) {}

    inline IOProxy &operator=(const IOProxy &p) {
      ptr_ = p.ptr_;
      name_ = p.name_;
      return *this;
    }
    inline IOProxy &operator=(const IOPtr<T> &p) {
      ptr_ = p.ptr_;
      name_ = "";
      return *this;
    }

    // Get name
    inline const std::string &name() const { return name_; }

    // Set name
    inline IOProxy &setName(const char *varname) {
      name_ = varname ? varname : "";
      return *this;
    }
    inline IOProxy &setName(const std::string &varname) {
      name_ = varname;
      return *this;
    }

    // Typical pointer operations
    inline T *get() const { return ptr_; }
    inline T *operator->() const {
      if (!ptr_)
        throw gs::IOInvalidArgument("In gs::IOProxy::operator->: attempt to dereference null pointer");
      return ptr_;
    }
    inline T &operator*() const {
      if (!ptr_)
        throw gs::IOInvalidArgument("In gs::IOProxy::operator*: attempt to dereference null pointer");
      return *ptr_;
    }
    inline IOProxy &operator++() {
      ++ptr_;
      return *this;
    }
    inline void operator++(int) { ++ptr_; }
    inline IOProxy &operator--() {
      --ptr_;
      return *this;
    }
    inline void operator--(int) { --ptr_; }

    // Implicit conversion to "bool"
    inline operator bool() const { return !(ptr_ == 0); }

    // Names are ignored during comparisons
    inline bool operator==(const IOProxy &r) const { return ptr_ == r.ptr_; }
    inline bool operator!=(const IOProxy &r) const { return ptr_ != r.ptr_; }
    inline bool operator==(const IOPtr<T> &r) const { return ptr_ == r.ptr_; }
    inline bool operator!=(const IOPtr<T> &r) const { return ptr_ != r.ptr_; }

    // Should be able to work as with bare pointer inside the I/O code
    inline T *&getIOReference() { return ptr_; }
    inline T *const &getIOReference() const {
      if (!ptr_)
        throw gs::IOInvalidArgument(
            "In gs::IOProxy::getIOReference: unusable "
            "const reference to null pointer");
      return ptr_;
    }

  private:
    T *ptr_;
    std::string name_;
  };

  // Convenience function for making IOPtr objects
  template <typename T>
  inline IOPtr<T> make_IOPtr(T &obj) {
    return IOPtr<T>(&obj);
  }

  // In the user code, the following function can be usually wrapped
  // as follows:
  //
  // #define io_proxy(obj) gs::make_IOProxy( obj , #obj )
  //
  template <typename T>
  inline IOProxy<T> make_IOProxy(T &obj, const char *name) {
    return IOProxy<T>(&obj, name);
  }
}  // namespace gs

// IOPtr methods which could not be defined earlier
namespace gs {
  template <typename T>
  inline IOPtr<T>::IOPtr(const IOProxy<T> &p) : ptr_(p.ptr_) {}

  template <typename T>
  inline IOPtr<T> &IOPtr<T>::operator=(const IOProxy<T> &p) {
    ptr_ = p.ptr_;
    return *this;
  }

  template <typename T>
  inline bool IOPtr<T>::operator==(const IOProxy<T> &r) const {
    return ptr_ == r.ptr_;
  }

  template <typename T>
  inline bool IOPtr<T>::operator!=(const IOProxy<T> &r) const {
    return ptr_ != r.ptr_;
  }
}  // namespace gs

#endif  // GENERS_IOPTR_HH_