/Users/deen/code/yugabyte-db/src/yb/rocksdb/third-party/fbson/FbsonStream.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2011-present, Facebook, Inc. |
3 | | * All rights reserved. |
4 | | * |
5 | | * This source code is licensed under the BSD-style license found in the |
6 | | * LICENSE file in the root directory of this source tree. An additional grant |
7 | | * of patent rights can be found in the PATENTS file in the same directory. |
8 | | * |
9 | | * The following only applies to changes made to this file as part of YugaByte development. |
10 | | * |
11 | | * Portions Copyright (c) YugaByte, Inc. |
12 | | * |
13 | | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
14 | | * in compliance with the License. You may obtain a copy of the License at |
15 | | * |
16 | | * http://www.apache.org/licenses/LICENSE-2.0 |
17 | | * |
18 | | * Unless required by applicable law or agreed to in writing, software distributed under the License |
19 | | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
20 | | * or implied. See the License for the specific language governing permissions and limitations |
21 | | * under the License. |
22 | | * |
23 | | * |
24 | | */ |
25 | | |
26 | | /* |
27 | | * This header file defines FbsonInBuffer and FbsonOutStream classes. |
28 | | * |
29 | | * ** Input Buffer ** |
30 | | * FbsonInBuffer is a customer input buffer to wrap raw character buffer. Its |
31 | | * object instances are used to create std::istream objects interally. |
32 | | * |
33 | | * ** Output Stream ** |
34 | | * FbsonOutStream is a custom output stream classes, to contain the FBSON |
35 | | * serialized binary. The class is conveniently used to specialize templates of |
36 | | * FbsonParser and FbsonWriter. |
37 | | * |
38 | | * @author Tian Xia <tianx@fb.com> |
39 | | */ |
40 | | |
41 | | #ifndef FBSON_FBSONSTREAM_H |
42 | | #define FBSON_FBSONSTREAM_H |
43 | | |
44 | | #ifndef __STDC_FORMAT_MACROS |
45 | | #define __STDC_FORMAT_MACROS |
46 | | #endif |
47 | | |
48 | | #if defined OS_WIN && !defined snprintf |
49 | | #define snprintf _snprintf |
50 | | #endif |
51 | | |
52 | | #include <inttypes.h> |
53 | | #include <iostream> |
54 | | |
55 | | namespace fbson { |
56 | | |
57 | | // lengths includes sign |
58 | 0 | #define MAX_INT_DIGITS 11 |
59 | 0 | #define MAX_INT64_DIGITS 20 |
60 | 0 | #define MAX_DOUBLE_DIGITS 23 // 1(sign)+16(significant)+1(decimal)+5(exponent) |
61 | | |
62 | | /* |
63 | | * FBSON's implementation of input buffer |
64 | | */ |
65 | | class FbsonInBuffer : public std::streambuf { |
66 | | public: |
67 | 54 | FbsonInBuffer(const char* str, uint32_t len) { |
68 | | // this is read buffer and the str will not be changed |
69 | | // so we use const_cast (ugly!) to remove constness |
70 | 54 | char* pch(const_cast<char*>(str)); |
71 | 54 | setg(pch, pch, pch + len); |
72 | 54 | } |
73 | | }; |
74 | | |
75 | | /* |
76 | | * FBSON's implementation of output stream. |
77 | | * |
78 | | * This is a wrapper of a char buffer. By default, the buffer capacity is 1024 |
79 | | * bytes. We will double the buffer if realloc is needed for writes. |
80 | | */ |
81 | | class FbsonOutStream : public std::ostream { |
82 | | public: |
83 | | explicit FbsonOutStream(uint32_t capacity = 1024) |
84 | | : std::ostream(nullptr), |
85 | | head_(nullptr), |
86 | | size_(0), |
87 | | capacity_(capacity), |
88 | 146 | alloc_(true) { |
89 | 146 | if (capacity_ == 0) { |
90 | 0 | capacity_ = 1024; |
91 | 0 | } |
92 | | |
93 | 146 | head_ = (char*)malloc(capacity_); |
94 | 146 | } |
95 | | |
96 | | FbsonOutStream(char* buffer, uint32_t capacity) |
97 | | : std::ostream(nullptr), |
98 | | head_(buffer), |
99 | | size_(0), |
100 | | capacity_(capacity), |
101 | 0 | alloc_(false) { |
102 | 0 | assert(buffer && capacity_ > 0); |
103 | 0 | } Unexecuted instantiation: fbson::FbsonOutStream::FbsonOutStream(char*, unsigned int) Unexecuted instantiation: fbson::FbsonOutStream::FbsonOutStream(char*, unsigned int) |
104 | | |
105 | 146 | ~FbsonOutStream() { |
106 | 146 | if (alloc_) { |
107 | 146 | free(head_); |
108 | 146 | } |
109 | 146 | } |
110 | | |
111 | 1.04k | void put(char c) { write(&c, 1); } |
112 | | |
113 | 0 | void write(const char* c_str) { write(c_str, (uint32_t)strlen(c_str)); } |
114 | | |
115 | 2.11k | void write(const char* bytes, uint32_t len) { |
116 | 2.11k | if (len == 0) |
117 | 1 | return; |
118 | | |
119 | 2.11k | if (size_ + len > capacity_) { |
120 | 0 | realloc(len); |
121 | 0 | } |
122 | | |
123 | 2.11k | memcpy(head_ + size_, bytes, len); |
124 | 2.11k | size_ += len; |
125 | 2.11k | } |
126 | | |
127 | | // write the integer to string |
128 | 0 | void write(int i) { |
129 | | // snprintf automatically adds a NULL, so we need one more char |
130 | 0 | if (size_ + MAX_INT_DIGITS + 1 > capacity_) { |
131 | 0 | realloc(MAX_INT_DIGITS + 1); |
132 | 0 | } |
133 | |
|
134 | 0 | int len = snprintf(head_ + size_, MAX_INT_DIGITS + 1, "%d", i); |
135 | 0 | assert(len > 0); |
136 | 0 | size_ += len; |
137 | 0 | } |
138 | | |
139 | | // write the 64bit integer to string |
140 | 0 | void write(int64_t l) { |
141 | | // snprintf automatically adds a NULL, so we need one more char |
142 | 0 | if (size_ + MAX_INT64_DIGITS + 1 > capacity_) { |
143 | 0 | realloc(MAX_INT64_DIGITS + 1); |
144 | 0 | } |
145 | |
|
146 | 0 | int len = snprintf(head_ + size_, MAX_INT64_DIGITS + 1, "%" PRIi64, l); |
147 | 0 | assert(len > 0); |
148 | 0 | size_ += len; |
149 | 0 | } |
150 | | |
151 | | // write the double to string |
152 | 0 | void write(double d) { |
153 | | // snprintf automatically adds a NULL, so we need one more char |
154 | 0 | if (size_ + MAX_DOUBLE_DIGITS + 1 > capacity_) { |
155 | 0 | realloc(MAX_DOUBLE_DIGITS + 1); |
156 | 0 | } |
157 | |
|
158 | 0 | int len = snprintf(head_ + size_, MAX_DOUBLE_DIGITS + 1, "%.15g", d); |
159 | 0 | assert(len > 0); |
160 | 0 | size_ += len; |
161 | 0 | } |
162 | | |
163 | 865 | pos_type tellp() const { return size_; } |
164 | | |
165 | 692 | void seekp(pos_type pos) { size_ = (uint32_t)pos; } |
166 | | |
167 | 155 | const char* getBuffer() const { return head_; } |
168 | | |
169 | 236 | pos_type getSize() const { return tellp(); } |
170 | | |
171 | | private: |
172 | 0 | void realloc(uint32_t len) { |
173 | 0 | assert(capacity_ > 0); |
174 | | |
175 | 0 | capacity_ *= 2; |
176 | 0 | while (capacity_ < size_ + len) { |
177 | 0 | capacity_ *= 2; |
178 | 0 | } |
179 | |
|
180 | 0 | if (alloc_) { |
181 | 0 | char* new_buf = (char*)::realloc(head_, capacity_); |
182 | 0 | assert(new_buf); |
183 | 0 | head_ = new_buf; |
184 | 0 | } else { |
185 | 0 | char* new_buf = (char*)::malloc(capacity_); |
186 | 0 | assert(new_buf); |
187 | 0 | memcpy(new_buf, head_, size_); |
188 | 0 | head_ = new_buf; |
189 | 0 | alloc_ = true; |
190 | 0 | } |
191 | 0 | } |
192 | | |
193 | | private: |
194 | | char* head_; |
195 | | uint32_t size_; |
196 | | uint32_t capacity_; |
197 | | bool alloc_; |
198 | | }; |
199 | | |
200 | | } // namespace fbson |
201 | | |
202 | | #endif // FBSON_FBSONSTREAM_H |