aboutsummaryrefslogtreecommitdiff
path: root/build2/utility
blob: 187834ef81d33f8f68652291070bf74e710d8df9 (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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// file      : build2/utility -*- C++ -*-
// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#ifndef BUILD2_UTILITY
#define BUILD2_UTILITY

#include <memory>   // make_shared()
#include <string>   // to_string()
#include <utility>  // move(), forward(), declval(), make_pair()
#include <cassert>  // assert()
#include <iterator> // make_move_iterator()

#include <butl/utility> // reverse_iterate()

#include <exception>     // uncaught_exception()
#include <unordered_set>

#include <build2/types>

namespace build2
{
  using std::move;
  using std::forward;
  using std::declval;

  using std::make_pair;
  using std::make_shared;
  using std::make_move_iterator;
  using std::to_string;

  // <butl/utility>
  //
  using butl::reverse_iterate;

  // Empty string and path.
  //
  extern const std::string empty_string;
  extern const path empty_path;
  extern const dir_path empty_dir_path;

  // Append all the values from a variable to the C-string list. T is either
  // target or scope. The variable is expected to be of type strings.
  //
  template <typename T>
  void
  append_options (cstrings&, T&, const char* variable);

  template <typename T>
  void
  hash_options (sha256&, T&, const char* variable);

  // As above but from the strings value directly.
  //
  class value;
  template <typename> struct lookup;
  template <typename, typename> struct vector_value;
  using const_strings_value = vector_value<string, const names>;

  void
  append_options (cstrings&, const lookup<const value>&);

  void
  hash_options (sha256&, const lookup<const value>&);

  void
  append_options (cstrings&, const const_strings_value&);

  void
  hash_options (sha256&, const const_strings_value&);

  // Check if a specified option is present in the variable value.
  // T is either target or scope.
  //
  template <typename T>
  bool
  find_option (const char* option, T&, const char* variable);

  bool
  find_option (const char* option, const lookup<const value>&);

  // Parse version string in the X.Y.Z[-{a|b}N] to a version integer in the
  // AABBCCDD form, where:
  //
  // AA - major version number
  // BB - minor version number
  // CC - bugfix version number
  // DD - alpha / beta (DD + 50) version number
  //
  // When DD is not 00, 1 is subtracted from AABBCC. For example:
  //
  // Version     AABBCCDD
  // 2.0.0       02000000
  // 2.1.0       02010000
  // 2.1.1       02010100
  // 2.2.0-a1    02019901
  // 3.0.0-b2    02999952
  //
  // For a version in the 1.2.3- form, it returns (AABBCC-1)01, which is the
  // lowest possible version in the 1.2.3 release set. For example:
  //
  // Version     AABBCCDD
  // 2.2.0-      02019901
  // 1.2.3-      01020201
  //
  // In fact versions 1.2.3- and 1.2.3-a1 are equivalent.
  //
  // Throw invalid_argument if the passed string is not a valid version.
  //
  unsigned int
  to_version (const string&);

  // Call a function if there is an exception.
  //

  // Means we are in the body of a destructor that is being called
  // as part of the exception stack unwindining. Used to compensate
  // for the deficiencies of uncaught_exception() until C++17
  // uncaught_exceptions() becomes available.
  //
  // @@ MT: will have to be TLS.
  //
  extern bool exception_unwinding_dtor;

  template <typename F>
  struct exception_guard;

  template <typename F>
  inline exception_guard<F>
  make_exception_guard (F f)
  {
    return exception_guard<F> (move (f));
  }

  template <typename F>
  struct exception_guard
  {
    exception_guard (F f): f_ (move (f)) {}
    ~exception_guard ()
    {
      if (std::uncaught_exception ())
      {
        exception_unwinding_dtor = true;
        f_ ();
        exception_unwinding_dtor = false;
      }
    }

  private:
    F f_;
  };

  // Pools (@@ perhaps move into a separate header).
  //
  struct string_pool: std::unordered_set<std::string>
  {
    const std::string&
    find (const char* s) {return *emplace (s).first;}

    const std::string&
    find (const std::string& s) {return *emplace (s).first;}
  };
}

#include <build2/utility.ixx>

#endif // BUILD2_UTILITY