xref: /6.6.0/subjson/subdoc/operations.h (revision e51529ef)
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#include "subdoc-c.h"
19
20#if !defined(SUBDOC_OPERATIONS_H) && defined(__cplusplus)
21#define SUBDOC_OPERATIONS_H
22#include "subdoc-api.h"
23#include "loc.h"
24#include "path.h"
25#include "match.h"
26
27namespace Subdoc {
28
29/**
30 * This class acts as a user-allocated buffer region for the Operation
31 * object to store results.
32 *
33 * This will be treated as an "out" param
34 */
35class Result {
36public:
37    Result() : m_newlen(0) {}
38    Result(const Result&) = delete;
39    Result& operator=(const Result&) = delete;
40
41    /**
42     * Returns the segments of the new document. Note that the underlying
43     * buffer (the one used in Operation::set_doc()) as well as this object
44     * itself (i.e. the Result object) must both still remain valid for
45     * the returned buffer's contents to be considered valid.
46     * @return a Buffer object representing the layout of the new document.
47     */
48    const Buffer<Loc> newdoc() const {
49        return Buffer<Loc>(m_newdoc, m_newlen);
50    }
51
52    /**
53     * For operations which result in a match returned to the user (e.g.
54     * Command::GET, Command::COUNTER), the result is returned here.
55     *
56     * The returned @ref Loc may refer to regions within the input document
57     * (Operation::set_doc()), and thus should be considered invalid when the
58     * buffer passed to Operation::set_doc() has been modified.
59     *
60     * @return The location of the match.
61     */
62    const Loc& matchloc() const { return m_match; }
63
64    void clear() {
65        m_bkbuf.clear();
66        m_numbuf.clear();
67        m_match.length = 0;
68        m_newlen = 0;
69    }
70private:
71    friend class Operation;
72    std::string m_bkbuf;
73    std::string m_numbuf;
74    Loc m_newdoc[8];
75    size_t m_newlen = 0;
76    Loc m_match;
77};
78
79class Operation {
80public:
81    Operation();
82    void clear();
83    ~Operation();
84    Error op_exec(const char *pth, size_t npth);
85    Error op_exec(const std::string& s) { return op_exec(s.c_str(), s.size()); }
86
87    void set_value(const char *s, size_t n) { m_userval.assign(s, n); }
88    void set_value(const std::string& s) { set_value(s.c_str(), s.size()); }
89    void set_result_buf(Result *res) { m_result = res; }
90    void set_doc(const char *s, size_t n) { m_doc.assign(s, n); }
91    void set_doc(const std::string& s) { set_doc(s.c_str(), s.size()); }
92    void set_code(uint8_t code) { m_optype = code; }
93
94    const Match& match() const { return m_match; }
95    const Path& path() const { return *m_path; }
96    jsonsl_t parser() const { return m_jsn; }
97
98private:
99    /* malloc'd because this block is pretty big (several k) */
100    Path *m_path;
101    /* cached JSON parser */
102    jsonsl_t m_jsn;
103
104    Match m_match;
105
106    /* opcode */
107    Command m_optype;
108
109    /* Location of original document */
110    Loc m_doc;
111
112    /* Location of the user's "Value" (if applicable) */
113    Loc m_userval;
114
115    //! Pointer to result given by user
116    Result *m_result;
117
118    Error do_match_common(Match::SearchOptions options);
119    Error do_get();
120    Error do_store_dict();
121    Error do_remove();
122
123    enum MkdirPMode {
124        MKDIR_P_ARRAY, //!< Insert ... "key": [ value ]
125        MKDIR_P_DICT //!< Insert ... "key":value
126    };
127    Error do_mkdir_p(MkdirPMode mode);
128    Error insert_singleton_element();
129    Error do_list_append();
130    Error do_empty_append();
131    Error do_list_prepend();
132    Error do_arith_op();
133    Error do_insert();
134    Error do_container_size();
135
136    // Wrapper around Validator::validate(), this omits the
137    // passing of arguments we already have (for example, the new object)
138    // and also wraps the error code
139    Error validate(int mode, int depth = -1);
140
141    enum DepthMode {
142        /// Last component of the path is the key for the new item
143        PATH_HAS_NEWKEY,
144        /// Path consists only of parent elements
145        PATH_IS_PARENT
146    };
147    inline int get_maxdepth(DepthMode mode) const;
148
149    //! Equivalent to m_newdoc[n]. This is here so our frequent access
150    //! can occupy less line space.
151    Loc& newdoc_at(size_t n) { return m_result->m_newdoc[n]; }
152};
153}
154
155#endif
156