]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/third-party/fbson/FbsonStream.h
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / rocksdb / third-party / fbson / FbsonStream.h
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 */
10
11 /*
12 * This header file defines FbsonInBuffer and FbsonOutStream classes.
13 *
14 * ** Input Buffer **
15 * FbsonInBuffer is a customer input buffer to wrap raw character buffer. Its
16 * object instances are used to create std::istream objects interally.
17 *
18 * ** Output Stream **
19 * FbsonOutStream is a custom output stream classes, to contain the FBSON
20 * serialized binary. The class is conveniently used to specialize templates of
21 * FbsonParser and FbsonWriter.
22 *
23 * @author Tian Xia <tianx@fb.com>
24 */
25
26 #ifndef FBSON_FBSONSTREAM_H
27 #define FBSON_FBSONSTREAM_H
28
29 #ifndef __STDC_FORMAT_MACROS
30 #define __STDC_FORMAT_MACROS
31 #endif
32
33 #if defined OS_WIN && !defined snprintf
34 #define snprintf _snprintf
35 #endif
36
37 #include <inttypes.h>
38 #include <iostream>
39
40 namespace fbson {
41
42 // lengths includes sign
43 #define MAX_INT_DIGITS 11
44 #define MAX_INT64_DIGITS 20
45 #define MAX_DOUBLE_DIGITS 23 // 1(sign)+16(significant)+1(decimal)+5(exponent)
46
47 /*
48 * FBSON's implementation of input buffer
49 */
50 class FbsonInBuffer : public std::streambuf {
51 public:
52 FbsonInBuffer(const char* str, uint32_t len) {
53 // this is read buffer and the str will not be changed
54 // so we use const_cast (ugly!) to remove constness
55 char* pch(const_cast<char*>(str));
56 setg(pch, pch, pch + len);
57 }
58 };
59
60 /*
61 * FBSON's implementation of output stream.
62 *
63 * This is a wrapper of a char buffer. By default, the buffer capacity is 1024
64 * bytes. We will double the buffer if realloc is needed for writes.
65 */
66 class FbsonOutStream : public std::ostream {
67 public:
68 explicit FbsonOutStream(uint32_t capacity = 1024)
69 : std::ostream(nullptr),
70 head_(nullptr),
71 size_(0),
72 capacity_(capacity),
73 alloc_(true) {
74 if (capacity_ == 0) {
75 capacity_ = 1024;
76 }
77
78 head_ = (char*)malloc(capacity_);
79 }
80
81 FbsonOutStream(char* buffer, uint32_t capacity)
82 : std::ostream(nullptr),
83 head_(buffer),
84 size_(0),
85 capacity_(capacity),
86 alloc_(false) {
87 assert(buffer && capacity_ > 0);
88 }
89
90 ~FbsonOutStream() {
91 if (alloc_) {
92 free(head_);
93 }
94 }
95
96 void put(char c) { write(&c, 1); }
97
98 void write(const char* c_str) { write(c_str, (uint32_t)strlen(c_str)); }
99
100 void write(const char* bytes, uint32_t len) {
101 if (len == 0)
102 return;
103
104 if (size_ + len > capacity_) {
105 realloc(len);
106 }
107
108 memcpy(head_ + size_, bytes, len);
109 size_ += len;
110 }
111
112 // write the integer to string
113 void write(int i) {
114 // snprintf automatically adds a NULL, so we need one more char
115 if (size_ + MAX_INT_DIGITS + 1 > capacity_) {
116 realloc(MAX_INT_DIGITS + 1);
117 }
118
119 int len = snprintf(head_ + size_, MAX_INT_DIGITS + 1, "%d", i);
120 assert(len > 0);
121 size_ += len;
122 }
123
124 // write the 64bit integer to string
125 void write(int64_t l) {
126 // snprintf automatically adds a NULL, so we need one more char
127 if (size_ + MAX_INT64_DIGITS + 1 > capacity_) {
128 realloc(MAX_INT64_DIGITS + 1);
129 }
130
131 int len = snprintf(head_ + size_, MAX_INT64_DIGITS + 1, "%" PRIi64, l);
132 assert(len > 0);
133 size_ += len;
134 }
135
136 // write the double to string
137 void write(double d) {
138 // snprintf automatically adds a NULL, so we need one more char
139 if (size_ + MAX_DOUBLE_DIGITS + 1 > capacity_) {
140 realloc(MAX_DOUBLE_DIGITS + 1);
141 }
142
143 int len = snprintf(head_ + size_, MAX_DOUBLE_DIGITS + 1, "%.15g", d);
144 assert(len > 0);
145 size_ += len;
146 }
147
148 pos_type tellp() const { return size_; }
149
150 void seekp(pos_type pos) { size_ = (uint32_t)pos; }
151
152 const char* getBuffer() const { return head_; }
153
154 pos_type getSize() const { return tellp(); }
155
156 private:
157 void realloc(uint32_t len) {
158 assert(capacity_ > 0);
159
160 capacity_ *= 2;
161 while (capacity_ < size_ + len) {
162 capacity_ *= 2;
163 }
164
165 if (alloc_) {
166 char* new_buf = (char*)::realloc(head_, capacity_);
167 assert(new_buf);
168 head_ = new_buf;
169 } else {
170 char* new_buf = (char*)::malloc(capacity_);
171 assert(new_buf);
172 memcpy(new_buf, head_, size_);
173 head_ = new_buf;
174 alloc_ = true;
175 }
176 }
177
178 private:
179 char* head_;
180 uint32_t size_;
181 uint32_t capacity_;
182 bool alloc_;
183 };
184
185 } // namespace fbson
186
187 #endif // FBSON_FBSONSTREAM_H