xref: /6.0.3/subjson/subdoc/path.h (revision 5a685f44)
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_PATH_H) && defined(__cplusplus)
19#define SUBDOC_PATH_H
20
21#include "subdoc-api.h"
22#include "jsonsl_header.h"
23#include <string>
24#include <list>
25
26
27typedef jsonsl_jpr_component_st PathComponent;
28
29class PathComponentInfo : public jsonsl_jpr_st {
30public:
31    PathComponentInfo(PathComponent *comps = NULL, size_t n = 0) {
32        components = comps;
33        ncomponents = n;
34        basestr = NULL;
35        orig = NULL;
36        norig = 0;
37        match_type = 0;
38    }
39
40    size_t size() const { return ncomponents; }
41
42    bool empty() const { return size() == 0; }
43
44    PathComponent& operator[](size_t ix) const { return get_component(ix); }
45    PathComponent& get_component(size_t ix) const { return components[ix]; }
46    PathComponent& back() const { return get_component(size()-1); }
47
48    /**Adds a component (without bounds checking)
49     * @return the newly added component*/
50    PathComponent& add(jsonsl_jpr_type_t ptype) {
51        PathComponent& ret = get_component(size());
52        ret.ptype = ptype;
53        ncomponents++;
54        return ret;
55    }
56
57    void pop() {
58        ncomponents--;
59    }
60
61    typedef PathComponent *iterator;
62    iterator begin() const { return components; }
63    iterator end() const { return components + size(); }
64};
65
66namespace Subdoc {
67/**
68 * Path limits:
69 *
70 * Path limits are designed to avoid abuse of the server by making paths too
71 * deep. The jsonsl parser has a fixed limit of depth (adjustable at runtime,
72 * but it is still fixed when allocating it).
73 *
74 * In the context of JSONSL, each JSON document contains an ephemeral "root"
75 * object which is at level 0. The actual top-level object (the list or object)
76 * is considered to be at level 1, and any of its children are considered to be
77 * level 2 and so on. Thus for example
78 *
79 * @code
80 * L0
81 *    L1
82 *    {
83 *       L2
84 *       "foo"
85 *       :
86 *       "bar"
87 *    }
88 * @endcode
89 *
90 * and so on.
91 *
92 * It also follows that a maximum depth of 1 only allows a top level (empty)
93 * object.
94 *
95 */
96class Limits {
97public:
98    static const size_t MAX_COMPONENTS = 32;
99    static const size_t PARSER_DEPTH = MAX_COMPONENTS + 1;
100    static const size_t PATH_COMPONENTS_ALLOC = MAX_COMPONENTS + 1;
101};
102
103class Path : public PathComponentInfo {
104public:
105    typedef PathComponent Component;
106    typedef PathComponentInfo CompInfo;
107
108    Path();
109    ~Path();
110    void clear();
111    int parse(const char *, size_t);
112    int parse(const char *s) { return parse(s, strlen(s)); }
113    int parse(const std::string& s) { return parse(s.c_str(), s.size()); }
114
115    Component components_s[Limits::PATH_COMPONENTS_ALLOC];
116    jsonsl_error_t add_array_index(long ixnum);
117    bool has_negix; /* True if there is a negative array index in the path */
118private:
119    inline const char * convert_escaped(const char *src, size_t &len);
120    inline int add_num_component(const char *component, size_t len);
121    inline int add_str_component(const char *component, size_t len, int n_backtick);
122    inline int parse_bracket(const char *path, size_t len, size_t *n_comsumed);
123    inline int parse_string(const char *path, size_t len, size_t *n_consumed);
124
125    std::list<std::string*> m_cached;
126    std::list<std::string*> m_used;
127};
128}
129
130#endif
131