| /* Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define C_LUCY_BYTEBUF |
| #define C_LUCY_VIEWBYTEBUF |
| #define LUCY_USE_SHORT_NAMES |
| #define CHY_USE_SHORT_NAMES |
| |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <ctype.h> |
| |
| #include "Lucy/Object/VTable.h" |
| #include "Lucy/Object/ByteBuf.h" |
| #include "Lucy/Object/Err.h" |
| #include "Lucy/Store/InStream.h" |
| #include "Lucy/Store/OutStream.h" |
| #include "Lucy/Util/Memory.h" |
| |
| static void |
| S_grow(ByteBuf *self, size_t size); |
| |
| ByteBuf* |
| BB_new(size_t capacity) { |
| ByteBuf *self = (ByteBuf*)VTable_Make_Obj(BYTEBUF); |
| return BB_init(self, capacity); |
| } |
| |
| ByteBuf* |
| BB_init(ByteBuf *self, size_t capacity) { |
| size_t amount = capacity ? capacity : sizeof(int64_t); |
| self->buf = NULL; |
| self->size = 0; |
| self->cap = 0; |
| S_grow(self, amount); |
| return self; |
| } |
| |
| ByteBuf* |
| BB_new_bytes(const void *bytes, size_t size) { |
| ByteBuf *self = (ByteBuf*)VTable_Make_Obj(BYTEBUF); |
| BB_init(self, size); |
| memcpy(self->buf, bytes, size); |
| self->size = size; |
| return self; |
| } |
| |
| ByteBuf* |
| BB_new_steal_bytes(void *bytes, size_t size, size_t capacity) { |
| ByteBuf *self = (ByteBuf*)VTable_Make_Obj(BYTEBUF); |
| self->buf = (char*)bytes; |
| self->size = size; |
| self->cap = capacity; |
| return self; |
| } |
| |
| void |
| BB_destroy(ByteBuf *self) { |
| FREEMEM(self->buf); |
| SUPER_DESTROY(self, BYTEBUF); |
| } |
| |
| ByteBuf* |
| BB_clone(ByteBuf *self) { |
| return BB_new_bytes(self->buf, self->size); |
| } |
| |
| void |
| BB_set_size(ByteBuf *self, size_t size) { |
| if (size > self->cap) { |
| THROW(ERR, "Can't set size to %u64 (greater than capacity of %u64)", |
| (uint64_t)size, (uint64_t)self->cap); |
| } |
| self->size = size; |
| } |
| |
| char* |
| BB_get_buf(ByteBuf *self) { |
| return self->buf; |
| } |
| |
| size_t |
| BB_get_size(ByteBuf *self) { |
| return self->size; |
| } |
| |
| size_t |
| BB_get_capacity(ByteBuf *self) { |
| return self->cap; |
| } |
| |
| static INLINE bool_t |
| SI_equals_bytes(ByteBuf *self, const void *bytes, size_t size) { |
| if (self->size != size) { return false; } |
| return (memcmp(self->buf, bytes, self->size) == 0); |
| } |
| |
| bool_t |
| BB_equals(ByteBuf *self, Obj *other) { |
| ByteBuf *const twin = (ByteBuf*)other; |
| if (twin == self) { return true; } |
| if (!Obj_Is_A(other, BYTEBUF)) { return false; } |
| return SI_equals_bytes(self, twin->buf, twin->size); |
| } |
| |
| bool_t |
| BB_equals_bytes(ByteBuf *self, const void *bytes, size_t size) { |
| return SI_equals_bytes(self, bytes, size); |
| } |
| |
| int32_t |
| BB_hash_sum(ByteBuf *self) { |
| uint32_t sum = 5381; |
| uint8_t *const buf = (uint8_t*)self->buf; |
| |
| for (size_t i = 0, max = self->size; i < max; i++) { |
| sum = ((sum << 5) + sum) ^ buf[i]; |
| } |
| |
| return (int32_t)sum; |
| } |
| |
| static INLINE void |
| SI_mimic_bytes(ByteBuf *self, const void *bytes, size_t size) { |
| if (size > self->cap) { S_grow(self, size); } |
| memmove(self->buf, bytes, size); |
| self->size = size; |
| } |
| |
| void |
| BB_mimic_bytes(ByteBuf *self, const void *bytes, size_t size) { |
| SI_mimic_bytes(self, bytes, size); |
| } |
| |
| void |
| BB_mimic(ByteBuf *self, Obj *other) { |
| ByteBuf *twin = (ByteBuf*)CERTIFY(other, BYTEBUF); |
| SI_mimic_bytes(self, twin->buf, twin->size); |
| } |
| |
| static INLINE void |
| SI_cat_bytes(ByteBuf *self, const void *bytes, size_t size) { |
| const size_t new_size = self->size + size; |
| if (new_size > self->cap) { |
| S_grow(self, Memory_oversize(new_size, sizeof(char))); |
| } |
| memcpy((self->buf + self->size), bytes, size); |
| self->size = new_size; |
| } |
| |
| void |
| BB_cat_bytes(ByteBuf *self, const void *bytes, size_t size) { |
| SI_cat_bytes(self, bytes, size); |
| } |
| |
| void |
| BB_cat(ByteBuf *self, const ByteBuf *other) { |
| SI_cat_bytes(self, other->buf, other->size); |
| } |
| |
| static void |
| S_grow(ByteBuf *self, size_t size) { |
| if (size > self->cap) { |
| size_t amount = size; |
| size_t remainder = amount % sizeof(int64_t); |
| if (remainder) { |
| amount += sizeof(int64_t); |
| amount -= remainder; |
| } |
| self->buf = (char*)REALLOCATE(self->buf, amount); |
| self->cap = amount; |
| } |
| } |
| |
| char* |
| BB_grow(ByteBuf *self, size_t size) { |
| if (size > self->cap) { S_grow(self, size); } |
| return self->buf; |
| } |
| |
| void |
| BB_serialize(ByteBuf *self, OutStream *target) { |
| OutStream_Write_C32(target, self->size); |
| OutStream_Write_Bytes(target, self->buf, self->size); |
| } |
| |
| ByteBuf* |
| BB_deserialize(ByteBuf *self, InStream *instream) { |
| const size_t size = InStream_Read_C32(instream); |
| const size_t capacity = size ? size : sizeof(int64_t); |
| self = self ? self : (ByteBuf*)VTable_Make_Obj(BYTEBUF); |
| if (capacity > self->cap) { S_grow(self, capacity); } |
| self->size = size; |
| InStream_Read_Bytes(instream, self->buf, size); |
| return self; |
| } |
| |
| int |
| BB_compare(const void *va, const void *vb) { |
| const ByteBuf *a = *(const ByteBuf**)va; |
| const ByteBuf *b = *(const ByteBuf**)vb; |
| const size_t size = a->size < b->size ? a->size : b->size; |
| |
| int32_t comparison = memcmp(a->buf, b->buf, size); |
| |
| if (comparison == 0 && a->size != b->size) { |
| comparison = a->size < b->size ? -1 : 1; |
| } |
| |
| return comparison; |
| } |
| |
| int32_t |
| BB_compare_to(ByteBuf *self, Obj *other) { |
| CERTIFY(other, BYTEBUF); |
| return BB_compare(&self, &other); |
| } |
| |
| /******************************************************************/ |
| |
| ViewByteBuf* |
| ViewBB_new(char *buf, size_t size) { |
| ViewByteBuf *self = (ViewByteBuf*)VTable_Make_Obj(VIEWBYTEBUF); |
| return ViewBB_init(self, buf, size); |
| } |
| |
| ViewByteBuf* |
| ViewBB_init(ViewByteBuf *self, char *buf, size_t size) { |
| self->cap = 0; |
| self->buf = buf; |
| self->size = size; |
| return self; |
| } |
| |
| void |
| ViewBB_destroy(ViewByteBuf *self) { |
| Obj_destroy((Obj*)self); |
| } |
| |
| void |
| ViewBB_assign_bytes(ViewByteBuf *self, char*buf, size_t size) { |
| self->buf = buf; |
| self->size = size; |
| } |
| |
| void |
| ViewBB_assign(ViewByteBuf *self, const ByteBuf *other) { |
| self->buf = other->buf; |
| self->size = other->size; |
| } |
| |
| |