couchbase 4.2.1 → 4.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (162) hide show
  1. package/CMakeLists.txt +1 -0
  2. package/deps/couchbase-cxx-client/.gitmodules +3 -0
  3. package/deps/couchbase-cxx-client/.idea/misc.xml +1 -0
  4. package/deps/couchbase-cxx-client/.idea/vcs.xml +1 -0
  5. package/deps/couchbase-cxx-client/CMakeLists.txt +11 -1
  6. package/deps/couchbase-cxx-client/README.md +3 -3
  7. package/deps/couchbase-cxx-client/cmake/CompilerWarnings.cmake +4 -1
  8. package/deps/couchbase-cxx-client/cmake/VersionInfo.cmake +13 -1
  9. package/deps/couchbase-cxx-client/cmake/build_version.hxx.in +1 -0
  10. package/deps/couchbase-cxx-client/core/cluster.hxx +15 -5
  11. package/deps/couchbase-cxx-client/core/impl/build_deferred_query_indexes.cxx +17 -6
  12. package/deps/couchbase-cxx-client/core/impl/cluster.cxx +1 -1
  13. package/deps/couchbase-cxx-client/core/impl/collection_query_index_manager.cxx +93 -0
  14. package/deps/couchbase-cxx-client/core/impl/configuration_profiles_registry.cxx +11 -0
  15. package/deps/couchbase-cxx-client/core/impl/create_query_index.cxx +119 -0
  16. package/deps/couchbase-cxx-client/core/impl/drop_query_index.cxx +108 -0
  17. package/deps/couchbase-cxx-client/core/impl/get.cxx +1 -1
  18. package/deps/couchbase-cxx-client/core/impl/get_all_query_indexes.cxx +76 -0
  19. package/deps/couchbase-cxx-client/core/impl/query.cxx +5 -7
  20. package/deps/couchbase-cxx-client/core/impl/watch_query_indexes.cxx +168 -0
  21. package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +15 -1
  22. package/deps/couchbase-cxx-client/core/logger/configuration.hxx +3 -0
  23. package/deps/couchbase-cxx-client/core/logger/level.hxx +21 -0
  24. package/deps/couchbase-cxx-client/core/logger/logger.hxx +4 -6
  25. package/deps/couchbase-cxx-client/core/meta/CMakeLists.txt +4 -2
  26. package/deps/couchbase-cxx-client/core/meta/features.hxx +31 -0
  27. package/deps/couchbase-cxx-client/core/meta/version.cxx +67 -5
  28. package/deps/couchbase-cxx-client/core/meta/version.hxx +12 -1
  29. package/deps/couchbase-cxx-client/core/metrics/CMakeLists.txt +4 -1
  30. package/deps/couchbase-cxx-client/core/metrics/logging_meter.cxx +46 -5
  31. package/deps/couchbase-cxx-client/core/metrics/logging_meter.hxx +10 -26
  32. package/deps/couchbase-cxx-client/core/operations/document_get_projected.cxx +3 -2
  33. package/deps/couchbase-cxx-client/core/operations/document_query.cxx +10 -12
  34. package/deps/couchbase-cxx-client/core/operations/document_query.hxx +1 -3
  35. package/deps/couchbase-cxx-client/core/operations/management/query_index_build.cxx +8 -14
  36. package/deps/couchbase-cxx-client/core/operations/management/query_index_build.hxx +2 -1
  37. package/deps/couchbase-cxx-client/core/operations/management/query_index_build_deferred.hxx +15 -8
  38. package/deps/couchbase-cxx-client/core/operations/management/query_index_create.cxx +7 -14
  39. package/deps/couchbase-cxx-client/core/operations/management/query_index_create.hxx +2 -0
  40. package/deps/couchbase-cxx-client/core/operations/management/query_index_drop.cxx +11 -16
  41. package/deps/couchbase-cxx-client/core/operations/management/query_index_drop.hxx +2 -0
  42. package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all.cxx +8 -12
  43. package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all.hxx +4 -3
  44. package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all_deferred.cxx +21 -12
  45. package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all_deferred.hxx +3 -2
  46. package/deps/couchbase-cxx-client/core/origin.hxx +1 -1
  47. package/deps/couchbase-cxx-client/core/platform/uuid.cc +1 -2
  48. package/deps/couchbase-cxx-client/core/protocol/cmd_hello.hxx +5 -1
  49. package/deps/couchbase-cxx-client/core/query_context.hxx +79 -0
  50. package/deps/couchbase-cxx-client/core/tracing/CMakeLists.txt +3 -1
  51. package/deps/couchbase-cxx-client/core/tracing/threshold_logging_tracer.cxx +19 -4
  52. package/deps/couchbase-cxx-client/core/tracing/threshold_logging_tracer.hxx +2 -2
  53. package/deps/couchbase-cxx-client/core/transactions/async_attempt_context.hxx +10 -4
  54. package/deps/couchbase-cxx-client/core/transactions/atr_cleanup_entry.cxx +52 -63
  55. package/deps/couchbase-cxx-client/core/transactions/attempt_context.hxx +8 -3
  56. package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.cxx +163 -126
  57. package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.hxx +24 -37
  58. package/deps/couchbase-cxx-client/core/transactions/forward_compat.hxx +4 -4
  59. package/deps/couchbase-cxx-client/core/transactions/internal/atr_cleanup_entry.hxx +51 -13
  60. package/deps/couchbase-cxx-client/core/transactions/internal/client_record.hxx +26 -1
  61. package/deps/couchbase-cxx-client/core/transactions/internal/doc_record.hxx +21 -0
  62. package/deps/couchbase-cxx-client/core/transactions/internal/logging.hxx +40 -18
  63. package/deps/couchbase-cxx-client/core/transactions/internal/transaction_context.hxx +5 -0
  64. package/deps/couchbase-cxx-client/core/transactions/result.hxx +26 -0
  65. package/deps/couchbase-cxx-client/core/transactions/staged_mutation.cxx +48 -47
  66. package/deps/couchbase-cxx-client/core/transactions/staged_mutation.hxx +6 -6
  67. package/deps/couchbase-cxx-client/core/transactions/transaction_context.cxx +33 -19
  68. package/deps/couchbase-cxx-client/core/transactions/transaction_get_result.hxx +18 -2
  69. package/deps/couchbase-cxx-client/core/transactions/transaction_links.hxx +25 -2
  70. package/deps/couchbase-cxx-client/core/transactions/transactions.cxx +4 -4
  71. package/deps/couchbase-cxx-client/core/transactions/transactions_cleanup.cxx +49 -56
  72. package/deps/couchbase-cxx-client/core/transactions/waitable_op_list.hxx +7 -7
  73. package/deps/couchbase-cxx-client/core/transactions.hxx +0 -12
  74. package/deps/couchbase-cxx-client/core/utils/binary.hxx +1 -1
  75. package/deps/couchbase-cxx-client/core/utils/keyspace.hxx +55 -0
  76. package/deps/couchbase-cxx-client/couchbase/build_query_index_options.hxx +12 -45
  77. package/deps/couchbase-cxx-client/couchbase/cluster.hxx +1 -1
  78. package/deps/couchbase-cxx-client/couchbase/cluster_options.hxx +6 -7
  79. package/deps/couchbase-cxx-client/couchbase/collection.hxx +8 -0
  80. package/deps/couchbase-cxx-client/couchbase/collection_query_index_manager.hxx +218 -0
  81. package/deps/couchbase-cxx-client/couchbase/configuration_profiles_registry.hxx +3 -0
  82. package/deps/couchbase-cxx-client/couchbase/create_primary_query_index_options.hxx +166 -0
  83. package/deps/couchbase-cxx-client/couchbase/create_query_index_options.hxx +172 -0
  84. package/deps/couchbase-cxx-client/couchbase/drop_primary_query_index_options.hxx +129 -0
  85. package/deps/couchbase-cxx-client/couchbase/drop_query_index_options.hxx +116 -0
  86. package/deps/couchbase-cxx-client/couchbase/fmt/cas.hxx +1 -1
  87. package/deps/couchbase-cxx-client/couchbase/fmt/query_scan_consistency.hxx +46 -0
  88. package/deps/couchbase-cxx-client/couchbase/fmt/query_status.hxx +70 -0
  89. package/deps/couchbase-cxx-client/couchbase/fmt/tls_verify_mode.hxx +46 -0
  90. package/deps/couchbase-cxx-client/couchbase/get_all_query_indexes_options.hxx +100 -0
  91. package/deps/couchbase-cxx-client/{core → couchbase}/management/query_index.hxx +2 -2
  92. package/deps/couchbase-cxx-client/couchbase/metrics/meter.hxx +16 -0
  93. package/deps/couchbase-cxx-client/couchbase/query_index_manager.hxx +178 -6
  94. package/deps/couchbase-cxx-client/couchbase/query_options.hxx +1 -18
  95. package/deps/couchbase-cxx-client/couchbase/scope.hxx +5 -2
  96. package/deps/couchbase-cxx-client/couchbase/tracing/request_tracer.hxx +16 -0
  97. package/deps/couchbase-cxx-client/couchbase/transactions/async_attempt_context.hxx +11 -4
  98. package/deps/couchbase-cxx-client/couchbase/transactions/attempt_context.hxx +5 -3
  99. package/deps/couchbase-cxx-client/couchbase/transactions/transaction_keyspace.hxx +16 -0
  100. package/deps/couchbase-cxx-client/couchbase/transactions/transaction_query_options.hxx +0 -6
  101. package/deps/couchbase-cxx-client/couchbase/watch_query_indexes_options.hxx +115 -0
  102. package/deps/couchbase-cxx-client/examples/minimal.cxx +3 -1
  103. package/deps/couchbase-cxx-client/test/test_integration_crud.cxx +72 -0
  104. package/deps/couchbase-cxx-client/test/test_integration_management.cxx +727 -310
  105. package/deps/couchbase-cxx-client/test/test_integration_query.cxx +4 -8
  106. package/deps/couchbase-cxx-client/test/test_integration_transcoders.cxx +14 -0
  107. package/deps/couchbase-cxx-client/test/test_transaction_transaction_public_blocking_api.cxx +34 -19
  108. package/deps/couchbase-cxx-client/test/test_unit_transaction_logging.cxx +66 -22
  109. package/deps/couchbase-cxx-client/test/test_unit_utils.cxx +51 -0
  110. package/deps/couchbase-cxx-client/test/tools/tool_kv_loader.cxx +2 -2
  111. package/deps/couchbase-cxx-client/test/utils/integration_test_guard.cxx +2 -0
  112. package/deps/couchbase-cxx-client/test/utils/wait_until.cxx +4 -4
  113. package/deps/couchbase-cxx-client/third_party/docopt/.travis.yml +103 -0
  114. package/deps/couchbase-cxx-client/third_party/docopt/CMakeLists.txt +129 -0
  115. package/deps/couchbase-cxx-client/third_party/docopt/LICENSE-Boost-1.0 +23 -0
  116. package/deps/couchbase-cxx-client/third_party/docopt/LICENSE-MIT +23 -0
  117. package/deps/couchbase-cxx-client/third_party/docopt/README.rst +479 -0
  118. package/deps/couchbase-cxx-client/third_party/docopt/docopt-config.cmake +1 -0
  119. package/deps/couchbase-cxx-client/third_party/docopt/docopt.cpp +687 -0
  120. package/deps/couchbase-cxx-client/third_party/docopt/docopt.h +98 -0
  121. package/deps/couchbase-cxx-client/third_party/docopt/docopt.pc.in +9 -0
  122. package/deps/couchbase-cxx-client/third_party/docopt/docopt_private.h +676 -0
  123. package/deps/couchbase-cxx-client/third_party/docopt/docopt_util.h +122 -0
  124. package/deps/couchbase-cxx-client/third_party/docopt/docopt_value.h +341 -0
  125. package/deps/couchbase-cxx-client/third_party/docopt/examples/naval_fate.cpp +36 -0
  126. package/deps/couchbase-cxx-client/third_party/docopt/main.cpp +16 -0
  127. package/deps/couchbase-cxx-client/third_party/docopt/run_testcase.cpp +40 -0
  128. package/deps/couchbase-cxx-client/third_party/docopt/run_tests.py +72 -0
  129. package/deps/couchbase-cxx-client/third_party/docopt/testcases.docopt +957 -0
  130. package/deps/couchbase-cxx-client/tools/CMakeLists.txt +14 -0
  131. package/deps/couchbase-cxx-client/tools/cbc.cxx +65 -0
  132. package/deps/couchbase-cxx-client/tools/command.hxx +31 -0
  133. package/deps/couchbase-cxx-client/tools/command_registry.cxx +43 -0
  134. package/deps/couchbase-cxx-client/tools/command_registry.hxx +39 -0
  135. package/deps/couchbase-cxx-client/tools/get.cxx +267 -0
  136. package/deps/couchbase-cxx-client/tools/get.hxx +26 -0
  137. package/deps/couchbase-cxx-client/tools/query.cxx +441 -0
  138. package/deps/couchbase-cxx-client/tools/query.hxx +26 -0
  139. package/deps/couchbase-cxx-client/tools/utils.cxx +418 -0
  140. package/deps/couchbase-cxx-client/tools/utils.hxx +150 -0
  141. package/deps/couchbase-cxx-client/tools/version.cxx +82 -0
  142. package/deps/couchbase-cxx-client/tools/version.hxx +26 -0
  143. package/dist/authenticators.d.ts +2 -2
  144. package/dist/authenticators.js +1 -2
  145. package/dist/binding.d.ts +32 -16
  146. package/dist/cluster.js +14 -7
  147. package/dist/collection.d.ts +6 -0
  148. package/dist/collection.js +8 -0
  149. package/dist/queryexecutor.js +1 -1
  150. package/dist/queryindexmanager.d.ts +100 -4
  151. package/dist/queryindexmanager.js +344 -118
  152. package/dist/transactions.js +0 -2
  153. package/package.json +1 -1
  154. package/src/connection.cpp +2 -0
  155. package/src/connection.hpp +1 -0
  156. package/src/connection_autogen.cpp +16 -0
  157. package/src/jstocbpp_autogen.hpp +93 -23
  158. package/src/jstocbpp_basic.hpp +24 -0
  159. package/src/jstocbpp_transactions.hpp +0 -8
  160. package/tools/gen-bindings-js.js +1 -0
  161. package/tools/gen-bindings-json.py +4 -2
  162. package/deps/couchbase-cxx-client/core/transactions/logging.cxx +0 -107
