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