MessagePack C implementation for mbed, modified from https://github.com/msgpack/msgpack-c
vrefbuffer.c@2:5237a514fdab, 2014-10-25 (annotated)
- Committer:
- yihui
- Date:
- Sat Oct 25 16:53:10 2014 +0000
- Revision:
- 2:5237a514fdab
- Parent:
- 0:1382f081365b
delete gcc_atomic.h
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
yihui | 0:1382f081365b | 1 | /* |
yihui | 0:1382f081365b | 2 | * MessagePack for C zero-copy buffer implementation |
yihui | 0:1382f081365b | 3 | * |
yihui | 0:1382f081365b | 4 | * Copyright (C) 2008-2009 FURUHASHI Sadayuki |
yihui | 0:1382f081365b | 5 | * |
yihui | 0:1382f081365b | 6 | * Licensed under the Apache License, Version 2.0 (the "License"); |
yihui | 0:1382f081365b | 7 | * you may not use this file except in compliance with the License. |
yihui | 0:1382f081365b | 8 | * You may obtain a copy of the License at |
yihui | 0:1382f081365b | 9 | * |
yihui | 0:1382f081365b | 10 | * http://www.apache.org/licenses/LICENSE-2.0 |
yihui | 0:1382f081365b | 11 | * |
yihui | 0:1382f081365b | 12 | * Unless required by applicable law or agreed to in writing, software |
yihui | 0:1382f081365b | 13 | * distributed under the License is distributed on an "AS IS" BASIS, |
yihui | 0:1382f081365b | 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
yihui | 0:1382f081365b | 15 | * See the License for the specific language governing permissions and |
yihui | 0:1382f081365b | 16 | * limitations under the License. |
yihui | 0:1382f081365b | 17 | */ |
yihui | 0:1382f081365b | 18 | #include "msgpack/vrefbuffer.h" |
yihui | 0:1382f081365b | 19 | #include <stdlib.h> |
yihui | 0:1382f081365b | 20 | #include <string.h> |
yihui | 0:1382f081365b | 21 | |
yihui | 0:1382f081365b | 22 | struct msgpack_vrefbuffer_chunk { |
yihui | 0:1382f081365b | 23 | struct msgpack_vrefbuffer_chunk* next; |
yihui | 0:1382f081365b | 24 | /* data ... */ |
yihui | 0:1382f081365b | 25 | }; |
yihui | 0:1382f081365b | 26 | |
yihui | 0:1382f081365b | 27 | bool msgpack_vrefbuffer_init(msgpack_vrefbuffer* vbuf, |
yihui | 0:1382f081365b | 28 | size_t ref_size, size_t chunk_size) |
yihui | 0:1382f081365b | 29 | { |
yihui | 0:1382f081365b | 30 | vbuf->chunk_size = chunk_size; |
yihui | 0:1382f081365b | 31 | vbuf->ref_size = ref_size; |
yihui | 0:1382f081365b | 32 | |
yihui | 0:1382f081365b | 33 | size_t nfirst = (sizeof(struct iovec) < 72/2) ? |
yihui | 0:1382f081365b | 34 | 72 / sizeof(struct iovec) : 8; |
yihui | 0:1382f081365b | 35 | |
yihui | 0:1382f081365b | 36 | struct iovec* array = (struct iovec*)malloc( |
yihui | 0:1382f081365b | 37 | sizeof(struct iovec) * nfirst); |
yihui | 0:1382f081365b | 38 | if(array == NULL) { |
yihui | 0:1382f081365b | 39 | return false; |
yihui | 0:1382f081365b | 40 | } |
yihui | 0:1382f081365b | 41 | |
yihui | 0:1382f081365b | 42 | vbuf->tail = array; |
yihui | 0:1382f081365b | 43 | vbuf->end = array + nfirst; |
yihui | 0:1382f081365b | 44 | vbuf->array = array; |
yihui | 0:1382f081365b | 45 | |
yihui | 0:1382f081365b | 46 | msgpack_vrefbuffer_chunk* chunk = (msgpack_vrefbuffer_chunk*)malloc( |
yihui | 0:1382f081365b | 47 | sizeof(msgpack_vrefbuffer_chunk) + chunk_size); |
yihui | 0:1382f081365b | 48 | if(chunk == NULL) { |
yihui | 0:1382f081365b | 49 | free(array); |
yihui | 0:1382f081365b | 50 | return false; |
yihui | 0:1382f081365b | 51 | } |
yihui | 0:1382f081365b | 52 | |
yihui | 0:1382f081365b | 53 | msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer; |
yihui | 0:1382f081365b | 54 | |
yihui | 0:1382f081365b | 55 | ib->free = chunk_size; |
yihui | 0:1382f081365b | 56 | ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk); |
yihui | 0:1382f081365b | 57 | ib->head = chunk; |
yihui | 0:1382f081365b | 58 | chunk->next = NULL; |
yihui | 0:1382f081365b | 59 | |
yihui | 0:1382f081365b | 60 | return true; |
yihui | 0:1382f081365b | 61 | } |
yihui | 0:1382f081365b | 62 | |
yihui | 0:1382f081365b | 63 | void msgpack_vrefbuffer_destroy(msgpack_vrefbuffer* vbuf) |
yihui | 0:1382f081365b | 64 | { |
yihui | 0:1382f081365b | 65 | msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head; |
yihui | 0:1382f081365b | 66 | while(true) { |
yihui | 0:1382f081365b | 67 | msgpack_vrefbuffer_chunk* n = c->next; |
yihui | 0:1382f081365b | 68 | free(c); |
yihui | 0:1382f081365b | 69 | if(n != NULL) { |
yihui | 0:1382f081365b | 70 | c = n; |
yihui | 0:1382f081365b | 71 | } else { |
yihui | 0:1382f081365b | 72 | break; |
yihui | 0:1382f081365b | 73 | } |
yihui | 0:1382f081365b | 74 | } |
yihui | 0:1382f081365b | 75 | free(vbuf->array); |
yihui | 0:1382f081365b | 76 | } |
yihui | 0:1382f081365b | 77 | |
yihui | 0:1382f081365b | 78 | void msgpack_vrefbuffer_clear(msgpack_vrefbuffer* vbuf) |
yihui | 0:1382f081365b | 79 | { |
yihui | 0:1382f081365b | 80 | msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head->next; |
yihui | 0:1382f081365b | 81 | msgpack_vrefbuffer_chunk* n; |
yihui | 0:1382f081365b | 82 | while(c != NULL) { |
yihui | 0:1382f081365b | 83 | n = c->next; |
yihui | 0:1382f081365b | 84 | free(c); |
yihui | 0:1382f081365b | 85 | c = n; |
yihui | 0:1382f081365b | 86 | } |
yihui | 0:1382f081365b | 87 | |
yihui | 0:1382f081365b | 88 | msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer; |
yihui | 0:1382f081365b | 89 | msgpack_vrefbuffer_chunk* chunk = ib->head; |
yihui | 0:1382f081365b | 90 | chunk->next = NULL; |
yihui | 0:1382f081365b | 91 | ib->free = vbuf->chunk_size; |
yihui | 0:1382f081365b | 92 | ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk); |
yihui | 0:1382f081365b | 93 | |
yihui | 0:1382f081365b | 94 | vbuf->tail = vbuf->array; |
yihui | 0:1382f081365b | 95 | } |
yihui | 0:1382f081365b | 96 | |
yihui | 0:1382f081365b | 97 | int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf, |
yihui | 0:1382f081365b | 98 | const char* buf, size_t len) |
yihui | 0:1382f081365b | 99 | { |
yihui | 0:1382f081365b | 100 | if(vbuf->tail == vbuf->end) { |
yihui | 0:1382f081365b | 101 | const size_t nused = (size_t)(vbuf->tail - vbuf->array); |
yihui | 0:1382f081365b | 102 | const size_t nnext = nused * 2; |
yihui | 0:1382f081365b | 103 | |
yihui | 0:1382f081365b | 104 | struct iovec* nvec = (struct iovec*)realloc( |
yihui | 0:1382f081365b | 105 | vbuf->array, sizeof(struct iovec)*nnext); |
yihui | 0:1382f081365b | 106 | if(nvec == NULL) { |
yihui | 0:1382f081365b | 107 | return -1; |
yihui | 0:1382f081365b | 108 | } |
yihui | 0:1382f081365b | 109 | |
yihui | 0:1382f081365b | 110 | vbuf->array = nvec; |
yihui | 0:1382f081365b | 111 | vbuf->end = nvec + nnext; |
yihui | 0:1382f081365b | 112 | vbuf->tail = nvec + nused; |
yihui | 0:1382f081365b | 113 | } |
yihui | 0:1382f081365b | 114 | |
yihui | 0:1382f081365b | 115 | vbuf->tail->iov_base = (char*)buf; |
yihui | 0:1382f081365b | 116 | vbuf->tail->iov_len = len; |
yihui | 0:1382f081365b | 117 | ++vbuf->tail; |
yihui | 0:1382f081365b | 118 | |
yihui | 0:1382f081365b | 119 | return 0; |
yihui | 0:1382f081365b | 120 | } |
yihui | 0:1382f081365b | 121 | |
yihui | 0:1382f081365b | 122 | int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf, |
yihui | 0:1382f081365b | 123 | const char* buf, size_t len) |
yihui | 0:1382f081365b | 124 | { |
yihui | 0:1382f081365b | 125 | msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer; |
yihui | 0:1382f081365b | 126 | |
yihui | 0:1382f081365b | 127 | if(ib->free < len) { |
yihui | 0:1382f081365b | 128 | size_t sz = vbuf->chunk_size; |
yihui | 0:1382f081365b | 129 | if(sz < len) { |
yihui | 0:1382f081365b | 130 | sz = len; |
yihui | 0:1382f081365b | 131 | } |
yihui | 0:1382f081365b | 132 | |
yihui | 0:1382f081365b | 133 | msgpack_vrefbuffer_chunk* chunk = (msgpack_vrefbuffer_chunk*)malloc( |
yihui | 0:1382f081365b | 134 | sizeof(msgpack_vrefbuffer_chunk) + sz); |
yihui | 0:1382f081365b | 135 | if(chunk == NULL) { |
yihui | 0:1382f081365b | 136 | return -1; |
yihui | 0:1382f081365b | 137 | } |
yihui | 0:1382f081365b | 138 | |
yihui | 0:1382f081365b | 139 | chunk->next = ib->head; |
yihui | 0:1382f081365b | 140 | ib->head = chunk; |
yihui | 0:1382f081365b | 141 | ib->free = sz; |
yihui | 0:1382f081365b | 142 | ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk); |
yihui | 0:1382f081365b | 143 | } |
yihui | 0:1382f081365b | 144 | |
yihui | 0:1382f081365b | 145 | char* m = ib->ptr; |
yihui | 0:1382f081365b | 146 | memcpy(m, buf, len); |
yihui | 0:1382f081365b | 147 | ib->free -= len; |
yihui | 0:1382f081365b | 148 | ib->ptr += len; |
yihui | 0:1382f081365b | 149 | |
yihui | 0:1382f081365b | 150 | if(vbuf->tail != vbuf->array && m == |
yihui | 0:1382f081365b | 151 | (const char*)((vbuf->tail-1)->iov_base) + (vbuf->tail-1)->iov_len) { |
yihui | 0:1382f081365b | 152 | (vbuf->tail-1)->iov_len += len; |
yihui | 0:1382f081365b | 153 | return 0; |
yihui | 0:1382f081365b | 154 | } else { |
yihui | 0:1382f081365b | 155 | return msgpack_vrefbuffer_append_ref(vbuf, m, len); |
yihui | 0:1382f081365b | 156 | } |
yihui | 0:1382f081365b | 157 | } |
yihui | 0:1382f081365b | 158 | |
yihui | 0:1382f081365b | 159 | int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer* vbuf, msgpack_vrefbuffer* to) |
yihui | 0:1382f081365b | 160 | { |
yihui | 0:1382f081365b | 161 | size_t sz = vbuf->chunk_size; |
yihui | 0:1382f081365b | 162 | |
yihui | 0:1382f081365b | 163 | msgpack_vrefbuffer_chunk* empty = (msgpack_vrefbuffer_chunk*)malloc( |
yihui | 0:1382f081365b | 164 | sizeof(msgpack_vrefbuffer_chunk) + sz); |
yihui | 0:1382f081365b | 165 | if(empty == NULL) { |
yihui | 0:1382f081365b | 166 | return -1; |
yihui | 0:1382f081365b | 167 | } |
yihui | 0:1382f081365b | 168 | |
yihui | 0:1382f081365b | 169 | empty->next = NULL; |
yihui | 0:1382f081365b | 170 | |
yihui | 0:1382f081365b | 171 | |
yihui | 0:1382f081365b | 172 | const size_t nused = (size_t)(vbuf->tail - vbuf->array); |
yihui | 0:1382f081365b | 173 | if(to->tail + nused < vbuf->end) { |
yihui | 0:1382f081365b | 174 | const size_t tosize = (size_t)(to->tail - to->array); |
yihui | 0:1382f081365b | 175 | const size_t reqsize = nused + tosize; |
yihui | 0:1382f081365b | 176 | size_t nnext = (size_t)(to->end - to->array) * 2; |
yihui | 0:1382f081365b | 177 | while(nnext < reqsize) { |
yihui | 0:1382f081365b | 178 | nnext *= 2; |
yihui | 0:1382f081365b | 179 | } |
yihui | 0:1382f081365b | 180 | |
yihui | 0:1382f081365b | 181 | struct iovec* nvec = (struct iovec*)realloc( |
yihui | 0:1382f081365b | 182 | to->array, sizeof(struct iovec)*nnext); |
yihui | 0:1382f081365b | 183 | if(nvec == NULL) { |
yihui | 0:1382f081365b | 184 | free(empty); |
yihui | 0:1382f081365b | 185 | return -1; |
yihui | 0:1382f081365b | 186 | } |
yihui | 0:1382f081365b | 187 | |
yihui | 0:1382f081365b | 188 | to->array = nvec; |
yihui | 0:1382f081365b | 189 | to->end = nvec + nnext; |
yihui | 0:1382f081365b | 190 | to->tail = nvec + tosize; |
yihui | 0:1382f081365b | 191 | } |
yihui | 0:1382f081365b | 192 | |
yihui | 0:1382f081365b | 193 | memcpy(to->tail, vbuf->array, sizeof(struct iovec)*nused); |
yihui | 0:1382f081365b | 194 | |
yihui | 0:1382f081365b | 195 | to->tail += nused; |
yihui | 0:1382f081365b | 196 | vbuf->tail = vbuf->array; |
yihui | 0:1382f081365b | 197 | |
yihui | 0:1382f081365b | 198 | |
yihui | 0:1382f081365b | 199 | msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer; |
yihui | 0:1382f081365b | 200 | msgpack_vrefbuffer_inner_buffer* const toib = &to->inner_buffer; |
yihui | 0:1382f081365b | 201 | |
yihui | 0:1382f081365b | 202 | msgpack_vrefbuffer_chunk* last = ib->head; |
yihui | 0:1382f081365b | 203 | while(last->next != NULL) { |
yihui | 0:1382f081365b | 204 | last = last->next; |
yihui | 0:1382f081365b | 205 | } |
yihui | 0:1382f081365b | 206 | last->next = toib->head; |
yihui | 0:1382f081365b | 207 | toib->head = ib->head; |
yihui | 0:1382f081365b | 208 | |
yihui | 0:1382f081365b | 209 | if(toib->free < ib->free) { |
yihui | 0:1382f081365b | 210 | toib->free = ib->free; |
yihui | 0:1382f081365b | 211 | toib->ptr = ib->ptr; |
yihui | 0:1382f081365b | 212 | } |
yihui | 0:1382f081365b | 213 | |
yihui | 0:1382f081365b | 214 | ib->head = empty; |
yihui | 0:1382f081365b | 215 | ib->free = sz; |
yihui | 0:1382f081365b | 216 | ib->ptr = ((char*)empty) + sizeof(msgpack_vrefbuffer_chunk); |
yihui | 0:1382f081365b | 217 | |
yihui | 0:1382f081365b | 218 | return 0; |
yihui | 0:1382f081365b | 219 | } |
yihui | 0:1382f081365b | 220 |