Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/third_party/msgpack/src/vrefbuffer.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * MessagePack for C zero-copy buffer implementation
3
 *
4
 * Copyright (C) 2008-2009 FURUHASHI Sadayuki
5
 *
6
 *    Distributed under the Boost Software License, Version 1.0.
7
 *    (See accompanying file LICENSE_1_0.txt or copy at
8
 *    http://www.boost.org/LICENSE_1_0.txt)
9
 */
10
#include "msgpack/vrefbuffer.h"
11
#include <stdlib.h>
12
#include <string.h>
13
14
0
#define MSGPACK_PACKER_MAX_BUFFER_SIZE 9
15
16
struct msgpack_vrefbuffer_chunk {
17
    struct msgpack_vrefbuffer_chunk* next;
18
    /* data ... */
19
};
20
21
bool msgpack_vrefbuffer_init(msgpack_vrefbuffer* vbuf,
22
        size_t ref_size, size_t chunk_size)
23
0
{
24
0
    size_t nfirst;
25
0
    struct iovec* array;
26
0
    msgpack_vrefbuffer_chunk* chunk;
27
0
28
0
    vbuf->chunk_size = chunk_size;
29
0
    vbuf->ref_size =
30
0
        ref_size > MSGPACK_PACKER_MAX_BUFFER_SIZE + 1 ?
31
0
        ref_size : MSGPACK_PACKER_MAX_BUFFER_SIZE + 1 ;
32
0
33
0
    nfirst = (sizeof(struct iovec) < 72/2) ?
34
0
            72 / sizeof(struct iovec) : 8;
35
0
36
0
    array = (struct iovec*)malloc(
37
0
            sizeof(struct iovec) * nfirst);
38
0
    if(array == NULL) {
39
0
        return false;
40
0
    }
41
0
42
0
    vbuf->tail  = array;
43
0
    vbuf->end   = array + nfirst;
44
0
    vbuf->array = array;
45
0
46
0
    chunk = (msgpack_vrefbuffer_chunk*)malloc(
47
0
            sizeof(msgpack_vrefbuffer_chunk) + chunk_size);
48
0
    if(chunk == NULL) {
49
0
        free(array);
50
0
        return false;
51
0
    }
52
0
    else {
53
0
        msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
54
0
55
0
        ib->free = chunk_size;
56
0
        ib->ptr  = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
57
0
        ib->head = chunk;
58
0
        chunk->next = NULL;
59
0
60
0
        return true;
61
0
    }
62
0
}
63
64
void msgpack_vrefbuffer_destroy(msgpack_vrefbuffer* vbuf)
65
0
{
66
0
    msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head;
67
0
    while(true) {
68
0
        msgpack_vrefbuffer_chunk* n = c->next;
69
0
        free(c);
70
0
        if(n != NULL) {
71
0
            c = n;
72
0
        } else {
73
0
            break;
74
0
        }
75
0
    }
76
0
    free(vbuf->array);
77
0
}
78
79
void msgpack_vrefbuffer_clear(msgpack_vrefbuffer* vbuf)
80
0
{
81
0
    msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head->next;
82
0
    msgpack_vrefbuffer_chunk* n;
83
0
    while(c != NULL) {
84
0
        n = c->next;
85
0
        free(c);
86
0
        c = n;
87
0
    }
88
0
89
0
    {
90
0
        msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
91
0
        msgpack_vrefbuffer_chunk* chunk = ib->head;
92
0
        chunk->next = NULL;
93
0
        ib->free = vbuf->chunk_size;
94
0
        ib->ptr  = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
95
0
96
0
        vbuf->tail = vbuf->array;
97
0
    }
98
0
}
99
100
int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf,
101
        const char* buf, size_t len)
102
0
{
103
0
    if(vbuf->tail == vbuf->end) {
104
0
        const size_t nused = (size_t)(vbuf->tail - vbuf->array);
105
0
        const size_t nnext = nused * 2;
106
0
107
0
        struct iovec* nvec = (struct iovec*)realloc(
108
0
                vbuf->array, sizeof(struct iovec)*nnext);
109
0
        if(nvec == NULL) {
110
0
            return -1;
111
0
        }
112
0
113
0
        vbuf->array = nvec;
114
0
        vbuf->end   = nvec + nnext;
115
0
        vbuf->tail  = nvec + nused;
116
0
    }
117
0
118
0
    vbuf->tail->iov_base = (char*)buf;
119
0
    vbuf->tail->iov_len  = len;
120
0
    ++vbuf->tail;
121
0
122
0
    return 0;
123
0
}
124
125
int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf,
126
        const char* buf, size_t len)
