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.
- package/CMakeLists.txt +1 -0
- package/deps/couchbase-cxx-client/.gitmodules +3 -0
- package/deps/couchbase-cxx-client/.idea/misc.xml +1 -0
- package/deps/couchbase-cxx-client/.idea/vcs.xml +1 -0
- package/deps/couchbase-cxx-client/CMakeLists.txt +11 -1
- package/deps/couchbase-cxx-client/README.md +3 -3
- package/deps/couchbase-cxx-client/cmake/CompilerWarnings.cmake +4 -1
- package/deps/couchbase-cxx-client/cmake/VersionInfo.cmake +13 -1
- package/deps/couchbase-cxx-client/cmake/build_version.hxx.in +1 -0
- package/deps/couchbase-cxx-client/core/cluster.hxx +15 -5
- package/deps/couchbase-cxx-client/core/impl/build_deferred_query_indexes.cxx +17 -6
- package/deps/couchbase-cxx-client/core/impl/cluster.cxx +1 -1
- package/deps/couchbase-cxx-client/core/impl/collection_query_index_manager.cxx +93 -0
- package/deps/couchbase-cxx-client/core/impl/configuration_profiles_registry.cxx +11 -0
- package/deps/couchbase-cxx-client/core/impl/create_query_index.cxx +119 -0
- package/deps/couchbase-cxx-client/core/impl/drop_query_index.cxx +108 -0
- package/deps/couchbase-cxx-client/core/impl/get.cxx +1 -1
- package/deps/couchbase-cxx-client/core/impl/get_all_query_indexes.cxx +76 -0
- package/deps/couchbase-cxx-client/core/impl/query.cxx +5 -7
- package/deps/couchbase-cxx-client/core/impl/watch_query_indexes.cxx +168 -0
- package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +15 -1
- package/deps/couchbase-cxx-client/core/logger/configuration.hxx +3 -0
- package/deps/couchbase-cxx-client/core/logger/level.hxx +21 -0
- package/deps/couchbase-cxx-client/core/logger/logger.hxx +4 -6
- package/deps/couchbase-cxx-client/core/meta/CMakeLists.txt +4 -2
- package/deps/couchbase-cxx-client/core/meta/features.hxx +31 -0
- package/deps/couchbase-cxx-client/core/meta/version.cxx +67 -5
- package/deps/couchbase-cxx-client/core/meta/version.hxx +12 -1
- package/deps/couchbase-cxx-client/core/metrics/CMakeLists.txt +4 -1
- package/deps/couchbase-cxx-client/core/metrics/logging_meter.cxx +46 -5
- package/deps/couchbase-cxx-client/core/metrics/logging_meter.hxx +10 -26
- package/deps/couchbase-cxx-client/core/operations/document_get_projected.cxx +3 -2
- package/deps/couchbase-cxx-client/core/operations/document_query.cxx +10 -12
- package/deps/couchbase-cxx-client/core/operations/document_query.hxx +1 -3
- package/deps/couchbase-cxx-client/core/operations/management/query_index_build.cxx +8 -14
- package/deps/couchbase-cxx-client/core/operations/management/query_index_build.hxx +2 -1
- package/deps/couchbase-cxx-client/core/operations/management/query_index_build_deferred.hxx +15 -8
- package/deps/couchbase-cxx-client/core/operations/management/query_index_create.cxx +7 -14
- package/deps/couchbase-cxx-client/core/operations/management/query_index_create.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/management/query_index_drop.cxx +11 -16
- package/deps/couchbase-cxx-client/core/operations/management/query_index_drop.hxx +2 -0
- package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all.cxx +8 -12
- package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all.hxx +4 -3
- package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all_deferred.cxx +21 -12
- package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all_deferred.hxx +3 -2
- package/deps/couchbase-cxx-client/core/origin.hxx +1 -1
- package/deps/couchbase-cxx-client/core/platform/uuid.cc +1 -2
- package/deps/couchbase-cxx-client/core/protocol/cmd_hello.hxx +5 -1
- package/deps/couchbase-cxx-client/core/query_context.hxx +79 -0
- package/deps/couchbase-cxx-client/core/tracing/CMakeLists.txt +3 -1
- package/deps/couchbase-cxx-client/core/tracing/threshold_logging_tracer.cxx +19 -4
- package/deps/couchbase-cxx-client/core/tracing/threshold_logging_tracer.hxx +2 -2
- package/deps/couchbase-cxx-client/core/transactions/async_attempt_context.hxx +10 -4
- package/deps/couchbase-cxx-client/core/transactions/atr_cleanup_entry.cxx +52 -63
- package/deps/couchbase-cxx-client/core/transactions/attempt_context.hxx +8 -3
- package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.cxx +163 -126
- package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.hxx +24 -37
- package/deps/couchbase-cxx-client/core/transactions/forward_compat.hxx +4 -4
- package/deps/couchbase-cxx-client/core/transactions/internal/atr_cleanup_entry.hxx +51 -13
- package/deps/couchbase-cxx-client/core/transactions/internal/client_record.hxx +26 -1
- package/deps/couchbase-cxx-client/core/transactions/internal/doc_record.hxx +21 -0
- package/deps/couchbase-cxx-client/core/transactions/internal/logging.hxx +40 -18
- package/deps/couchbase-cxx-client/core/transactions/internal/transaction_context.hxx +5 -0
- package/deps/couchbase-cxx-client/core/transactions/result.hxx +26 -0
- package/deps/couchbase-cxx-client/core/transactions/staged_mutation.cxx +48 -47
- package/deps/couchbase-cxx-client/core/transactions/staged_mutation.hxx +6 -6
- package/deps/couchbase-cxx-client/core/transactions/transaction_context.cxx +33 -19
- package/deps/couchbase-cxx-client/core/transactions/transaction_get_result.hxx +18 -2
- package/deps/couchbase-cxx-client/core/transactions/transaction_links.hxx +25 -2
- package/deps/couchbase-cxx-client/core/transactions/transactions.cxx +4 -4
- package/deps/couchbase-cxx-client/core/transactions/transactions_cleanup.cxx +49 -56
- package/deps/couchbase-cxx-client/core/transactions/waitable_op_list.hxx +7 -7
- package/deps/couchbase-cxx-client/core/transactions.hxx +0 -12
- package/deps/couchbase-cxx-client/core/utils/binary.hxx +1 -1
- package/deps/couchbase-cxx-client/core/utils/keyspace.hxx +55 -0
- package/deps/couchbase-cxx-client/couchbase/build_query_index_options.hxx +12 -45
- package/deps/couchbase-cxx-client/couchbase/cluster.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/cluster_options.hxx +6 -7
- package/deps/couchbase-cxx-client/couchbase/collection.hxx +8 -0
- package/deps/couchbase-cxx-client/couchbase/collection_query_index_manager.hxx +218 -0
- package/deps/couchbase-cxx-client/couchbase/configuration_profiles_registry.hxx +3 -0
- package/deps/couchbase-cxx-client/couchbase/create_primary_query_index_options.hxx +166 -0
- package/deps/couchbase-cxx-client/couchbase/create_query_index_options.hxx +172 -0
- package/deps/couchbase-cxx-client/couchbase/drop_primary_query_index_options.hxx +129 -0
- package/deps/couchbase-cxx-client/couchbase/drop_query_index_options.hxx +116 -0
- package/deps/couchbase-cxx-client/couchbase/fmt/cas.hxx +1 -1
- package/deps/couchbase-cxx-client/couchbase/fmt/query_scan_consistency.hxx +46 -0
- package/deps/couchbase-cxx-client/couchbase/fmt/query_status.hxx +70 -0
- package/deps/couchbase-cxx-client/couchbase/fmt/tls_verify_mode.hxx +46 -0
- package/deps/couchbase-cxx-client/couchbase/get_all_query_indexes_options.hxx +100 -0
- package/deps/couchbase-cxx-client/{core → couchbase}/management/query_index.hxx +2 -2
- package/deps/couchbase-cxx-client/couchbase/metrics/meter.hxx +16 -0
- package/deps/couchbase-cxx-client/couchbase/query_index_manager.hxx +178 -6
- package/deps/couchbase-cxx-client/couchbase/query_options.hxx +1 -18
- package/deps/couchbase-cxx-client/couchbase/scope.hxx +5 -2
- package/deps/couchbase-cxx-client/couchbase/tracing/request_tracer.hxx +16 -0
- package/deps/couchbase-cxx-client/couchbase/transactions/async_attempt_context.hxx +11 -4
- package/deps/couchbase-cxx-client/couchbase/transactions/attempt_context.hxx +5 -3
- package/deps/couchbase-cxx-client/couchbase/transactions/transaction_keyspace.hxx +16 -0
- package/deps/couchbase-cxx-client/couchbase/transactions/transaction_query_options.hxx +0 -6
- package/deps/couchbase-cxx-client/couchbase/watch_query_indexes_options.hxx +115 -0
- package/deps/couchbase-cxx-client/examples/minimal.cxx +3 -1
- package/deps/couchbase-cxx-client/test/test_integration_crud.cxx +72 -0
- package/deps/couchbase-cxx-client/test/test_integration_management.cxx +727 -310
- package/deps/couchbase-cxx-client/test/test_integration_query.cxx +4 -8
- package/deps/couchbase-cxx-client/test/test_integration_transcoders.cxx +14 -0
- package/deps/couchbase-cxx-client/test/test_transaction_transaction_public_blocking_api.cxx +34 -19
- package/deps/couchbase-cxx-client/test/test_unit_transaction_logging.cxx +66 -22
- package/deps/couchbase-cxx-client/test/test_unit_utils.cxx +51 -0
- package/deps/couchbase-cxx-client/test/tools/tool_kv_loader.cxx +2 -2
- package/deps/couchbase-cxx-client/test/utils/integration_test_guard.cxx +2 -0
- package/deps/couchbase-cxx-client/test/utils/wait_until.cxx +4 -4
- package/deps/couchbase-cxx-client/third_party/docopt/.travis.yml +103 -0
- package/deps/couchbase-cxx-client/third_party/docopt/CMakeLists.txt +129 -0
- package/deps/couchbase-cxx-client/third_party/docopt/LICENSE-Boost-1.0 +23 -0
- package/deps/couchbase-cxx-client/third_party/docopt/LICENSE-MIT +23 -0
- package/deps/couchbase-cxx-client/third_party/docopt/README.rst +479 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt-config.cmake +1 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt.cpp +687 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt.h +98 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt.pc.in +9 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt_private.h +676 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt_util.h +122 -0
- package/deps/couchbase-cxx-client/third_party/docopt/docopt_value.h +341 -0
- package/deps/couchbase-cxx-client/third_party/docopt/examples/naval_fate.cpp +36 -0
- package/deps/couchbase-cxx-client/third_party/docopt/main.cpp +16 -0
- package/deps/couchbase-cxx-client/third_party/docopt/run_testcase.cpp +40 -0
- package/deps/couchbase-cxx-client/third_party/docopt/run_tests.py +72 -0
- package/deps/couchbase-cxx-client/third_party/docopt/testcases.docopt +957 -0
- package/deps/couchbase-cxx-client/tools/CMakeLists.txt +14 -0
- package/deps/couchbase-cxx-client/tools/cbc.cxx +65 -0
- package/deps/couchbase-cxx-client/tools/command.hxx +31 -0
- package/deps/couchbase-cxx-client/tools/command_registry.cxx +43 -0
- package/deps/couchbase-cxx-client/tools/command_registry.hxx +39 -0
- package/deps/couchbase-cxx-client/tools/get.cxx +267 -0
- package/deps/couchbase-cxx-client/tools/get.hxx +26 -0
- package/deps/couchbase-cxx-client/tools/query.cxx +441 -0
- package/deps/couchbase-cxx-client/tools/query.hxx +26 -0
- package/deps/couchbase-cxx-client/tools/utils.cxx +418 -0
- package/deps/couchbase-cxx-client/tools/utils.hxx +150 -0
- package/deps/couchbase-cxx-client/tools/version.cxx +82 -0
- package/deps/couchbase-cxx-client/tools/version.hxx +26 -0
- package/dist/authenticators.d.ts +2 -2
- package/dist/authenticators.js +1 -2
- package/dist/binding.d.ts +32 -16
- package/dist/cluster.js +14 -7
- package/dist/collection.d.ts +6 -0
- package/dist/collection.js +8 -0
- package/dist/queryexecutor.js +1 -1
- package/dist/queryindexmanager.d.ts +100 -4
- package/dist/queryindexmanager.js +344 -118
- package/dist/transactions.js +0 -2
- package/package.json +1 -1
- package/src/connection.cpp +2 -0
- package/src/connection.hpp +1 -0
- package/src/connection_autogen.cpp +16 -0
- package/src/jstocbpp_autogen.hpp +93 -23
- package/src/jstocbpp_basic.hpp +24 -0
- package/src/jstocbpp_transactions.hpp +0 -8
- package/tools/gen-bindings-js.js +1 -0
- package/tools/gen-bindings-json.py +4 -2
- 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
|