couchbase 4.2.1 → 4.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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