File Coverage

bson/bson-writer.c
Criterion Covered Total %
statement 0 60 0.0
branch 0 22 0.0
condition n/a
subroutine n/a
pod n/a
total 0 82 0.0


line stmt bran cond sub pod time code
1             /*
2             * Copyright 2013 MongoDB, Inc.
3             *
4             * Licensed under the Apache License, Version 2.0 (the "License");
5             * you may not use this file except in compliance with the License.
6             * You may obtain a copy of the License at
7             *
8             * http://www.apache.org/licenses/LICENSE-2.0
9             *
10             * Unless required by applicable law or agreed to in writing, software
11             * distributed under the License is distributed on an "AS IS" BASIS,
12             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13             * See the License for the specific language governing permissions and
14             * limitations under the License.
15             */
16              
17              
18             #include "bson-private.h"
19             #include "bson-writer.h"
20              
21              
22             struct _bson_writer_t
23             {
24             bool ready;
25             uint8_t **buf;
26             size_t *buflen;
27             size_t offset;
28             bson_realloc_func realloc_func;
29             void *realloc_func_ctx;
30             bson_t b;
31             };
32              
33              
34             /*
35             *--------------------------------------------------------------------------
36             *
37             * bson_writer_new --
38             *
39             * Creates a new instance of bson_writer_t using the buffer, length,
40             * offset, and realloc() function supplied.
41             *
42             * The caller is expected to clean up the structure when finished
43             * using bson_writer_destroy().
44             *
45             * Parameters:
46             * @buf: (inout): A pointer to a target buffer.
47             * @buflen: (inout): A pointer to the buffer length.
48             * @offset: The offset in the target buffer to start from.
49             * @realloc_func: A realloc() style function or NULL.
50             *
51             * Returns:
52             * A newly allocated bson_writer_t that should be freed with
53             * bson_writer_destroy().
54             *
55             * Side effects:
56             * None.
57             *
58             *--------------------------------------------------------------------------
59             */
60              
61             bson_writer_t *
62 0           bson_writer_new (uint8_t **buf, /* IN */
63             size_t *buflen, /* IN */
64             size_t offset, /* IN */
65             bson_realloc_func realloc_func, /* IN */
66             void *realloc_func_ctx) /* IN */
67             {
68             bson_writer_t *writer;
69              
70 0           writer = bson_malloc0 (sizeof *writer);
71 0           writer->buf = buf;
72 0           writer->buflen = buflen;
73 0           writer->offset = offset;
74 0           writer->realloc_func = realloc_func;
75 0           writer->realloc_func_ctx = realloc_func_ctx;
76 0           writer->ready = true;
77              
78 0           return writer;
79             }
80              
81              
82             /*
83             *--------------------------------------------------------------------------
84             *
85             * bson_writer_destroy --
86             *
87             * Cleanup after @writer and release any allocated memory. Note that
88             * the buffer supplied to bson_writer_new() is NOT freed from this
89             * method. The caller is responsible for that.
90             *
91             * Returns:
92             * None.
93             *
94             * Side effects:
95             * None.
96             *
97             *--------------------------------------------------------------------------
98             */
99              
100             void
101 0           bson_writer_destroy (bson_writer_t *writer) /* IN */
102             {
103 0           bson_free (writer);
104 0           }
105              
106              
107             /*
108             *--------------------------------------------------------------------------
109             *
110             * bson_writer_get_length --
111             *
112             * Fetches the current length of the content written by the buffer
113             * (including the initial offset). This includes a partly written
114             * document currently being written.
115             *
116             * This is useful if you want to check to see if you've passed a given
117             * memory boundry that cannot be sent in a packet. See
118             * bson_writer_rollback() to abort the current document being written.
119             *
120             * Returns:
121             * The number of bytes written plus initial offset.
122             *
123             * Side effects:
124             * None.
125             *
126             *--------------------------------------------------------------------------
127             */
128              
129             size_t
130 0           bson_writer_get_length (bson_writer_t *writer) /* IN */
131             {
132 0           return writer->offset + writer->b.len;
133             }
134              
135              
136             /*
137             *--------------------------------------------------------------------------
138             *
139             * bson_writer_begin --
140             *
141             * Begins writing a new document. The caller may use the bson
142             * structure to write out a new BSON document. When completed, the
143             * caller must call either bson_writer_end() or
144             * bson_writer_rollback().
145             *
146             * Parameters:
147             * @writer: A bson_writer_t.
148             * @bson: (out): A location for a bson_t*.
149             *
150             * Returns:
151             * true if the underlying realloc was successful; otherwise false.
152             *
153             * Side effects:
154             * @bson is initialized if true is returned.
155             *
156             *--------------------------------------------------------------------------
157             */
158              
159             bool
160 0           bson_writer_begin (bson_writer_t *writer, /* IN */
161             bson_t **bson) /* OUT */
162             {
163             bson_impl_alloc_t *b;
164 0           bool grown = false;
165              
166 0 0         BSON_ASSERT (writer);
167 0 0         BSON_ASSERT (writer->ready);
168 0 0         BSON_ASSERT (bson);
169              
170 0           writer->ready = false;
171              
172 0           memset (&writer->b, 0, sizeof (bson_t));
173              
174 0           b = (bson_impl_alloc_t *)&writer->b;
175 0           b->flags = BSON_FLAG_STATIC | BSON_FLAG_NO_FREE;
176 0           b->len = 5;
177 0           b->parent = NULL;
178 0           b->buf = writer->buf;
179 0           b->buflen = writer->buflen;
180 0           b->offset = writer->offset;
181 0           b->alloc = NULL;
182 0           b->alloclen = 0;
183 0           b->realloc = writer->realloc_func;
184 0           b->realloc_func_ctx = writer->realloc_func_ctx;
185              
186 0 0         while ((writer->offset + writer->b.len) > *writer->buflen) {
187 0 0         if (!writer->realloc_func) {
188 0           memset (&writer->b, 0, sizeof (bson_t));
189 0           writer->ready = true;
190 0           return false;
191             }
192 0           grown = true;
193              
194 0 0         if (!*writer->buflen) {
195 0           *writer->buflen = 64;
196             } else {
197 0           (*writer->buflen) *= 2;
198             }
199             }
200              
201 0 0         if (grown) {
202 0           *writer->buf = writer->realloc_func (*writer->buf, *writer->buflen, writer->realloc_func_ctx);
203             }
204              
205 0           memset ((*writer->buf) + writer->offset + 1, 0, 5);
206 0           (*writer->buf)[writer->offset] = 5;
207              
208 0           *bson = &writer->b;
209              
210 0           return true;
211             }
212              
213              
214             /*
215             *--------------------------------------------------------------------------
216             *
217             * bson_writer_end --
218             *
219             * Complete writing of a bson_writer_t to the buffer supplied.
220             *
221             * Returns:
222             * None.
223             *
224             * Side effects:
225             * None.
226             *
227             *--------------------------------------------------------------------------
228             */
229              
230             void
231 0           bson_writer_end (bson_writer_t *writer) /* IN */
232             {
233 0 0         BSON_ASSERT (writer);
234 0 0         BSON_ASSERT (!writer->ready);
235              
236 0           writer->offset += writer->b.len;
237 0           memset (&writer->b, 0, sizeof (bson_t));
238 0           writer->ready = true;
239 0           }
240              
241              
242             /*
243             *--------------------------------------------------------------------------
244             *
245             * bson_writer_rollback --
246             *
247             * Abort the appending of the current bson_t to the memory region
248             * managed by @writer. This is useful if you detected that you went
249             * past a particular memory limit. For example, MongoDB has 48MB
250             * message limits.
251             *
252             * Returns:
253             * None.
254             *
255             * Side effects:
256             * None.
257             *
258             *--------------------------------------------------------------------------
259             */
260              
261             void
262 0           bson_writer_rollback (bson_writer_t *writer) /* IN */
263             {
264 0 0         BSON_ASSERT (writer);
265              
266 0 0         if (writer->b.len) {
267 0           memset (&writer->b, 0, sizeof (bson_t));
268             }
269              
270 0           writer->ready = true;
271 0           }