| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | |||
| 2 | /* GATE PROJECT LICENSE: | ||
| 3 | +----------------------------------------------------------------------------+ | ||
| 4 | | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> | | ||
| 5 | | All rights reserved. | | ||
| 6 | | | | ||
| 7 | | Redistribution and use in source and binary forms, with or without | | ||
| 8 | | modification, are permitted provided that the following conditions are met:| | ||
| 9 | | | | ||
| 10 | | 1. Redistributions of source code must retain the above copyright notice, | | ||
| 11 | | this list of conditions and the following disclaimer. | | ||
| 12 | | 2. Redistributions in binary form must reproduce the above copyright | | ||
| 13 | | notice, this list of conditions and the following disclaimer in the | | ||
| 14 | | documentation and/or other materials provided with the distribution. | | ||
| 15 | | | | ||
| 16 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"| | ||
| 17 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | ||
| 18 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | ||
| 19 | | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | | ||
| 20 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | ||
| 21 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | ||
| 22 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | ||
| 23 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | ||
| 24 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | ||
| 25 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | ||
| 26 | | THE POSSIBILITY OF SUCH DAMAGE. | | ||
| 27 | +----------------------------------------------------------------------------+ | ||
| 28 | */ | ||
| 29 | #include "gate/blobs.h" | ||
| 30 | #include "gate/results.h" | ||
| 31 | #include "gate/memalloc.h" | ||
| 32 | |||
| 33 | 70 | gate_blob_t* gate_blob_create(gate_blob_t* blob, void const* data, gate_size_t length) | |
| 34 | { | ||
| 35 | gate_blobbuffer_t* ptr_buffer; | ||
| 36 | |||
| 37 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 66 times.
|
70 | if (length == 0) |
| 38 | { | ||
| 39 | 4 | return gate_blob_create_empty(blob); | |
| 40 | } | ||
| 41 | |||
| 42 | 66 | ptr_buffer = gate_mem_alloc(sizeof(gate_blobbuffer_t) + length); | |
| 43 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
|
66 | if (ptr_buffer == NULL) |
| 44 | { | ||
| 45 | ✗ | return NULL; | |
| 46 | } | ||
| 47 | 66 | gate_atomic_int_set(&ptr_buffer->refcount, 1); | |
| 48 |
1/2✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
|
66 | if (data) |
| 49 | { | ||
| 50 | 66 | gate_mem_copy(&ptr_buffer->data[0], data, length); | |
| 51 | } | ||
| 52 | 66 | blob->data = &ptr_buffer->data[0]; | |
| 53 | 66 | blob->length = length; | |
| 54 | 66 | blob->buffer = ptr_buffer; | |
| 55 | 66 | return blob; | |
| 56 | } | ||
| 57 | 6 | gate_blob_t* gate_blob_create_static(gate_blob_t* blob, void const* data, gate_size_t length) | |
| 58 | { | ||
| 59 | 6 | blob->data = data; | |
| 60 | 6 | blob->length = length; | |
| 61 | 6 | blob->buffer = NULL; | |
| 62 | 6 | return blob; | |
| 63 | } | ||
| 64 | 154 | gate_blob_t* gate_blob_create_empty(gate_blob_t* blob) | |
| 65 | { | ||
| 66 | 154 | blob->data = NULL; | |
| 67 | 154 | blob->length = 0; | |
| 68 | 154 | blob->buffer = NULL; | |
| 69 | 154 | return blob; | |
| 70 | } | ||
| 71 | 2 | gate_blob_t* gate_blob_create_copy(gate_blob_t* blob, gate_blob_t const* srcblob) | |
| 72 | { | ||
| 73 | 2 | gate_size_t length = gate_blob_length(srcblob); | |
| 74 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (length == 0) |
| 75 | { | ||
| 76 | ✗ | return gate_blob_create_empty(blob); | |
| 77 | } | ||
| 78 | else | ||
| 79 | { | ||
| 80 | 2 | return gate_blob_create(blob, gate_blob_data(srcblob), length); | |
| 81 | } | ||
| 82 | } | ||
| 83 | 6 | gate_blob_t* gate_blob_create_clone(gate_blob_t* blob, gate_blob_t const* srcblob) | |
| 84 | { | ||
| 85 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!srcblob) |
| 86 | { | ||
| 87 | ✗ | return gate_blob_create_empty(blob); | |
| 88 | } | ||
| 89 | else | ||
| 90 | { | ||
| 91 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | if (srcblob->buffer) |
| 92 | { | ||
| 93 | 3 | blob->data = srcblob->data; | |
| 94 | 3 | blob->length = srcblob->length; | |
| 95 | 3 | blob->buffer = srcblob->buffer; | |
| 96 | 3 | gate_atomic_int_inc(&blob->buffer->refcount); | |
| 97 | 3 | return blob; | |
| 98 | } | ||
| 99 | else | ||
| 100 | { | ||
| 101 | 3 | return gate_blob_create(blob, gate_blob_data(srcblob), gate_blob_length(srcblob)); | |
| 102 | } | ||
| 103 | } | ||
| 104 | } | ||
| 105 | 17 | gate_blob_t* gate_blob_create_duplicate(gate_blob_t* blob, gate_blob_t const* srcblob) | |
| 106 | { | ||
| 107 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (!srcblob) |
| 108 | { | ||
| 109 | ✗ | return gate_blob_create_empty(blob); | |
| 110 | } | ||
| 111 | else | ||
| 112 | { | ||
| 113 | 17 | blob->data = srcblob->data; | |
| 114 | 17 | blob->length = srcblob->length; | |
| 115 | 17 | blob->buffer = srcblob->buffer; | |
| 116 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 8 times.
|
17 | if (blob->buffer) |
| 117 | { | ||
| 118 | 9 | gate_atomic_int_inc(&blob->buffer->refcount); | |
| 119 | } | ||
| 120 | 17 | return blob; | |
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | 2 | gate_blob_t* gate_blob_create_subset(gate_blob_t* blob, gate_blob_t const* srcblob, gate_size_t offset, gate_size_t length) | |
| 125 | { | ||
| 126 |
3/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
2 | if (!srcblob || (offset >= srcblob->length) || (length == 0)) |
| 127 | { | ||
| 128 | ✗ | return gate_blob_create_empty(blob); | |
| 129 | } | ||
| 130 | else | ||
| 131 | { | ||
| 132 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (offset + length > srcblob->length) |
| 133 | { | ||
| 134 | ✗ | length = srcblob->length - offset; | |
| 135 | } | ||
| 136 | |||
| 137 | 2 | blob->data = (void const*)((gate_uint8_t const*)srcblob->data + offset); | |
| 138 | 2 | blob->length = length; | |
| 139 | 2 | blob->buffer = srcblob->buffer; | |
| 140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (blob->buffer) |
| 141 | { | ||
| 142 | ✗ | gate_atomic_int_inc(&blob->buffer->refcount); | |
| 143 | } | ||
| 144 | 2 | return blob; | |
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | 132 | void gate_blob_release(gate_blob_t* blob) | |
| 149 | { | ||
| 150 |
1/2✓ Branch 0 taken 132 times.
✗ Branch 1 not taken.
|
132 | if (blob) |
| 151 | { | ||
| 152 |
2/2✓ Branch 0 taken 78 times.
✓ Branch 1 taken 54 times.
|
132 | if (blob->buffer) |
| 153 | { | ||
| 154 |
2/2✓ Branch 1 taken 66 times.
✓ Branch 2 taken 12 times.
|
78 | if (gate_atomic_int_dec(&blob->buffer->refcount) == 0) |
| 155 | { | ||
| 156 | 66 | gate_mem_dealloc(blob->buffer); | |
| 157 | } | ||
| 158 | } | ||
| 159 | 132 | gate_blob_create_empty(blob); | |
| 160 | } | ||
| 161 | 132 | } | |
| 162 | |||
| 163 | 129 | gate_size_t gate_blob_length(gate_blob_t const* blob) | |
| 164 | { | ||
| 165 | 129 | gate_size_t ret = 0; | |
| 166 |
1/2✓ Branch 0 taken 129 times.
✗ Branch 1 not taken.
|
129 | if (blob) |
| 167 | { | ||
| 168 | 129 | ret = blob->length; | |
| 169 | } | ||
| 170 | 129 | return ret; | |
| 171 | } | ||
| 172 | 56 | void const* gate_blob_data(gate_blob_t const* blob) | |
| 173 | { | ||
| 174 | 56 | void const* data = NULL; | |
| 175 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | if (blob) |
| 176 | { | ||
| 177 | 56 | data = blob->data; | |
| 178 | } | ||
| 179 | 56 | return data; | |
| 180 | } | ||
| 181 | 1 | void* gate_blob_databuffer(gate_blob_t* blob) | |
| 182 | { | ||
| 183 | 1 | void* data = NULL; | |
| 184 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | if (blob && blob->buffer) |
| 185 | { | ||
| 186 | 1 | data = &blob->buffer->data[0]; | |
| 187 | } | ||
| 188 | 1 | return data; | |
| 189 | } | ||
| 190 | 29 | gate_uint8_t gate_blob_get_byte(gate_blob_t const* blob, gate_size_t index) | |
| 191 | { | ||
| 192 | 29 | gate_uint8_t ret = 0; | |
| 193 | 29 | gate_size_t const length = gate_blob_length(blob); | |
| 194 | gate_uint8_t const* data; | ||
| 195 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 1 times.
|
29 | if (length != 0) |
| 196 | { | ||
| 197 | 28 | data = (gate_uint8_t const*)blob->data; | |
| 198 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 1 times.
|
28 | if (index < length) |
| 199 | { | ||
| 200 | 27 | ret = data[index]; | |
| 201 | } | ||
| 202 | } | ||
| 203 | 29 | return ret; | |
| 204 | } | ||
| 205 | 5 | gate_result_t gate_blob_set_byte(gate_blob_t* blob, gate_size_t index, gate_uint8_t content) | |
| 206 | { | ||
| 207 | 5 | gate_result_t ret = GATE_RESULT_FAILED; | |
| 208 | 5 | gate_size_t const length = gate_blob_length(blob); | |
| 209 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | if ((length != 0) && (blob->buffer != NULL)) |
| 210 | { | ||
| 211 | 5 | gate_uint8_t* data = (gate_uint8_t*)blob->buffer->data; | |
| 212 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | if (index < length) |
| 213 | { | ||
| 214 | 4 | data[index] = content; | |
| 215 | 4 | ret = GATE_RESULT_OK; | |
| 216 | } | ||
| 217 | else | ||
| 218 | { | ||
| 219 | 1 | ret = GATE_RESULT_OUTOFBOUNDS; | |
| 220 | } | ||
| 221 | } | ||
| 222 | 5 | return ret; | |
| 223 | } | ||
| 224 | 1 | gate_size_t gate_blob_get_bytes(gate_blob_t const* blob, gate_size_t index, void* ptr_dest, gate_size_t dest_length) | |
| 225 | { | ||
| 226 | 1 | gate_size_t length = gate_blob_length(blob); | |
| 227 | gate_uint8_t const* ptr_data; | ||
| 228 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (index >= length) |
| 229 | { | ||
| 230 | ✗ | return 0; | |
| 231 | } | ||
| 232 | |||
| 233 | 1 | length -= index; | |
| 234 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (dest_length < length) |
| 235 | { | ||
| 236 | 1 | length = dest_length; | |
| 237 | } | ||
| 238 | 1 | ptr_data = (gate_uint8_t const*)blob->data; | |
| 239 | 1 | gate_mem_copy(ptr_dest, &ptr_data[index], length); | |
| 240 | 1 | return length; | |
| 241 | } | ||
| 242 | 1 | gate_size_t gate_blob_set_bytes(gate_blob_t* blob, gate_size_t index, void const* ptr_src, gate_size_t src_length) | |
| 243 | { | ||
| 244 | 1 | gate_size_t length = gate_blob_length(blob); | |
| 245 | gate_uint8_t* ptr_data; | ||
| 246 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if ((index >= length) || (!blob->buffer)) |
| 247 | { | ||
| 248 | ✗ | return 0; | |
| 249 | } | ||
| 250 | |||
| 251 | 1 | length -= index; | |
| 252 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (src_length < length) |
| 253 | { | ||
| 254 | 1 | length = src_length; | |
| 255 | } | ||
| 256 | 1 | ptr_data = &blob->buffer->data[0]; | |
| 257 | 1 | gate_mem_copy(&ptr_data[index], ptr_src, length); | |
| 258 | 1 | return length; | |
| 259 | } | ||
| 260 | |||
| 261 | 1 | gate_result_t gate_blob_copy_constructor(void* dest_mem, void const* src_mem) | |
| 262 | { | ||
| 263 | 1 | gate_blob_t* dst = (gate_blob_t*)dest_mem; | |
| 264 | 1 | gate_blob_t const* src = (gate_blob_t const*)src_mem; | |
| 265 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (NULL == gate_blob_create_clone(dst, src)) |
| 266 | { | ||
| 267 | ✗ | return GATE_RESULT_OUTOFMEMORY; | |
| 268 | } | ||
| 269 | else | ||
| 270 | { | ||
| 271 | 1 | return GATE_RESULT_OK; | |
| 272 | } | ||
| 273 | } | ||
| 274 | |||
| 275 | 1 | gate_result_t gate_blob_duplicate_constructor(void* dest_mem, void const* src_mem) | |
| 276 | { | ||
| 277 | 1 | gate_blob_t* dst = (gate_blob_t*)dest_mem; | |
| 278 | 1 | gate_blob_t const* src = (gate_blob_t const*)src_mem; | |
| 279 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (NULL == gate_blob_create_duplicate(dst, src)) |
| 280 | { | ||
| 281 | ✗ | return GATE_RESULT_OUTOFMEMORY; | |
| 282 | } | ||
| 283 | else | ||
| 284 | { | ||
| 285 | 1 | return GATE_RESULT_OK; | |
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | 1 | void gate_blob_destructor(void* dest) | |
| 290 | { | ||
| 291 | 1 | gate_blob_t* dst = (gate_blob_t*)dest; | |
| 292 | 1 | gate_blob_release(dst); | |
| 293 | 1 | } | |
| 294 | |||
| 295 | /***************************** | ||
| 296 | * * | ||
| 297 | * BitField implementation * | ||
| 298 | * * | ||
| 299 | *****************************/ | ||
| 300 | |||
| 301 | 28 | gate_bool_t gate_bit_is_set(void const* data, gate_size_t bitindex) | |
| 302 | { | ||
| 303 | 28 | unsigned char const* ptr = (unsigned char const*)data; | |
| 304 | 28 | gate_size_t byte_index = bitindex / 8; | |
| 305 | 28 | gate_size_t bit_pos = bitindex % 8; | |
| 306 | 28 | return (ptr[byte_index] & (1 << bit_pos)) == 0 ? false : true; | |
| 307 | } | ||
| 308 | 11 | void gate_bit_set(void* data, gate_size_t bitindex) | |
| 309 | { | ||
| 310 | 11 | unsigned char* ptr = (unsigned char*)data; | |
| 311 | 11 | gate_size_t byte_index = bitindex / 8; | |
| 312 | 11 | gate_size_t bit_pos = bitindex % 8; | |
| 313 | |||
| 314 | 11 | ptr[byte_index] |= (unsigned char)(1 << bit_pos); | |
| 315 | 11 | } | |
| 316 | 11 | void gate_bit_clear(void* data, gate_size_t bitindex) | |
| 317 | { | ||
| 318 | 11 | unsigned char* ptr = (unsigned char*)data; | |
| 319 | 11 | gate_size_t byte_index = bitindex / 8; | |
| 320 | 11 | gate_size_t bit_pos = bitindex % 8; | |
| 321 | |||
| 322 | 11 | ptr[byte_index] &= ~(unsigned char)(1 << bit_pos); | |
| 323 | 11 | } | |
| 324 |