@@ -0,0 +1,676 @@
1
+ //
2
+ // docopt_private.h
3
+ // docopt
4
+ //
5
+ // Created by Jared Grubb on 2013-11-04.
6
+ // Copyright (c) 2013 Jared Grubb. All rights reserved.
7
+ //
8
+
9
+ #ifndef docopt_docopt_private_h
10
+ #define docopt_docopt_private_h
11
+
12
+ #include <vector>
13
+ #include <memory>
14
+ #include <unordered_set>
15
+ #include <assert.h>
16
+
17
+ // Workaround GCC 4.8 not having std::regex
18
+ #if DOCTOPT_USE_BOOST_REGEX
19
+ #include <boost/regex.hpp>
20
+ namespace std {
21
+ using boost::regex;
22
+ using boost::sregex_iterator;
23
+ using boost::smatch;
24
+ using boost::regex_search;
25
+ namespace regex_constants {
26
+ using boost::regex_constants::match_not_null;
27
+ }
28
+ }
29
+ #else
30
+ #include <regex>
31
+ #endif
32
+
33
+ #include "docopt_value.h"
34
+
35
+ namespace docopt {
36
+
37
+ class Pattern;
38
+ class LeafPattern;
39
+
40
+ using PatternList = std::vector<std::shared_ptr<Pattern>>;
41
+
42
+ // Utility to use Pattern types in std hash-containers
43
+ struct PatternHasher {
44
+ template <typename P>
45
+ size_t operator()(std::shared_ptr<P> const& pattern) const {
46
+ return pattern->hash();
47
+ }
48
+ template <typename P>
49
+ size_t operator()(P const* pattern) const {
50
+ return pattern->hash();
51
+ }
52
+ template <typename P>
53
+ size_t operator()(P const& pattern) const {
54
+ return pattern.hash();
55
+ }
56
+ };
57
+
58
+ // Utility to use 'hash' as the equality operator as well in std containers
59
+ struct PatternPointerEquality {
60
+ template <typename P1, typename P2>
61
+ bool operator()(std::shared_ptr<P1> const& p1, std::shared_ptr<P2> const& p2) const {
62
+ return p1->hash()==p2->hash();
63
+ }
64
+ template <typename P1, typename P2>
65
+ bool operator()(P1 const* p1, P2 const* p2) const {
66
+ return p1->hash()==p2->hash();
67
+ }
68
+ };
69
+
70
+ // A hash-set that uniques by hash value
71
+ using UniquePatternSet = std::unordered_set<std::shared_ptr<Pattern>, PatternHasher, PatternPointerEquality>;
72
+
73
+
74
+ class Pattern {
75
+ public:
76
+ // flatten out children, stopping descent when the given filter returns 'true'
77
+ virtual std::vector<Pattern*> flat(bool (*filter)(Pattern const*)) = 0;
78
+
79
+ // flatten out all children into a list of LeafPattern objects
80
+ virtual void collect_leaves(std::vector<LeafPattern*>&) = 0;
81
+
82
+ // flatten out all children into a list of LeafPattern objects
83
+ std::vector<LeafPattern*> leaves();
84
+
85
+ // Attempt to find something in 'left' that matches this pattern's spec, and if so, move it to 'collected'
86
+ virtual bool match(PatternList& left, std::vector<std::shared_ptr<LeafPattern>>& collected) const = 0;
87
+
88
+ virtual std::string const& name() const = 0;
89
+
90
+ virtual bool hasValue() const { return false; }
91
+
92
+ virtual size_t hash() const = 0;
93
+
94
+ virtual ~Pattern() = default;
95
+ };
96
+
97
+ class LeafPattern
98
+ : public Pattern {
99
+ public:
100
+ LeafPattern(std::string name, value v = {})
101
+ : fName(std::move(name)),
102
+ fValue(std::move(v))
103
+ {}
104
+
105
+ virtual std::vector<Pattern*> flat(bool (*filter)(Pattern const*)) override {
106
+ if (filter(this)) {
107
+ return { this };
108
+ }
109
+ return {};
110
+ }
111
+
112
+ virtual void collect_leaves(std::vector<LeafPattern*>& lst) override final {
113
+ lst.push_back(this);
114
+ }
115
+
116
+ virtual bool match(PatternList& left, std::vector<std::shared_ptr<LeafPattern>>& collected) const override;
117
+
118
+ virtual bool hasValue() const override { return static_cast<bool>(fValue); }
119
+
120
+ value const& getValue() const { return fValue; }
121
+ void setValue(value&& v) { fValue = std::move(v); }
122
+
123
+ virtual std::string const& name() const override { return fName; }
124
+
125
+ virtual size_t hash() const override {
126
+ size_t seed = typeid(*this).hash_code();
127
+ hash_combine(seed, fName);
128
+ hash_combine(seed, fValue);
129
+ return seed;
130
+ }
131
+
132
+ protected:
133
+ virtual std::pair<size_t, std::shared_ptr<LeafPattern>> single_match(PatternList const&) const = 0;
134
+
135
+ private:
136
+ std::string fName;
137
+ value fValue;
138
+ };
139
+
140
+ class BranchPattern
141
+ : public Pattern {
142
+ public:
143
+ BranchPattern(PatternList children = {})
144
+ : fChildren(std::move(children))
145
+ {}
146
+
147
+ Pattern& fix() {
148
+ UniquePatternSet patterns;
149
+ fix_identities(patterns);
150
+ fix_repeating_arguments();
151
+ return *this;
152
+ }
153
+
154
+ virtual std::string const& name() const override {
155
+ throw std::runtime_error("Logic error: name() shouldnt be called on a BranchPattern");
156
+ }
157
+
158
+ virtual value const& getValue() const {
159
+ throw std::runtime_error("Logic error: name() shouldnt be called on a BranchPattern");
160
+ }
161
+
162
+ virtual std::vector<Pattern*> flat(bool (*filter)(Pattern const*)) override {
163
+ if (filter(this)) {
164
+ return {this};
165
+ }
166
+
167
+ std::vector<Pattern*> ret;
168
+ for(auto& child : fChildren) {
169
+ auto sublist = child->flat(filter);
170
+ ret.insert(ret.end(), sublist.begin(), sublist.end());
171
+ }
172
+ return ret;
173
+ }
174
+
175
+ virtual void collect_leaves(std::vector<LeafPattern*>& lst) override final {
176
+ for(auto& child : fChildren) {
177
+ child->collect_leaves(lst);
178
+ }
179
+ }
180
+
181
+ void setChildren(PatternList children) {
182
+ fChildren = std::move(children);
183
+ }
184
+
185
+ PatternList const& children() const { return fChildren; }
186
+
187
+ virtual void fix_identities(UniquePatternSet& patterns) {
188
+ for(auto& child : fChildren) {
189
+ // this will fix up all its children, if needed
190
+ if (auto bp = dynamic_cast<BranchPattern*>(child.get())) {
191
+ bp->fix_identities(patterns);
192
+ }
193
+
194
+ // then we try to add it to the list
195
+ auto inserted = patterns.insert(child);
196
+ if (!inserted.second) {
197
+ // already there? then reuse the existing shared_ptr for that thing
198
+ child = *inserted.first;
199
+ }
200
+ }
201
+ }
202
+
203
+ virtual size_t hash() const override {
204
+ size_t seed = typeid(*this).hash_code();
205
+ hash_combine(seed, fChildren.size());
206
+ for(auto const& child : fChildren) {
207
+ hash_combine(seed, child->hash());
208
+ }
209
+ return seed;
210
+ }
211
+ private:
212
+ void fix_repeating_arguments();
213
+
214
+ protected:
215
+ PatternList fChildren;
216
+ };
217
+
218
+ class Argument
219
+ : public LeafPattern {
220
+ public:
221
+ using LeafPattern::LeafPattern;
222
+
223
+ protected:
224
+ virtual std::pair<size_t, std::shared_ptr<LeafPattern>> single_match(PatternList const& left) const override;
225
+ };
226
+
227
+ class Command : public Argument {
228
+ public:
229
+ Command(std::string name, value v = value{false})
230
+ : Argument(std::move(name), std::move(v))
231
+ {}
232
+
233
+ protected:
234
+ virtual std::pair<size_t, std::shared_ptr<LeafPattern>> single_match(PatternList const& left) const override;
235
+ };
236
+
237
+ class Option final
238
+ : public LeafPattern
239
+ {
240
+ public:
241
+ static Option parse(std::string const& option_description);
242
+
243
+ Option(std::string shortOption,
244
+ std::string longOption,
245
+ int argcount = 0,
246
+ value v = value{false})
247
+ : LeafPattern(longOption.empty() ? shortOption : longOption,
248
+ std::move(v)),
249
+ fShortOption(std::move(shortOption)),
250
+ fLongOption(std::move(longOption)),
251
+ fArgcount(argcount)
252
+ {
253
+ // From Python:
254
+ // self.value = None if value is False and argcount else value
255
+ if (argcount && v.isBool() && !v.asBool()) {
256
+ setValue(value{});
257
+ }
258
+ }
259
+
260
+ Option(Option const&) = default;
261
+ Option(Option&&) = default;
262
+ Option& operator=(Option const&) = default;
263
+ Option& operator=(Option&&) = default;
264
+
265
+ using LeafPattern::setValue;
266
+
267
+ std::string const& longOption() const { return fLongOption; }
268
+ std::string const& shortOption() const { return fShortOption; }
269
+ int argCount() const { return fArgcount; }
270
+
271
+ virtual size_t hash() const override {
272
+ size_t seed = LeafPattern::hash();
273
+ hash_combine(seed, fShortOption);
274
+ hash_combine(seed, fLongOption);
275
+ hash_combine(seed, fArgcount);
276
+ return seed;
277
+ }
278
+
279
+ protected:
280
+ virtual std::pair<size_t, std::shared_ptr<LeafPattern>> single_match(PatternList const& left) const override;
281
+
282
+ private:
283
+ std::string fShortOption;
284
+ std::string fLongOption;
285
+ int fArgcount;
286
+ };
287
+
288
+ class Required : public BranchPattern {
289
+ public:
290
+ using BranchPattern::BranchPattern;
291
+
292
+ bool match(PatternList& left, std::vector<std::shared_ptr<LeafPattern>>& collected) const override;
293
+ };
294
+
295
+ class Optional : public BranchPattern {
296
+ public:
297
+ using BranchPattern::BranchPattern;
298
+
299
+ bool match(PatternList& left, std::vector<std::shared_ptr<LeafPattern>>& collected) const override {
300
+ for(auto const& pattern : fChildren) {
301
+ pattern->match(left, collected);
302
+ }
303
+ return true;
304
+ }
305
+ };
306
+
307
+ class OptionsShortcut : public Optional {
308
+ using Optional::Optional;
309
+ };
310
+
311
+ class OneOrMore : public BranchPattern {
312
+ public:
313
+ using BranchPattern::BranchPattern;
314
+
315
+ bool match(PatternList& left, std::vector<std::shared_ptr<LeafPattern>>& collected) const override;
316
+ };
317
+
318
+ class Either : public BranchPattern {
319
+ public:
320
+ using BranchPattern::BranchPattern;
321
+
322
+ bool match(PatternList& left, std::vector<std::shared_ptr<LeafPattern>>& collected) const override;
323
+ };
324
+
325
+ #if 0
326
+ #pragma mark -
327
+ #pragma mark inline implementations
328
+ #endif
329
+
330
+ inline std::vector<LeafPattern*> Pattern::leaves()
331
+ {
332
+ std::vector<LeafPattern*> ret;
333
+ collect_leaves(ret);
334
+ return ret;
335
+ }
336
+
337
+ static inline std::vector<PatternList> transform(PatternList pattern)
338
+ {
339
+ std::vector<PatternList> result;
340
+
341
+ std::vector<PatternList> groups;
342
+ groups.emplace_back(std::move(pattern));
343
+
344
+ while(!groups.empty()) {
345
+ // pop off the first element
346
+ auto children = std::move(groups[0]);
347
+ groups.erase(groups.begin());
348
+
349
+ // find the first branch node in the list
350
+ auto child_iter = std::find_if(children.begin(), children.end(), [](std::shared_ptr<Pattern> const& p) {
351
+ return dynamic_cast<BranchPattern const*>(p.get());
352
+ });
353
+
354
+ // no branch nodes left : expansion is complete for this grouping
355
+ if (child_iter == children.end()) {
356
+ result.emplace_back(std::move(children));
357
+ continue;
358
+ }
359
+
360
+ // pop the child from the list
361
+ auto child = std::move(*child_iter);
362
+ children.erase(child_iter);
363
+
364
+ // expand the branch in the appropriate way
365
+ if (Either* either = dynamic_cast<Either*>(child.get())) {
366
+ // "[e] + children" for each child 'e' in Either
367
+ for(auto const& eitherChild : either->children()) {
368
+ PatternList group = { eitherChild };
369
+ group.insert(group.end(), children.begin(), children.end());
370
+
371
+ groups.emplace_back(std::move(group));
372
+ }
373
+ } else if (OneOrMore* oneOrMore = dynamic_cast<OneOrMore*>(child.get())) {
374
+ // child.children * 2 + children
375
+ auto const& subchildren = oneOrMore->children();
376
+ PatternList group = subchildren;
377
+ group.insert(group.end(), subchildren.begin(), subchildren.end());
378
+ group.insert(group.end(), children.begin(), children.end());
379
+
380
+ groups.emplace_back(std::move(group));
381
+ } else { // Required, Optional, OptionsShortcut
382
+ BranchPattern* branch = dynamic_cast<BranchPattern*>(child.get());
383
+
384
+ // child.children + children
385
+ PatternList group = branch->children();
386
+ group.insert(group.end(), children.begin(), children.end());
387
+
388
+ groups.emplace_back(std::move(group));
389
+ }
390
+ }
391
+
392
+ return result;
393
+ }
394
+
395
+ inline void BranchPattern::fix_repeating_arguments()
396
+ {
397
+ std::vector<PatternList> either = transform(children());
398
+ for(auto const& group : either) {
399
+ // use multiset to help identify duplicate entries
400
+ std::unordered_multiset<std::shared_ptr<Pattern>, PatternHasher> group_set {group.begin(), group.end()};
401
+ for(auto const& e : group_set) {
402
+ if (group_set.count(e) == 1)
403
+ continue;
404
+
405
+ LeafPattern* leaf = dynamic_cast<LeafPattern*>(e.get());
406
+ if (!leaf) continue;
407
+
408
+ bool ensureList = false;
409
+ bool ensureInt = false;
410
+
411
+ if (dynamic_cast<Command*>(leaf)) {
412
+ ensureInt = true;
413
+ } else if (dynamic_cast<Argument*>(leaf)) {
414
+ ensureList = true;
415
+ } else if (Option* o = dynamic_cast<Option*>(leaf)) {
416
+ if (o->argCount()) {
417
+ ensureList = true;
418
+ } else {
419
+ ensureInt = true;
420
+ }
421
+ }
422
+
423
+ if (ensureList) {
424
+ std::vector<std::string> newValue;
425
+ if (leaf->getValue().isString()) {
426
+ newValue = split(leaf->getValue().asString());
427
+ }
428
+ if (!leaf->getValue().isStringList()) {
429
+ leaf->setValue(value{newValue});
430
+ }
431
+ } else if (ensureInt) {
432
+ leaf->setValue(value{0});
433
+ }
434
+ }
435
+ }
436
+ }
437
+
438
+ inline bool LeafPattern::match(PatternList& left, std::vector<std::shared_ptr<LeafPattern>>& collected) const
439
+ {
440
+ auto match = single_match(left);
441
+ if (!match.second) {
442
+ return false;
443
+ }
444
+
445
+ left.erase(left.begin()+static_cast<std::ptrdiff_t>(match.first));
446
+
447
+ auto same_name = std::find_if(collected.begin(), collected.end(), [&](std::shared_ptr<LeafPattern> const& p) {
448
+ return p->name()==name();
449
+ });
450
+ if (getValue().isLong()) {
451
+ long val = 1;
452
+ if (same_name == collected.end()) {
453
+ collected.push_back(match.second);
454
+ match.second->setValue(value{val});
455
+ } else if ((**same_name).getValue().isLong()) {
456
+ val += (**same_name).getValue().asLong();
457
+ (**same_name).setValue(value{val});
458
+ } else {
459
+ (**same_name).setValue(value{val});
460
+ }
461
+ } else if (getValue().isStringList()) {
462
+ std::vector<std::string> val;
463
+ if (match.second->getValue().isString()) {
464
+ val.push_back(match.second->getValue().asString());
465
+ } else if (match.second->getValue().isStringList()) {
466
+ val = match.second->getValue().asStringList();
467
+ } else {
468
+ /// cant be!?
469
+ }
470
+
471
+ if (same_name == collected.end()) {
472
+ collected.push_back(match.second);
473
+ match.second->setValue(value{val});
474
+ } else if ((**same_name).getValue().isStringList()) {
475
+ std::vector<std::string> const& list = (**same_name).getValue().asStringList();
476
+ val.insert(val.begin(), list.begin(), list.end());
477
+ (**same_name).setValue(value{val});
478
+ } else {
479
+ (**same_name).setValue(value{val});
480
+ }
481
+ } else {
482
+ collected.push_back(match.second);
483
+ }
484
+ return true;
485
+ }
486
+
487
+ inline std::pair<size_t, std::shared_ptr<LeafPattern>> Argument::single_match(PatternList const& left) const
488
+ {
489
+ std::pair<size_t, std::shared_ptr<LeafPattern>> ret {};
490
+
491
+ for(size_t i = 0, size = left.size(); i < size; ++i)
492
+ {
493
+ auto arg = dynamic_cast<Argument const*>(left[i].get());
494
+ if (arg) {
495
+ ret.first = i;
496
+ ret.second = std::make_shared<Argument>(name(), arg->getValue());
497
+ break;
498
+ }
499
+ }
500
+
501
+ return ret;
502
+ }
503
+
504
+ inline std::pair<size_t, std::shared_ptr<LeafPattern>> Command::single_match(PatternList const& left) const
505
+ {
506
+ std::pair<size_t, std::shared_ptr<LeafPattern>> ret {};
507
+
508
+ for(size_t i = 0, size = left.size(); i < size; ++i)
509
+ {
510
+ auto arg = dynamic_cast<Argument const*>(left[i].get());
511
+ if (arg) {
512
+ if (name() == arg->getValue()) {
513
+ ret.first = i;
514
+ ret.second = std::make_shared<Command>(name(), value{true});
515
+ }
516
+ break;
517
+ }
518
+ }
519
+
520
+ return ret;
521
+ }
522
+
523
+ inline Option Option::parse(std::string const& option_description)
524
+ {
525
+ std::string shortOption, longOption;
526
+ int argcount = 0;
527
+ value val { false };
528
+
529
+ auto double_space = option_description.find(" ");
530
+ auto options_end = option_description.end();
531
+ if (double_space != std::string::npos) {
532
+ options_end = option_description.begin() + static_cast<std::ptrdiff_t>(double_space);
533
+ }
534
+
535
+ static const std::regex pattern {"(-{1,2})?(.*?)([,= ]|$)"};
536
+ for(std::sregex_iterator i {option_description.begin(), options_end, pattern, std::regex_constants::match_not_null},
537
+ e{};
538
+ i != e;
539
+ ++i)
540
+ {
541
+ std::smatch const& match = *i;
542
+ if (match[1].matched) { // [1] is optional.
543
+ if (match[1].length()==1) {
544
+ shortOption = "-" + match[2].str();
545
+ } else {
546
+ longOption = "--" + match[2].str();
547
+ }
548
+ } else if (match[2].length() > 0) { // [2] always matches.
549
+ std::string m = match[2];
550
+ argcount = 1;
551
+ } else {
552
+ // delimeter
553
+ }
554
+
555
+ if (match[3].length() == 0) { // [3] always matches.
556
+ // Hit end of string. For some reason 'match_not_null' will let us match empty
557
+ // at the end, and then we'll spin in an infinite loop. So, if we hit an empty
558
+ // match, we know we must be at the end.
559
+ break;
560
+ }
561
+ }
562
+
563
+ if (argcount) {
564
+ std::smatch match;
565
+ if (std::regex_search(options_end, option_description.end(),
566
+ match,
567
+ std::regex{"\\[default: (.*)\\]", std::regex::icase}))
568
+ {
569
+ val = match[1].str();
570
+ }
571
+ }
572
+
573
+ return {std::move(shortOption),
574
+ std::move(longOption),
575
+ argcount,
576
+ std::move(val)};
577
+ }
578
+
579
+ inline std::pair<size_t, std::shared_ptr<LeafPattern>> Option::single_match(PatternList const& left) const
580
+ {
581
+ auto thematch = find_if(left.begin(), left.end(), [this](std::shared_ptr<Pattern> const& a) {
582
+ auto leaf = std::dynamic_pointer_cast<LeafPattern>(a);
583
+ return leaf && this->name() == leaf->name();
584
+ });
585
+ if (thematch == left.end()) {
586
+ return {};
587
+ }
588
+ return { std::distance(left.begin(), thematch), std::dynamic_pointer_cast<LeafPattern>(*thematch) };
589
+ }
590
+
591
+ inline bool Required::match(PatternList& left, std::vector<std::shared_ptr<LeafPattern>>& collected) const {
592
+ auto l = left;
593
+ auto c = collected;
594
+ for(auto const& pattern : fChildren) {
595
+ bool ret = pattern->match(l, c);
596
+ if (!ret) {
597
+ // leave (left, collected) untouched
598
+ return false;
599
+ }
600
+ }
601
+
602
+ left = std::move(l);
603
+ collected = std::move(c);
604
+ return true;
605
+ }
606
+
607
+ inline bool OneOrMore::match(PatternList& left, std::vector<std::shared_ptr<LeafPattern>>& collected) const
608
+ {
609
+ assert(fChildren.size() == 1);
610
+
611
+ auto l = left;
612
+ auto c = collected;
613
+
614
+ bool matched = true;
615
+ size_t times = 0;
616
+
617
+ decltype(l) l_;
618
+ bool firstLoop = true;
619
+
620
+ while (matched) {
621
+ // could it be that something didn't match but changed l or c?
622
+ matched = fChildren[0]->match(l, c);
623
+
624
+ if (matched)
625
+ ++times;
626
+
627
+ if (firstLoop) {
628
+ firstLoop = false;
629
+ } else if (l == l_) {
630
+ break;
631
+ }
632
+
633
+ l_ = l;
634
+ }
635
+
636
+ if (times == 0) {
637
+ return false;
638
+ }
639
+
640
+ left = std::move(l);
641
+ collected = std::move(c);
642
+ return true;
643
+ }
644
+
645
+ inline bool Either::match(PatternList& left, std::vector<std::shared_ptr<LeafPattern>>& collected) const
646
+ {
647
+ using Outcome = std::pair<PatternList, std::vector<std::shared_ptr<LeafPattern>>>;
648
+
649
+ std::vector<Outcome> outcomes;
650
+
651
+ for(auto const& pattern : fChildren) {
652
+ // need a copy so we apply the same one for every iteration
653
+ auto l = left;
654
+ auto c = collected;
655
+ bool matched = pattern->match(l, c);
656
+ if (matched) {
657
+ outcomes.emplace_back(std::move(l), std::move(c));
658
+ }
659
+ }
660
+
661
+ auto min = std::min_element(outcomes.begin(), outcomes.end(), [](Outcome const& o1, Outcome const& o2) {
662
+ return o1.first.size() < o2.first.size();
663
+ });
664
+
665
+ if (min == outcomes.end()) {
666
+ // (left, collected) unchanged
667
+ return false;
668
+ }
669
+
670
+ std::tie(left, collected) = std::move(*min);
671
+ return true;
672
+ }
673
+
674
+ }
675
+
676
+ #endif