omni/graph/exec/unstable/ConstName.h

File members: omni/graph/exec/unstable/ConstName.h

// Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto. Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//

#pragma once

#include <carb/Defines.h>
#include <carb/cpp/StringView.h>

#include <omni/String.h>
#include <omni/graph/exec/unstable/Assert.h>
#include <omni/graph/exec/unstable/Types.h>

#include <type_traits>

namespace omni
{
namespace graph
{
namespace exec
{
namespace unstable
{

class ConstName
{
public:
    template <std::size_t N>
    explicit ConstName(const char (&s)[N]) : m_hash(carb::fnv1aHash(s, N - 1)), m_name(s, N - 1)
    {
        // N-1 so that we don't hash the terminating \0.
        OMNI_STATIC_ASSERT_MUST_BE_PASSED_BY_POINTER_IN_ABI(ConstName);
    }

    explicit ConstName(const carb::cpp::string_view& sv) : m_hash(carb::fnv1aHash(sv.data(), sv.size())), m_name(sv)
    {
    }

    explicit ConstName(const carb::cpp::string_view& sv, NameHash hash) : m_hash(hash), m_name(sv)
    {
    }

    ConstName() noexcept : m_hash(CARB_HASH_STRING(""))
    {
    }

    // LCOV_EXCL_START
    struct BogusArg
    {
    };
    // LCOV_EXCL_STOP

    template <typename T>
    explicit ConstName(const T& s, std::enable_if_t<std::is_same<std::string, T>::value, BogusArg> = {})
        : m_hash(carb::fnv1aHash(s.data(), s.size())), m_name(s)
    {
        // the enable_if disambiguates which constructor a const char* arg should use.
        // the BogusArg type keeps this constructor from being confused with the one with a hash.
    }

    template <typename T>
    explicit ConstName(const T& s, NameHash hash, std::enable_if_t<std::is_same<std::string, T>::value, BogusArg> = {})
        : m_hash(hash), m_name(s)
    {
        // the enable_if disambiguates which constructor a const char* arg should use.
    }

    const omni::string& getString() const noexcept
    {
        return m_name;
    }

    constexpr uint64_t getHash() const noexcept
    {
        return m_hash;
    }

    std::string toString() const noexcept
    {
        return std::string(m_name.data(), m_name.size()); // may throw
    }

    const char* c_str() const noexcept
    {
        return m_name.c_str();
    }

    operator carb::cpp::string_view() const noexcept
    {
        return carb::cpp::string_view(m_name.data(), m_name.size());
    }

private:
    uint64_t m_hash;
    omni::string m_name;
};

constexpr bool operator==(const ConstName& lhs, const ConstName& rhs) noexcept
{
    return (lhs.getHash() == rhs.getHash());
}

constexpr bool operator==(const ConstName& lhs, NameHash rhs) noexcept
{
    return (lhs.getHash() == rhs);
}

constexpr bool operator==(NameHash lhs, const ConstName& rhs) noexcept
{
    return (lhs == rhs.getHash());
}

constexpr bool operator!=(const ConstName& lhs, const ConstName& rhs) noexcept
{
    return (lhs.getHash() != rhs.getHash());
}

constexpr bool operator!=(const ConstName& lhs, NameHash rhs) noexcept
{
    return (lhs.getHash() != rhs);
}

constexpr bool operator!=(NameHash lhs, const ConstName& rhs) noexcept
{
    return (lhs != rhs.getHash());
}

constexpr bool operator<(const ConstName& lhs, const ConstName& rhs) noexcept
{
    return (lhs.getHash() < rhs.getHash());
}

constexpr bool operator<(const ConstName& lhs, NameHash rhs) noexcept
{
    return (lhs.getHash() < rhs);
}

constexpr bool operator<(NameHash lhs, const ConstName& rhs) noexcept
{
    return (lhs < rhs.getHash());
}

inline std::ostream& operator<<(std::ostream& os, const ConstName& str)
{
    return (os << str.getString());
}

inline auto operator+(const std::string& lhs, const ConstName& rhs)
{
    return lhs + rhs.getString();
}

inline auto operator+(const ConstName& lhs, const std::string& rhs)
{
    return lhs.getString() + rhs;
}

} // namespace unstable
} // namespace exec
} // namespace graph
} // namespace omni

namespace std
{

template <>
struct hash<omni::graph::exec::unstable::ConstName>
{
    using argument_type = omni::graph::exec::unstable::ConstName;

    using result_type = std::size_t;

    result_type operator()(const argument_type& x) const noexcept
    {
        return x.getHash();
    }
};

} // namespace std