blob: 5ee7a1a68655420ddb365957d188b77dcd443f88 [file]
/*
* 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.
*/
#pragma once
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "fury/row/row.h"
#include "fury/util/bit_util.h"
#include "fury/util/buffer.h"
#include "fury/util/logging.h"
namespace fury {
class Writer {
public:
std::shared_ptr<Buffer> &buffer() { return buffer_; }
inline uint32_t cursor() const { return buffer_->writer_index(); }
inline uint32_t size() const {
return buffer_->writer_index() - starting_offset_;
}
inline uint32_t starting_offset() const { return starting_offset_; }
inline std::vector<Writer *> &children() { return children_; }
inline void IncreaseCursor(uint32_t val) {
buffer_->IncreaseWriterIndex(val);
}
inline void Grow(uint32_t needed_size) { buffer_->Grow(needed_size); }
virtual int GetOffset(int i) const = 0;
void SetOffsetAndSize(int i, uint32_t size) {
SetOffsetAndSize(i, buffer_->writer_index(), size);
}
void SetOffsetAndSize(int i, uint32_t absolute_offset, uint32_t size);
void ZeroOutPaddingBytes(uint32_t num_bytes);
void SetNullAt(int i) {
util::SetBit(buffer_->data() + starting_offset_ + bytes_before_bitmap_, i);
}
void SetNotNullAt(int i) {
util::ClearBit(buffer_->data() + starting_offset_ + bytes_before_bitmap_,
i);
}
bool IsNullAt(int i) const;
virtual void Write(int i, int8_t value) = 0;
virtual void Write(int i, bool value) = 0;
virtual void Write(int i, int16_t value) = 0;
virtual void Write(int i, int32_t value) = 0;
virtual void Write(int i, float value) = 0;
virtual void Write(int i, int64_t value) = 0;
virtual void Write(int i, double value) = 0;
void WriteLong(int i, int64_t value) {
buffer_->UnsafePut(GetOffset(i), value);
}
void WriteDouble(int i, double value) {
buffer_->UnsafePut(GetOffset(i), value);
}
void WriteString(int i, std::string_view value);
void WriteBytes(int i, const uint8_t *input, uint32_t length);
void WriteUnaligned(int i, const uint8_t *input, uint32_t offset,
uint32_t num_bytes);
void WriteRow(int i, const std::shared_ptr<Row> &row_data);
void WriteArray(int i, const std::shared_ptr<ArrayData> &array_data);
void WriteMap(int i, const std::shared_ptr<MapData> &map_data);
void WriteAligned(int i, const uint8_t *input, uint32_t offset,
uint32_t num_bytes);
void WriteDirectly(int64_t value);
void WriteDirectly(uint32_t offset, int64_t value);
void SetBuffer(std::shared_ptr<Buffer> buffer) {
buffer_ = buffer;
for (auto child : children_) {
child->SetBuffer(buffer);
}
}
virtual ~Writer() = default;
protected:
explicit Writer(int bytes_before_bitmap);
explicit Writer(Writer *parent_writer, int bytes_before_bitmap);
std::shared_ptr<Buffer> buffer_;
// The offset of the global buffer where we start to WriteString this
// structure.
uint32_t starting_offset_;
// avoid polymorphic setNullAt/setNotNullAt to inline for performance.
// array use 8 byte for numElements
int bytes_before_bitmap_;
// hold children writer to update buffer recursively.
std::vector<Writer *> children_;
};
/// Must call `reset()`/`reset(buffer)` before use this writer to write a row.
class RowWriter : public Writer {
public:
explicit RowWriter(const std::shared_ptr<arrow::Schema> &schema);
explicit RowWriter(const std::shared_ptr<arrow::Schema> &schema,
Writer *writer);
std::shared_ptr<arrow::Schema> schema() { return schema_; }
void Reset();
int GetOffset(int i) const override {
return starting_offset_ + header_in_bytes_ + 8 * i;
}
void Write(int i, int8_t value) override;
void Write(int i, bool value) override;
void Write(int i, int16_t value) override;
void Write(int i, int32_t value) override;
void Write(int i, int64_t value) override;
void Write(int i, float value) override;
void Write(int i, double value) override;
std::shared_ptr<Row> ToRow();
private:
std::shared_ptr<arrow::Schema> schema_;
uint32_t header_in_bytes_;
uint32_t fixed_size_;
};
/// Must call reset(numElements) before use this writer to writer an array every
/// time.
class ArrayWriter : public Writer {
public:
explicit ArrayWriter(std::shared_ptr<arrow::ListType> type);
explicit ArrayWriter(std::shared_ptr<arrow::ListType> type, Writer *writer);
void Reset(uint32_t num_elements);
int GetOffset(int i) const override {
return starting_offset_ + header_in_bytes_ + i * element_size_;
}
void Write(int i, int8_t value) override;
void Write(int i, bool value) override;
void Write(int i, int16_t value) override;
void Write(int i, int32_t value) override;
void Write(int i, int64_t value) override;
void Write(int i, float value) override;
void Write(int i, double value) override;
/// note: this will create a new buffer, won't take ownership of writer's
/// buffer
std::shared_ptr<ArrayData> CopyToArrayData();
int size() { return cursor() - starting_offset_; }
std::shared_ptr<arrow::ListType> type() { return type_; }
private:
std::shared_ptr<arrow::ListType> type_;
int element_size_;
int num_elements_;
int header_in_bytes_;
};
} // namespace fury