tag.h

Back to Tags

pastel/sys/generic/

// Description: A compile-time tag parametrized by a string

#ifndef PASTELSYS_TAG_H
#define PASTELSYS_TAG_H

#include "pastel/sys/mytypes.h"

#include <type_traits>

#define PASTEL_TAG(name) Pastel::Tag<Pastel::tagHash(#name)>()

namespace Pastel
{

    using tag_integer = uint32;
    PASTEL_STATIC_ASSERT(std::is_unsigned<tag_integer>::value);

    template <tag_integer Hash>
    struct Tag {};

    //! Returns the hash for a tag-name.
    /*!
   Note that the N also contains the null-character at 
   the end of the string. That is, for "liquid",
   N = 6 + 1 = 7.
   */
    template <integer N>
    constexpr tag_integer tagHash(
        const char (&tagName)[N],
        // Skip the null-character at the end.
        integer i = N - 1)
    {
        // This is the Fowler-Noll-Vo 1a hash-function (FNV-1a) for 32-bit integers.
        return i > 0
            ? (tagHash(tagName, i - 1) ^ (tag_integer)tagName[i - 1]) * 16777619UL
            : 2166136261UL;
    }

    //! Returns the hash for a tag-name.
    /*!
   This should be named just tagHash(). However, a bug in Visual Studio 2015
   update 2 forces this function to have another name.
   */
    constexpr tag_integer tagHashString(
        const char* tagName,
        std::size_t n)
    {
        // This is the Fowler-Noll-Vo 1a hash-function (FNV-1a) for 32-bit integers.
        return n > 0
            ? (tagHashString(tagName, n - 1) ^ (tag_integer)tagName[n - 1]) * 16777619UL
            : 2166136261UL;
    }

    inline constexpr tag_integer operator "" _tag(const char* tagName, std::size_t n)
    {
        return tagHashString(tagName, n);
    }

}

#include "pastel/sys/generic/is_tag.h"
#include "pastel/sys/generic/tag_hash.h"

#endif