Text operator[](Int i) const { if (is_na() || (static_cast<size_t>(i.raw()) >= raw_size())) { return Text::na(); } if (is_direct_) { return data_[i.raw()]; } else { return Text(&bodies_[headers_[i.raw()].offset], headers_[i.raw()].size.raw()); } }
// Return a value. // // If "row_id" is valid, returns the stored value. // If "row_id" is invalid, returns N/A. GeoPoint get(Int row_id) const { size_t value_id = row_id.raw(); if (value_id >= values_.size()) { return GeoPoint::na(); } return values_[value_id]; }
void Column<Float>::set(Int row_id, const Datum &datum) { Float new_value = parse_datum(datum); if (!table_->test_row(row_id)) { throw "Invalid row ID"; // TODO } if (new_value.is_na()) { unset(row_id); return; } Float old_value = get(row_id); if (old_value.match(new_value)) { return; } if (!old_value.is_na()) { // Remove the old value from indexes. for (size_t i = 0; i < num_indexes(); ++i) { indexes_[i]->remove(row_id, old_value); } } size_t value_id = row_id.raw(); if (value_id >= values_.size()) { values_.resize(value_id + 1, Float::na()); } // Insert the new value into indexes. for (size_t i = 0; i < num_indexes(); ++i) try { indexes_[i]->insert(row_id, datum); } catch (...) { for (size_t j = 0; j < i; ++i) { indexes_[j]->remove(row_id, datum); } throw; } values_[value_id] = new_value; }
// Return a value. // // If "row_id" is valid, returns the stored value. // If "row_id" is invalid, returns N/A. Int get(Int row_id) const { size_t value_id = row_id.raw(); if (value_id >= size_) { return Int::na(); } return _get(value_id); }
void Column<Float>::get(Int row_id, Datum *datum) const { size_t value_id = row_id.raw(); if (value_id >= values_.size()) { *datum = Float::na(); } else { *datum = values_[value_id]; } }
void Column<Vector<GeoPoint>>::get(Int row_id, Datum *datum) const { size_t value_id = row_id.raw(); if (value_id >= headers_.size()) { *datum = Vector<GeoPoint>::na(); } else { // TODO *datum = get(row_id); } }
void Column<Float>::unset(Int row_id) { Float value = get(row_id); if (!value.is_na()) { // Update indexes if exist. for (size_t i = 0; i < num_indexes(); ++i) { indexes_[i]->remove(row_id, value); } values_[row_id.raw()] = Float::na(); } }
void Column<Vector<GeoPoint>>::unset(Int row_id) { Vector<GeoPoint> value = get(row_id); if (!value.is_na()) { // TODO: Update indexes if exist. // for (size_t i = 0; i < num_indexes(); ++i) { // indexes_[i]->remove(row_id, value); // } headers_[row_id.raw()] = na_header(); } }
void Column<Vector<GeoPoint>>::set(Int row_id, const Datum &datum) { Vector<GeoPoint> new_value = parse_datum(datum); if (!table_->test_row(row_id)) { throw "Invalid row ID"; // TODO } if (new_value.is_na()) { unset(row_id); return; } Vector<GeoPoint> old_value = get(row_id); if (old_value.match(new_value)) { return; } if (!old_value.is_na()) { // TODO: Remove the old value from indexes. // for (size_t i = 0; i < num_indexes(); ++i) { // indexes_[i]->remove(row_id, old_value); // } } size_t value_id = row_id.raw(); if (value_id >= headers_.size()) { headers_.resize(value_id + 1, na_header()); } // TODO: Insert the new value into indexes. // for (size_t i = 0; i < num_indexes(); ++i) try { // indexes_[i]->insert(row_id, datum)) { // } catch (...) { // for (size_t j = 0; j < i; ++i) { // indexes_[j]->remove(row_id, datum); // } // throw; // } // TODO: Error handling. size_t offset = bodies_.size(); size_t size = new_value.raw_size(); uint64_t header; if (size < 0xFFFF) { bodies_.resize(offset + size); std::memcpy(&bodies_[offset], new_value.raw_data(), sizeof(GeoPoint) * size); header = (offset << 16) | size; } else { // The size of a long vector is stored in front of the body. if ((offset % sizeof(uint64_t)) != 0) { offset += sizeof(uint64_t) - (offset % sizeof(uint64_t)); } bodies_.resize(offset + sizeof(uint64_t) + size); *reinterpret_cast<uint64_t *>(&bodies_[offset]) = size; std::memcpy(&bodies_[offset + sizeof(uint64_t)], new_value.raw_data(), sizeof(GeoPoint) * size); header = (offset << 16) | 0xFFFF; } headers_[value_id] = header; }
// Return a value. // // If "row_id" is valid, returns the stored value. // If "row_id" is invalid, returns N/A. // // TODO: Vector cannot reuse allocated memory because of this interface. Vector<Bool> get(Int row_id) const { size_t value_id = row_id.raw(); if (value_id >= headers_.size()) { return Vector<Bool>::na(); } if (headers_[value_id] == na_header()) { return Vector<Bool>::na(); } size_t size = headers_[value_id] & 0xFFFF; if (size == 0) { return Vector<Bool>(nullptr, 0); } size_t offset = headers_[value_id] >> 16; if (size < 0xFFFF) { return Vector<Bool>(&bodies_[offset], size); } else { // The size of a long vector is stored in front of the body. size = *reinterpret_cast<const uint64_t *>(&bodies_[offset]); return Vector<Bool>(&bodies_[offset + sizeof(uint64_t)], size); } }
Int operator[](Int i) const { if (is_na() || (static_cast<size_t>(i.raw()) >= raw_size())) { return Int::na(); } return data_[i.raw()]; }