1 
2 /**
3  *    Copyright (C) 2018-present MongoDB, Inc.
4  *
5  *    This program is free software: you can redistribute it and/or modify
6  *    it under the terms of the Server Side Public License, version 1,
7  *    as published by MongoDB, Inc.
8  *
9  *    This program is distributed in the hope that it will be useful,
10  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *    Server Side Public License for more details.
13  *
14  *    You should have received a copy of the Server Side Public License
15  *    along with this program. If not, see
16  *    <http://www.mongodb.com/licensing/server-side-public-license>.
17  *
18  *    As a special exception, the copyright holders give permission to link the
19  *    code of portions of this program with the OpenSSL library under certain
20  *    conditions as described in each individual source file and distribute
21  *    linked combinations including the program with the OpenSSL library. You
22  *    must comply with the Server Side Public License in all respects for
23  *    all of the code used other than as permitted herein. If you modify file(s)
24  *    with this exception, you may extend this exception to your version of the
25  *    file(s), but you are not obligated to do so. If you do not wish to do so,
26  *    delete this exception statement from your version. If you delete this
27  *    exception statement from all source files in the program, then also delete
28  *    it in the license file.
29  */
30 
31 #pragma once
32 
33 #include <cstddef>
34 #include <cstring>
35 #include <limits>
36 
37 #include "mongo/base/data_range.h"
38 #include "mongo/base/data_type.h"
39 #include "mongo/platform/endian.h"
40 #include "mongo/util/mongoutils/str.h"
41 
42 namespace mongo {
43 
44 class ConstDataRangeCursor : public ConstDataRange {
45 public:
46     ConstDataRangeCursor(const char* begin, const char* end, std::ptrdiff_t debug_offset = 0)
ConstDataRange(begin,end,debug_offset)47         : ConstDataRange(begin, end, debug_offset) {}
48 
ConstDataRangeCursor(ConstDataRange cdr)49     ConstDataRangeCursor(ConstDataRange cdr) : ConstDataRange(cdr) {}
50 
advance(size_t advance)51     Status advance(size_t advance) {
52         if (advance > length()) {
53             return makeAdvanceStatus(advance);
54         }
55 
56         _begin += advance;
57         _debug_offset += advance;
58 
59         return Status::OK();
60     }
61 
62     template <typename T>
skip()63     Status skip() {
64         size_t advanced = 0;
65 
66         Status x = DataType::load<T>(nullptr, _begin, _end - _begin, &advanced, _debug_offset);
67 
68         if (x.isOK()) {
69             _begin += advanced;
70             _debug_offset += advanced;
71         }
72 
73         return x;
74     }
75 
76     template <typename T>
readAndAdvance(T * t)77     Status readAndAdvance(T* t) {
78         size_t advanced = 0;
79 
80         Status x = DataType::load(t, _begin, _end - _begin, &advanced, _debug_offset);
81 
82         if (x.isOK()) {
83             _begin += advanced;
84             _debug_offset += advanced;
85         }
86 
87         return x;
88     }
89 
90     template <typename T>
readAndAdvance()91     StatusWith<T> readAndAdvance() {
92         T out(DataType::defaultConstruct<T>());
93         Status x = readAndAdvance(&out);
94 
95         if (x.isOK()) {
96             return StatusWith<T>(std::move(out));
97         } else {
98             return StatusWith<T>(std::move(x));
99         }
100     }
101 
102 private:
103     Status makeAdvanceStatus(size_t advance) const;
104 };
105 
106 class DataRangeCursor : public DataRange {
107 public:
108     DataRangeCursor(char* begin, char* end, std::ptrdiff_t debug_offset = 0)
DataRange(begin,end,debug_offset)109         : DataRange(begin, end, debug_offset) {}
110 
DataRangeCursor(DataRange range)111     DataRangeCursor(DataRange range) : DataRange(range) {}
112 
ConstDataRangeCursor()113     operator ConstDataRangeCursor() const {
114         return ConstDataRangeCursor(ConstDataRange(_begin, _end, _debug_offset));
115     }
116 
advance(size_t advance)117     Status advance(size_t advance) {
118         if (advance > length()) {
119             return makeAdvanceStatus(advance);
120         }
121 
122         _begin += advance;
123         _debug_offset += advance;
124 
125         return Status::OK();
126     }
127 
128     template <typename T>
skip()129     Status skip() {
130         size_t advanced = 0;
131 
132         Status x = DataType::load<T>(nullptr, _begin, _end - _begin, &advanced, _debug_offset);
133 
134         if (x.isOK()) {
135             _begin += advanced;
136             _debug_offset += advanced;
137         }
138 
139         return x;
140     }
141 
142     template <typename T>
readAndAdvance(T * t)143     Status readAndAdvance(T* t) {
144         size_t advanced = 0;
145 
146         Status x = DataType::load(t, _begin, _end - _begin, &advanced, _debug_offset);
147 
148         if (x.isOK()) {
149             _begin += advanced;
150             _debug_offset += advanced;
151         }
152 
153         return x;
154     }
155 
156     template <typename T>
readAndAdvance()157     StatusWith<T> readAndAdvance() {
158         T out(DataType::defaultConstruct<T>());
159         Status x = readAndAdvance(&out);
160 
161         if (x.isOK()) {
162             return StatusWith<T>(std::move(out));
163         } else {
164             return StatusWith<T>(std::move(x));
165         }
166     }
167 
168     template <typename T>
writeAndAdvance(const T & value)169     Status writeAndAdvance(const T& value) {
170         size_t advanced = 0;
171 
172         Status x = DataType::store(
173             value, const_cast<char*>(_begin), _end - _begin, &advanced, _debug_offset);
174 
175         if (x.isOK()) {
176             _begin += advanced;
177             _debug_offset += advanced;
178         }
179 
180         return x;
181     }
182 
183 private:
184     Status makeAdvanceStatus(size_t advance) const;
185 };
186 
187 }  // namespace mongo
188