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