<commit_before>#ifndef PINBA__REPORT_UTIL_H_
#define PINBA__REPORT_UTIL_H_

#include <string>
#include <vector>
#include <utility>

#include <sparsehash/dense_hash_map>
#include <sparsehash/sparse_hash_map>

#include <meow/intrusive_ptr.hpp>
#include <meow/hash/hash.hpp>
#include <meow/hash/hash_impl.hpp>
#include <meow/format/format_to_string.hpp>

#include "pinba/globals.h"
#include "pinba/dictionary.h"
#include "pinba/report_key.h"

#include "t1ha/t1ha.h"

////////////////////////////////////////////////////////////////////////////////////////////////

struct report_key__hasher_t
{
	template<size_t N>
	inline constexpr size_t operator()(report_key_base_t<N> const& key) const
	{
		// TODO: try a "better" hash function here, like https://github.com/leo-yuriev/t1ha
		// return meow::hash_blob(key.data(), key.size() * sizeof(typename report_key_base_t<N>::value_type));
		// return t1ha1_le(key.data(), key.size() * sizeof(typename report_key_base_t<N>::value_type), (uint64_t)this /*seed*/ );
		return t1ha0(key.data(), key.size() * sizeof(typename report_key_base_t<N>::value_type), (uint64_t)this /*seed*/ );
	}
};

// suitable for comaring any report keys (i.e. diff length)
struct report_key__equal_generic_t
{
	template<size_t N>
	inline bool operator()(report_key_base_t<N> const& l, report_key_base_t<N> const& r) const
	{
		return (l.size() == r.size())
				? (0 == memcmp(l.data(), r.data(), (l.size() * sizeof(typename report_key_base_t<N>::value_type)) ))
				: false
				;
	}
};

// report keys must have same length
struct report_key__equal_t
{
	template<size_t N>
	inline bool operator()(report_key_base_t<N> const& l, report_key_base_t<N> const& r) const
	{
		return (0 == memcmp(l.data(), r.data(), (l.size() * sizeof(typename report_key_base_t<N>::value_type)) ));
	}
};

template<size_t N>
std::string report_key_to_string(report_key_base_t<N> const& k)
{
	std::string result;

	for (size_t i = 0; i < k.size(); ++i)
	{
		ff::write(result, (i == 0) ? "" : "|", k[i]);
	}

	return result;
}

template<size_t N>
std::string report_key_to_string(report_key_base_t<N> const& k, dictionary_t const *dict)
{
	std::string result;<commit_msg>fixed hashtable compare, doesn't work with empty key properly<commit_after>#ifndef PINBA__REPORT_UTIL_H_
#define PINBA__REPORT_UTIL_H_

#include <string>
#include <vector>
#include <utility>

#include <sparsehash/dense_hash_map>
#include <sparsehash/sparse_hash_map>

#include <meow/intrusive_ptr.hpp>
#include <meow/hash/hash.hpp>
#include <meow/hash/hash_impl.hpp>
#include <meow/format/format_to_string.hpp>

#include "pinba/globals.h"
#include "pinba/dictionary.h"
#include "pinba/report_key.h"

#include "t1ha/t1ha.h"

////////////////////////////////////////////////////////////////////////////////////////////////

struct report_key__hasher_t
{
	template<size_t N>
	inline constexpr size_t operator()(report_key_base_t<N> const& key) const
	{
		// TODO: try a "better" hash function here, like https://github.com/leo-yuriev/t1ha
		// return meow::hash_blob(key.data(), key.size() * sizeof(typename report_key_base_t<N>::value_type));
		// return t1ha1_le(key.data(), key.size() * sizeof(typename report_key_base_t<N>::value_type), (uint64_t)this /*seed*/ );
		return t1ha0(key.data(), key.size() * sizeof(typename report_key_base_t<N>::value_type), (uint64_t)this /*seed*/ );
	}
};

struct report_key__equal_t
{
	template<size_t N>
	inline bool operator()(report_key_base_t<N> const& l, report_key_base_t<N> const& r) const
	{
		return (l.size() == r.size())
				? (0 == memcmp(l.data(), r.data(), (l.size() * sizeof(typename report_key_base_t<N>::value_type)) ))
				: false
				;
	}
};

template<size_t N>
std::string report_key_to_string(report_key_base_t<N> const& k)
{
	std::string result;

	for (size_t i = 0; i < k.size(); ++i)
	{
		ff::write(result, (i == 0) ? "" : "|", k[i]);
	}

	return result;
}

template<size_t N>
std::string report_key_to_string(report_key_base_t<N> const& k, dictionary_t const *dict)
{
	std::string result;
{'fraction_non_alphanumeric': 0.20269259536275244, 'fraction_numerical': 0.007230117177761157, 'mean_word_length': 4.1634491634491635, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 51, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5660705', 'n_tokens_mistral': 1589, 'n_tokens_neox': 1532, 'n_words': 290}