File size: 3,626 Bytes
bf20cb7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "wayy_db/column.hpp"

#include <cstring>

namespace wayy_db {

Column::Column(std::string name, DType dtype, std::vector<uint8_t> data)
    : name_(std::move(name))
    , dtype_(dtype)
    , size_(dtype_size(dtype) > 0 ? data.size() / dtype_size(dtype) : 0)
    , owns_data_(true)
    , owned_data_(std::move(data)) {
    data_ = owned_data_.data();
}

Column::Column(std::string name, DType dtype, void* data, size_t size, bool owns_data)
    : name_(std::move(name))
    , dtype_(dtype)
    , data_(data)
    , size_(size)
    , owns_data_(owns_data) {
    if (owns_data && data != nullptr && dtype_size(dtype) > 0) {
        // Copy data into owned buffer
        size_t byte_size = size * dtype_size(dtype);
        owned_data_.resize(byte_size);
        std::memcpy(owned_data_.data(), data, byte_size);
        data_ = owned_data_.data();
    }
}

// --- Validity bitmap ---

void Column::ensure_validity() {
    if (has_validity_) return;
    size_t num_bytes = (size_ + 7) / 8;
    validity_.assign(num_bytes, 0xFF);  // All bits set = all valid
    // Handle trailing bits in last byte
    if (size_ % 8 != 0) {
        uint8_t mask = static_cast<uint8_t>((1u << (size_ % 8)) - 1);
        validity_.back() = mask;
    }
    has_validity_ = true;
}

bool Column::is_valid(size_t row) const {
    if (!has_validity_) return true;  // No bitmap = all valid
    if (row >= size_) return false;
    return (validity_[row / 8] >> (row % 8)) & 1;
}

void Column::set_valid(size_t row, bool valid) {
    if (!has_validity_) ensure_validity();
    if (row >= size_) return;
    if (valid) {
        validity_[row / 8] |= (1u << (row % 8));
    } else {
        validity_[row / 8] &= ~(1u << (row % 8));
    }
}

size_t Column::count_valid() const {
    if (!has_validity_) return size_;  // All valid
    size_t count = 0;
    for (size_t i = 0; i < validity_.size(); ++i) {
        count += std::popcount(validity_[i]);
    }
    return count;
}

void Column::set_validity_bitmap(std::vector<uint8_t> bitmap) {
    validity_ = std::move(bitmap);
    has_validity_ = !validity_.empty();
}

void Column::append(const void* value, size_t value_size) {
    if (!owns_data_) {
        throw InvalidOperation("Cannot append to non-owned column");
    }
    size_t elem_size = dtype_size(dtype_);
    if (elem_size == 0) {
        throw InvalidOperation("Cannot append to variable-length column via Column::append");
    }
    if (value_size != elem_size) {
        throw InvalidOperation("Value size mismatch in append");
    }

    size_t old_byte_size = owned_data_.size();
    owned_data_.resize(old_byte_size + elem_size);
    std::memcpy(owned_data_.data() + old_byte_size, value, elem_size);
    data_ = owned_data_.data();
    ++size_;

    // Extend validity bitmap if present
    if (has_validity_) {
        size_t needed_bytes = (size_ + 7) / 8;
        if (validity_.size() < needed_bytes) {
            validity_.push_back(0);
        }
        set_valid(size_ - 1, true);
    }
}

void Column::set(size_t row, const void* value, size_t value_size) {
    if (!owns_data_) {
        throw InvalidOperation("Cannot set on non-owned column");
    }
    if (row >= size_) {
        throw InvalidOperation("Row index out of range in set");
    }
    size_t elem_size = dtype_size(dtype_);
    if (elem_size == 0) {
        throw InvalidOperation("Cannot set on variable-length column via Column::set");
    }
    if (value_size != elem_size) {
        throw InvalidOperation("Value size mismatch in set");
    }

    std::memcpy(owned_data_.data() + row * elem_size, value, elem_size);
}

}  // namespace wayy_db