xref: /5.5.2/subjson/subdoc/match.h (revision 9f2dfe6a)
1/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3*     Copyright 2015 Couchbase, Inc
4*
5*   Licensed under the Apache License, Version 2.0 (the "License");
6*   you may not use this file except in compliance with the License.
7*   You may obtain a copy of the License at
8*
9*       http://www.apache.org/licenses/LICENSE-2.0
10*
11*   Unless required by applicable law or agreed to in writing, software
12*   distributed under the License is distributed on an "AS IS" BASIS,
13*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*   See the License for the specific language governing permissions and
15*   limitations under the License.
16*/
17
18#if !defined(SUBDOC_MATCH_H) && defined(__cplusplus)
19#define SUBDOC_MATCH_H
20
21#include "loc.h"
22#include "path.h"
23
24namespace Subdoc {
25
26/** Structure describing a match for an item */
27class Match {
28public:
29    /**The JSON type for the result (i.e. jsonsl_type_t). If the match itself
30     * is not found, this will contain the innermost _parent_ type. */
31    uint32_t type;
32
33    /**Error status (jsonsl_error_t) */
34    uint16_t status;
35
36    /** result of the match. jsonsl_jpr_match_t */
37    int16_t matchres;
38
39    /** Flags, if #type is JSONSL_TYPE_SPECIAL */
40    uint16_t sflags;
41
42    /**
43     * The deepest level at which a possible match was found.
44     * In jsonsl, the imaginary root level is 0, the top level container
45     * is 1, etc.
46     */
47    uint16_t match_level;
48
49    /**
50     * The current position of the match. This value is 0-based and works
51     * in conjunction with #num_siblings to determine how to handle
52     * surrounding items for various modification items.
53     */
54    unsigned position;
55
56    /**The number of children in the last parent. Note this may not necessarily
57     * be the immediate parent; but rather indicates whether any kind of special
58     * comma handling is required.
59     *
60     * This is used by insertion/deletion operations to determine if any
61     * trailing tokens from surrounding items should be stripped.
62     * If a match is found, then this _excludes_ the match (in other words,
63     * this is not the size of the container, but rather how many elements
64     * in the container are not the match)
65     */
66    unsigned num_siblings;
67
68    /** For array matches, contains the number of children in the array */
69    unsigned num_children;
70
71    /**
72     * Check if match is the first of many
73     * @return true iff match is the first of multiple siblings
74     */
75    bool is_first() const {
76        return num_siblings && position == 0;
77    }
78
79    /**
80     * Check if match is the last of many
81     * @return true iff match is the last of multiple siblings
82     */
83    bool is_last() const {
84        return num_siblings && position == num_siblings;
85    }
86
87    /**
88     * Check if the match is alone in the container
89     * @return true iff match is the only element in the container
90     */
91    bool is_only() const {
92        return num_siblings == 0;
93    }
94
95    bool has_key() const {
96        return !loc_key.empty();
97    }
98
99    /**
100     * Response flag indicating that the match's immediate parent was found,
101     * and its location is in #loc_parent.
102     *
103     * This flag is implied to be true if #matchres is JSONSL_MATCH_COMPLETE
104     */
105    unsigned char immediate_parent_found;
106
107    /**Request flag; indicating whether the last child position should be
108     * returned inside the `loc_key` member. Note that the position will
109     * be indicated in the `loc_key`'s _length_ field, and its `at` field
110     * will be set to NULL
111     *
112     * This requires that the last child be an array element, and thus the
113     * parent match object be an array.
114     *
115     * This also changes some of the match semantics. Here most of the
116     * information will be adapted to suit the last child; this includes
117     * things like the value type and such.
118     */
119    unsigned char get_last;
120
121    enum SearchOptions {
122        GET_MATCH_ONLY = 0,
123        GET_FOLLOWING_SIBLINGS
124    };
125
126    SearchOptions extra_options = GET_MATCH_ONLY;
127
128    /**If 'ensure_unique' is true, set to true if the value of #ensure_unique
129     * already exists */
130    unsigned char unique_item_found;
131
132    /**
133     * Deepest match found. If the match was completely found, then this
134     * points to the actual match. Otherwise, this is one of the parents.
135     */
136    Loc loc_deepest;
137
138    /**Location desribing the key for the item. Valid only if #has_key is true*/
139    Loc loc_key;
140
141    /**If set to true, will also descend each child element to ensure that
142     * the contents here are unique. Will set an error code accordingly, if
143     * types are mismatched. */
144    Loc ensure_unique;
145
146    int exec_match(const char *value, size_t nvalue, const Path *path, jsonsl_t jsn);
147    int exec_match(const Loc& loc, const Path* path, jsonsl_t jsn) {
148        return exec_match(loc.at, loc.length, path, jsn);
149    }
150    int exec_match(const std::string& s, const Path& path, jsonsl_t jsn) {
151        return exec_match(s.c_str(), s.size(), &path, jsn);
152    }
153
154    Match();
155    ~Match();
156    void clear();
157
158    static jsonsl_t jsn_alloc();
159    static void jsn_free(jsonsl_t jsn);
160private:
161    inline int exec_match_simple(const char *value, size_t nvalue, const Path::CompInfo *jpr, jsonsl_t jsn);
162    inline int exec_match_negix(const char *value, size_t nvalue, const Path *pth, jsonsl_t jsn);
163};
164}
165
166#endif /* SUBDOC_MATCH_H */
167