xref: /6.6.0/subjson/subdoc/loc.h (revision 4e1bf09f)
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_LOC_H) && defined(__cplusplus)
19#define SUBDOC_LOC_H
20
21#include <stddef.h>
22#include <string>
23
24namespace Subdoc {
25/** Structure describing a position and length of a buffer (e.g. IOV) */
26class Loc {
27public:
28    const char *at;
29    size_t length;
30
31    Loc() : at(NULL), length(0) {
32    }
33
34    Loc(const char *s, size_t n) {
35        assign(s, n);
36    }
37
38    enum OverlapMode {
39        NO_OVERLAP = 0,
40        OVERLAP = 1
41    };
42
43    void assign(const char *s, size_t n) { at = s; length = n; }
44
45    /**
46     * Modifies the object so that it ends where `until` begins.
47     *
48     * The object will have a starting position of the base buffer, and will
49     * span until the `until` buffer.
50     *
51     * Example:
52     * @code
53     * BASE     = ABCDEFGHIJ
54     * UNTIL    =      FGH
55     * THIS     = ABCDE
56     * @endcode
57     *
58     * @param base The common buffer
59     * @param until position at where this buffer should end
60     * @param overlap Whether the end should overlap with the first byte of `until`
61     */
62    void end_at_begin(const Loc& base, const Loc& until, OverlapMode overlap)
63    {
64        at = base.at;
65        length = until.at - base.at;
66        if (overlap == OVERLAP) {
67            length++;
68        }
69    }
70
71    /**
72     * Modifies the object so that it begins where `until` ends.
73     *
74     * The buffer will have an end position matching the end of the base buffer,
75     * and will end where `from` ends.
76     *
77     * Example:
78     * @code
79     * BASE     = ABCDEFGHIJ
80     * FROM     =   CDE
81     * THIS     =      FGHIJ
82     * @endcode
83     *
84     * @param base The common buffer
85     * @param from A buffer whose end should be used as the beginning of the
86     *        current buffer
87     * @param overlap Whether the current buffer should overlap `until`'s last
88     *        byte
89     */
90    void begin_at_end(const Loc& base, const Loc& from, OverlapMode overlap)
91    {
92        at = from.at + from.length;
93        length = base.length - (at - base.at);
94        if (overlap == OVERLAP) {
95            at--;
96            length++;
97        }
98    }
99
100    /**
101     * Modifies the object so that it begins where `from` begins.
102     *
103     * The buffer will have an end position matching the end of the base buffer
104     * and will begin where `from` begins
105     *
106     * Example:
107     * @code
108     * BASE     = ABCDEFGHIJ
109     * FROM     =    DEF
110     * THIS     =    DEFGHIJ
111     * @endcode
112     *
113     * @param base Common buffer
114     * @param from The begin position
115     */
116    void begin_at_begin(const Loc& base, const Loc& from)
117    {
118        at = from.at;
119        length = base.length - (from.at - base.at);
120    }
121
122    /**
123     * Modifies the object so that it ends where `until` ends.
124     *
125     * The buffer will have a start position of `base` and an end position of
126     * `until.
127     *
128     * Example
129     * @code
130     * BASE     = ABCDEFGHIJ
131     * UNTIL    =     EFG
132     * THIS     = ABCDEFG
133     * @endcode
134     *
135     * @param base
136     * @param until
137     * @param overlap
138     */
139    void
140    end_at_end(const Loc& base, const Loc& until, OverlapMode overlap)
141    {
142        at = base.at;
143        length = (until.at + until.length) - base.at;
144        if (overlap == NO_OVERLAP) {
145            length--;
146        }
147    }
148
149    bool empty() const { return length == 0; }
150    void clear() { at = NULL; length = 0; }
151
152    std::string to_string() const {
153        if (!empty()) {
154            return std::string(at, length);
155        } else {
156            return std::string();
157        }
158    }
159
160    // Move buffer start ahead n bytes
161    void ltrim(size_t n)
162    {
163        at += n;
164        length -= n;
165    }
166
167    // Move buffer end back n bytes
168    void rtrim(size_t n)
169    {
170        length -= n;
171    }
172};
173
174// similar to boost::buffer
175template <typename T> class Buffer {
176public:
177    Buffer(const T* buf, size_t n) : m_buf(buf), m_size(n) {
178    }
179
180    const T& operator[](size_t ix) const { return m_buf[ix]; }
181    size_t size() const { return m_size; }
182    typedef const T* const_iterator;
183    const_iterator begin() const { return m_buf; }
184    const_iterator end() const { return m_buf + m_size; }
185protected:
186    const T *m_buf;
187    size_t m_size;
188};
189
190} // namespace Subdoc
191#endif
192