Program Listing for File unique-id.h

Return to documentation for file (aslam_cv2/aslam_cv_common/include/aslam/common/unique-id.h)

#ifndef ASLAM_COMMON_UNIQUE_ID_H_
#define ASLAM_COMMON_UNIQUE_ID_H_

#include <sstream>
#include <string>
#include <unordered_set>
#include <vector>

#include <glog/logging.h>

#include <aslam/common/hash-id.h>
#include <aslam/common/internal/unique-id.h>

static constexpr unsigned kDefaultIDPrintLength = 10;

namespace aslam {
template <typename IdType>
class UniqueId;
}

#define UNIQUE_ID_DEFINE_ID(TypeName)                           \
  class TypeName : public aslam::UniqueId<TypeName> {          \
   public: /* NOLINT */                                         \
    TypeName() = default;                                       \
    explicit inline TypeName(const aslam::proto::Id& id_field) \
        : aslam::UniqueId<TypeName>(id_field) {}               \
  };                                                            \
  typedef std::vector<TypeName> TypeName##List;                 \
  typedef std::unordered_set<TypeName> TypeName##Set;           \
  extern void defineId##__FILE__##__LINE__(void)

#define UNIQUE_ID_DEFINE_IMMUTABLE_ID(TypeName, BaseTypeName)         \
  class TypeName : public aslam::UniqueId<TypeName> {                \
   public: /* NOLINT */                                               \
    TypeName() = default;                                             \
    explicit inline TypeName(const aslam::proto::Id& id_field)       \
        : aslam::UniqueId<TypeName>(id_field) {}                     \
    inline void from##BaseTypeName(const BaseTypeName& landmark_id) { \
      aslam::HashId hash_id;                                          \
      landmark_id.toHashId(&hash_id);                                 \
      this->fromHashId(hash_id);                                      \
    }                                                                 \
  };                                                                  \
  typedef std::vector<TypeName> TypeName##List;                       \
  typedef std::unordered_set<TypeName> TypeName##Set;                 \
  extern void defineId##__FILE__##__LINE__(void)

// This macro needs to be called outside of any namespace.
#define UNIQUE_ID_DEFINE_ID_HASH(TypeName)                                   \
  namespace std {                                                            \
  template <>                                                                \
  struct hash<TypeName> {                                                    \
    typedef TypeName argument_type;                                          \
    typedef std::size_t value_type;                                          \
    value_type operator()(const argument_type& hash_id) const {              \
      return hash_id.hashToSizeT();                                          \
    }                                                                        \
  };                                                                         \
                                                                             \
  template <>                                                                \
  struct hash<std::pair<TypeName, TypeName>> {                               \
    typedef TypeName argument_type;                                          \
    typedef std::size_t value_type;                                          \
    value_type operator()(                                                   \
        const std::pair<argument_type, argument_type>& hash_id_pair) const { \
      return hash_id_pair.first.hashToSizeT() ^                              \
             hash_id_pair.second.hashToSizeT();                              \
    }                                                                        \
  };                                                                         \
  }                                                                          \
  extern void defineId##__FILE__##__LINE__(void)

#define ALIAS_UNIQUE_ID(BaseIdType, AliasedIdType)  \
  typedef BaseIdType AliasedIdType;                       \
  typedef BaseIdType##List AliasedIdType##List;           \
  typedef BaseIdType##Set AliasedIdType##Set

template <typename ContainerType>
inline std::string printIdContainer(const ContainerType& container) {
  std::stringstream ss;
  ss << "[ ";
  for (const typename ContainerType::value_type& element : container) {
    ss << element << " ";
  }
  ss << "]";
  return ss.str();
}

namespace aslam {
template <typename IdType>
void generateId(IdType* id) {
  CHECK_NOTNULL(id);
  uint64_t hash[2];
  internal::generateUnique128BitHash(hash);
  id->fromUint64(hash);
}

template <typename IdType>
IdType createRandomId() {
  IdType id;
  generateId(&id);
  return id;
}

template <typename IdType>
void generateIdFromInt(unsigned int idx, IdType* id) {
  CHECK_NOTNULL(id);
  std::stringstream ss;
  ss << std::setfill('0') << std::setw(32) << idx;
  id->fromHexString(ss.str());
}

// For internal use only.
class Id : public HashId {
 public:
  Id() = default;
  explicit inline Id(const aslam::proto::Id& id_field) {
    deserialize(id_field);
  }
  inline void deserialize(const aslam::proto::Id& id_field) {
    CHECK_EQ(id_field.uint_size(), 2);
    fromUint64(id_field.uint().data());
  }
  inline void serialize(aslam::proto::Id* id_field) const {
    CHECK_NOTNULL(id_field)->clear_uint();

    google::protobuf::RepeatedField<google::protobuf::uint64>* uint_field =
        id_field->mutable_uint();
    uint_field->Add();
    uint_field->Add();
    toUint64(uint_field->mutable_data());
  }

