aboutsummaryrefslogtreecommitdiff
path: root/butl/utility
blob: 2436616f9dec3ada96bcb19a95967312a007aedc (plain)
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
// file      : butl/utility -*- C++ -*-
// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#ifndef BUTL_UTILITY
#define BUTL_UTILITY

#include <cstddef> // std::size_t
#include <utility> // forward()
#include <cstring> // strcmp

#include <butl/export>

namespace butl
{
  // Key comparators (i.e., to be used in sets, maps, etc).
  //
  struct LIBBUTL_EXPORT compare_c_string
  {
    bool operator() (const char* x, const char* y) const
    {
      return std::strcmp (x, y) < 0;
    }
  };

  struct LIBBUTL_EXPORT compare_pointer_target
  {
    template <typename P>
    bool operator() (const P& x, const P& y) const {return *x < *y;}
  };

  // Combine one or more hash values.
  //
  inline std::size_t
  combine_hash (std::size_t s, std::size_t h)
  {
    // Magic formula from boost::hash_combine().
    //
    return s ^ (h + 0x9e3779b9 + (s << 6) + (s >> 2));
  }

  template <typename... S>
  inline std::size_t
  combine_hash (std::size_t s, std::size_t h, S... hs)
  {
    return combine_hash (combine_hash (s, h), hs...);
  }

  // Support for reverse iteration using range-based for-loop:
  //
  // for (... : reverse_iterate (x)) ...
  //
  template <typename T>
  class reverse_range
  {
    T x_;

  public:
    reverse_range (T&& x): x_ (std::forward<T> (x)) {}

    auto begin () const -> decltype (this->x_.rbegin ()) {return x_.rbegin ();}
    auto end () const -> decltype (this->x_.rend ()) {return x_.rend ();}
  };

  template <typename T>
  inline reverse_range<T>
  reverse_iterate (T&& x) {return reverse_range<T> (std::forward<T> (x));}
}

#endif // BUTL_UTILITY