127
0
{
128
0
    msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
129
0
    char* m;
130
0
131
0
    if(ib->free < len) {
132
0
        msgpack_vrefbuffer_chunk* chunk;
133
0
        size_t sz = vbuf->chunk_size;
134
0
        if(sz < len) {
135
0
            sz = len;
136
0
        }
137
0
138
0
        chunk = (msgpack_vrefbuffer_chunk*)malloc(
139
0
                sizeof(msgpack_vrefbuffer_chunk) + sz);
140
0
        if(chunk == NULL) {
141
0
            return -1;
142
0
        }
143
0
144
0
        chunk->next = ib->head;
145
0
        ib->head = chunk;
146
0
        ib->free = sz;
147
0
        ib->ptr  = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
148
0
    }
149
0
150
0
    m = ib->ptr;
151
0
    memcpy(m, buf, len);
152
0
    ib->free -= len;
153
0
    ib->ptr  += len;
154
0
155
0
    if(vbuf->tail != vbuf->array && m ==
156
0
            (const char*)((vbuf->tail-1)->iov_base) + (vbuf->tail-1)->iov_len) {
157
0
        (vbuf->tail-1)->iov_len += len;
158
0
        return 0;
159
0
    } else {
160
0
        return msgpack_vrefbuffer_append_ref(vbuf, m, len);
161
0
    }
162
0
}
163
164
int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer* vbuf, msgpack_vrefbuffer* to)
165
0
{
166
0
    size_t sz = vbuf->chunk_size;
167
0
168
0
    msgpack_vrefbuffer_chunk* empty = (msgpack_vrefbuffer_chunk*)malloc(
169
0
            sizeof(msgpack_vrefbuffer_chunk) + sz);
170
0
    if(empty == NULL) {
171
0
        return -1;
172
0
    }
173
0
174
0
    empty->next = NULL;
175
0
176
0
    {
177
0
        const size_t nused = (size_t)(vbuf->tail - vbuf->array);
178
0
        if(to->tail + nused < vbuf->end) {
179
0
            struct iovec* nvec;
180
0
            const size_t tosize = (size_t)(to->tail - to->array);
181
0
            const size_t reqsize = nused + tosize;
182
0
            size_t nnext = (size_t)(to->end - to->array) * 2;
183
0
            while(nnext < reqsize) {
184
0
                size_t tmp_nnext = nnext * 2;
185
0
                if (tmp_nnext <= nnext) {
186
0
                    nnext = reqsize;
187
0
                    break;
188
0
                }
189
0
                nnext = tmp_nnext;
190
0
            }
191
0
192
0
            nvec = (struct iovec*)realloc(
193
0
                    to->array, sizeof(struct iovec)*nnext);
194
0
            if(nvec == NULL) {
195
0
                free(empty);
196
0
                return -1;
197
0
            }
198
0
199
0
            to->array = nvec;
200
0
            to->end   = nvec + nnext;
201
0
            to->tail  = nvec + tosize;
202
0
        }
203
0
204
0
        memcpy(to->tail, vbuf->array, sizeof(struct iovec)*nused);
205
0
206
0
        to->tail += nused;
207
0
        vbuf->tail = vbuf->array;
208
0
209
0
        {
210
0
            msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
211
0
            msgpack_vrefbuffer_inner_buffer* const toib = &to->inner_buffer;
212
0
213
0
            msgpack_vrefbuffer_chunk* last = ib->head;
214
0
            while(last->next != NULL) {
215
0
                last = last->next;
216
0
            }
217
0
            last->next = toib->head;
218
0
            toib->head = ib->head;
219
0
220
0
            if(toib->free < ib->free) {
221
0
                toib->free = ib->free;
222
0
                toib->ptr  = ib->ptr;
223
0
            }
224
0
225
0
            ib->head = empty;
226
0
            ib->free = sz;
227
0
            ib->ptr  = ((char*)empty) + sizeof(msgpack_vrefbuffer_chunk);
228
0
        }
229
0
    }
230
0
231
0
    return 0;
232
0
}