  inline void fromHashId(const aslam::HashId& id) {
    static_cast<aslam::HashId&>(*this) = id;
  }
  inline void toHashId(aslam::HashId* id) const {
    CHECK_NOTNULL(id);
    *id = static_cast<const aslam::HashId&>(*this);
  }

  std::string printString() const {
    constexpr int kPartLength = (kDefaultIDPrintLength - 2) / 2;
    const std::string hex = hexString();
    return hex.substr(0, kPartLength) + ".." +
           hex.substr(hex.length() - kPartLength, kPartLength);
  }

  template <typename IdType>
  inline IdType toIdType() const {
    IdType value;
    value.fromHashId(*this);
    return value;
  }

  template <typename GenerateIdType>
  friend void generateId(GenerateIdType* id);

  bool correspondsTo(const aslam::proto::Id& proto_id) const {
    Id corresponding(proto_id);
    return operator==(corresponding);
  }

 private:
  using aslam::HashId::fromUint64;
  using aslam::HashId::toUint64;
};

typedef std::unordered_set<Id> IdSet;
typedef std::vector<Id> IdList;

// To be used for general IDs.
template <typename IdType>
class UniqueId : private Id {
 public:
  UniqueId() = default;
  explicit inline UniqueId(const aslam::proto::Id& id_field) : Id(id_field) {}

  using aslam::HashId::hexString;
  using aslam::HashId::fromHexString;
  using aslam::HashId::hashToSizeT;
  using aslam::HashId::isValid;
  using aslam::HashId::setInvalid;
  using aslam::HashId::shortHex;

  using Id::deserialize;
  using Id::printString;
  using Id::serialize;
  using Id::toIdType;

  std::ostream& operator<<(std::ostream& os) const {
    return os << printString();
  }

  inline void fromHashId(const aslam::HashId& id) {
    static_cast<aslam::HashId&>(*this) = id;
  }

  inline void toHashId(aslam::HashId* id) const {
    CHECK_NOTNULL(id);
    *id = static_cast<const aslam::HashId&>(*this);
  }

  inline bool operator==(const IdType& other) const {
    return aslam::HashId::operator==(other);
  }

  inline bool operator==(const Id& other) const {
    return aslam::HashId::operator==(other);
  }

  inline bool operator!=(const IdType& other) const {
    return aslam::HashId::operator!=(other);
  }

  inline bool operator!=(const Id& other) const {
    return aslam::HashId::operator!=(other);
  }

  inline bool operator<(const IdType& other) const {
    return aslam::HashId::operator<(other);
  }

  inline bool operator<(const Id& other) const {
    return aslam::HashId::operator<(other);
  }

  template <typename GenerateIdType>
  friend void generateId(GenerateIdType* id);
};

UNIQUE_ID_DEFINE_ID(FrameId);
UNIQUE_ID_DEFINE_ID(NFramesId);
UNIQUE_ID_DEFINE_ID(SensorId);

// Maintain compatibility with old naming scheme.
ALIAS_UNIQUE_ID(SensorId, CameraId);
ALIAS_UNIQUE_ID(SensorId, NCameraId);

}  // namespace aslam

namespace std {
inline ostream& operator<<(ostream& out, const aslam::Id& hash) {
  out << hash.printString();
  return out;
}

template <typename IdType>
inline ostream& operator<<(ostream& out, const aslam::UniqueId<IdType>& hash) {
  out << hash.printString();
  return out;
}

template <>
struct hash<aslam::Id> {
  std::size_t operator()(const aslam::Id& hashId) const {
    return std::hash<std::string>()(hashId.hexString());
  }
};
}  // namespace std

UNIQUE_ID_DEFINE_ID_HASH(aslam::FrameId);
UNIQUE_ID_DEFINE_ID_HASH(aslam::NFramesId);
UNIQUE_ID_DEFINE_ID_HASH(aslam::SensorId);

#endif  // ASLAM_COMMON_UNIQUE_ID_H_