| /* |
| * 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. |
| */ |
| |
| #include "paimon/common/memory/memory_slice_output.h" |
| |
| #include "fmt/format.h" |
| #include "paimon/common/utils/math.h" |
| #include "paimon/common/utils/var_length_int_utils.h" |
| namespace paimon { |
| |
| MemorySliceOutput::MemorySliceOutput(int32_t estimated_size, MemoryPool* pool) { |
| size_ = 0; |
| pool_ = pool; |
| segment_ = MemorySegment::Wrap(Bytes::AllocateBytes(estimated_size, pool)); |
| } |
| |
| int32_t MemorySliceOutput::Size() const { |
| return size_; |
| } |
| |
| void MemorySliceOutput::Reset() { |
| size_ = 0; |
| } |
| |
| MemorySlice MemorySliceOutput::ToSlice() { |
| return MemorySlice(segment_, 0, size_); |
| } |
| |
| template <typename T> |
| void MemorySliceOutput::WriteValue(T value) { |
| int32_t write_length = sizeof(T); |
| EnsureSize(size_ + write_length); |
| T write_value = value; |
| if (NeedSwap()) { |
| write_value = EndianSwapValue(value); |
| } |
| segment_.PutValue(size_, write_value); |
| size_ += write_length; |
| } |
| |
| Status MemorySliceOutput::WriteVarLenInt(int32_t value) { |
| EnsureSize(size_ + VarLengthIntUtils::kMaxVarIntSize); |
| PAIMON_ASSIGN_OR_RAISE(int32_t bytes_written, |
| VarLengthIntUtils::EncodeInt(value, segment_.MutableData() + size_)); |
| size_ += bytes_written; |
| return Status::OK(); |
| } |
| |
| Status MemorySliceOutput::WriteVarLenLong(int64_t value) { |
| EnsureSize(size_ + VarLengthIntUtils::kMaxVarLongSize); |
| PAIMON_ASSIGN_OR_RAISE(int32_t bytes_written, |
| VarLengthIntUtils::EncodeLong(value, segment_.MutableData() + size_)); |
| size_ += bytes_written; |
| return Status::OK(); |
| } |
| |
| void MemorySliceOutput::WriteBytes(const std::shared_ptr<Bytes>& source) { |
| WriteBytes(source, 0, source->size()); |
| } |
| |
| void MemorySliceOutput::WriteBytes(const std::shared_ptr<Bytes>& source, int32_t source_index, |
| int32_t length) { |
| EnsureSize(size_ + length); |
| std::string_view sv{source->data(), source->size()}; |
| segment_.Put(size_, sv, source_index, length); |
| size_ += length; |
| } |
| |
| void MemorySliceOutput::SetOrder(ByteOrder order) { |
| byte_order_ = order; |
| } |
| |
| bool MemorySliceOutput::NeedSwap() const { |
| return SystemByteOrder() != byte_order_; |
| } |
| |
| void MemorySliceOutput::EnsureSize(int32_t size) { |
| if (size <= segment_.Size()) { |
| return; |
| } |
| int32_t capacity = segment_.Size(); |
| int32_t min_capacity = segment_.Size() + size; |
| while (capacity < min_capacity) { |
| // capacity is always a power-of-two and <= INT32_MAX/2 in practice, |
| // so this shift does not overflow. |
| capacity <<= 1; |
| } |
| |
| auto bytes = std::make_shared<Bytes>(capacity, pool_); |
| MemorySegment new_segment = MemorySegment::Wrap(bytes); |
| |
| segment_.CopyTo(0, &new_segment, 0, segment_.Size()); |
| segment_ = new_segment; |
| } |
| |
| template void MemorySliceOutput::WriteValue(bool); |
| template void MemorySliceOutput::WriteValue(char); |
| template void MemorySliceOutput::WriteValue(int8_t); |
| template void MemorySliceOutput::WriteValue(int16_t); |
| template void MemorySliceOutput::WriteValue(int32_t); |
| template void MemorySliceOutput::WriteValue(int64_t); |
| |
| } // namespace paimon |