| /* |
| * 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. |
| */ |
| #ifndef COMMON_CONTAINER_BYTE_BUFFER_H |
| #define COMMON_CONTAINER_BYTE_BUFFER_H |
| |
| #include <stdint.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "common/allocator/alloc_base.h" |
| #include "common/global.h" |
| #include "utils/util_define.h" |
| |
| namespace common { |
| class ByteBuffer { |
| public: |
| ByteBuffer() |
| : data_(nullptr), |
| variable_type_len_(sizeof(uint32_t)), |
| real_data_size_(0), |
| reserved_size_(0) {} |
| |
| ~ByteBuffer() { |
| if (data_ && (reserved_size_ > 0)) { |
| mem_free(data_); |
| data_ = nullptr; |
| real_data_size_ = 0; |
| reserved_size_ = 0; |
| } |
| } |
| |
| FORCE_INLINE void init(uint32_t size) { |
| data_ = static_cast<char *>(mem_alloc(size, MOD_TSBLOCK)); |
| reserved_size_ = size; |
| } |
| |
| FORCE_INLINE void reset() { real_data_size_ = 0; } |
| |
| FORCE_INLINE void extend_memory(uint32_t new_size) { |
| ASSERT(new_size > reserved_size_); |
| data_ = static_cast<char *>(mem_realloc(data_, new_size)); |
| reserved_size_ = new_size; |
| } |
| |
| FORCE_INLINE void append_variable_value(const char *value, uint32_t len) { |
| // dynamic growth |
| if (UNLIKELY((real_data_size_ + len + variable_type_len_) > |
| reserved_size_)) { |
| // extreme scenarios, when encountering very long string |
| uint32_t growth_size = |
| g_config_value_.tsblock_mem_inc_step_size_ > len |
| ? g_config_value_.tsblock_mem_inc_step_size_ |
| : (len + 1); |
| extend_memory(reserved_size_ + growth_size); |
| } |
| |
| ASSERT(data_); |
| // append len |
| memcpy(&data_[real_data_size_], reinterpret_cast<char *>(&len), |
| variable_type_len_); |
| real_data_size_ += variable_type_len_; |
| if (len > 0) { |
| // append data |
| memcpy(&data_[real_data_size_], value, len); |
| real_data_size_ += len; |
| } |
| } |
| |
| FORCE_INLINE void append_fixed_value(const char *value, uint32_t len) { |
| // dynamic growth |
| if (UNLIKELY(real_data_size_ + len > reserved_size_)) { |
| // extreme scenarios, when encountering very long string |
| uint32_t growth_size = |
| g_config_value_.tsblock_mem_inc_step_size_ > len |
| ? g_config_value_.tsblock_mem_inc_step_size_ |
| : (len + 1); |
| extend_memory(reserved_size_ + growth_size); |
| } |
| |
| ASSERT(data_); |
| memcpy(&data_[real_data_size_], value, len); |
| real_data_size_ += len; |
| } |
| |
| // for fixed len value |
| FORCE_INLINE char *read(uint32_t offset, uint32_t len) { |
| ASSERT((offset + len) <= real_data_size_); |
| char *p = &data_[offset]; |
| return p; |
| } |
| |
| // for variable len value |
| FORCE_INLINE char *read(uint32_t offset, uint32_t *len) { |
| uint32_t tmp; |
| // Directly memcpy to avoid potential alignment issues when casting |
| // int32_t array pointer |
| std::memcpy(&tmp, data_ + offset, sizeof(tmp)); |
| *len = tmp; |
| char *p = &data_[offset + variable_type_len_]; |
| return p; |
| } |
| |
| FORCE_INLINE char *get_data() { return data_; } |
| |
| private: |
| char *data_; |
| uint8_t variable_type_len_; |
| uint32_t real_data_size_; |
| uint32_t reserved_size_; // malloc memory size from system |
| }; |
| |
| } // namespace common |
| #endif // COMMON_CONTAINER_BYTE_BUFFER_H |