susumu.yata
null+****@clear*****
Thu Aug 28 13:43:11 JST 2014
susumu.yata 2014-08-28 13:43:11 +0900 (Thu, 28 Aug 2014) New Revision: 44561e760efb571686dafe0a5cee18eeeb0ca0e1 https://github.com/groonga/grnxx/commit/44561e760efb571686dafe0a5cee18eeeb0ca0e1 Message: Add ColumnImpl<Int/Float>. Modified files: lib/grnxx/column.cpp lib/grnxx/column_impl.hpp Modified: lib/grnxx/column.cpp (+178 -0) =================================================================== --- lib/grnxx/column.cpp 2014-08-28 13:24:20 +0900 (d8cab38) +++ lib/grnxx/column.cpp 2014-08-28 13:43:11 +0900 (a2a1d09) @@ -91,6 +91,12 @@ unique_ptr<Column> Column::create(Error *error, case BOOL_VECTOR_DATA: { return ColumnImpl<Vector<Bool>>::create(error, table, name, options); } + case INT_VECTOR_DATA: { + return ColumnImpl<Vector<Int>>::create(error, table, name, options); + } + case FLOAT_VECTOR_DATA: { + return ColumnImpl<Vector<Float>>::create(error, table, name, options); + } default: { // TODO: Other data types are not supported yet. GRNXX_ERROR_SET(error, NOT_SUPPORTED_YET, "Not suported yet"); @@ -286,4 +292,176 @@ void ColumnImpl<Text>::unset(Int row_id) { ColumnImpl<Text>::ColumnImpl() : Column(), headers_(), bodies_() {} +// -- ColumnImpl<Vector<Int>> -- + +bool ColumnImpl<Vector<Int>>::set(Error *error, Int row_id, + const Datum &datum) { + if (datum.type() != INT_VECTOR_DATA) { + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong data type"); + return false; + } + if (!table_->test_row(error, row_id)) { + return false; + } + Vector<Int> value = datum.force_int_vector(); + if (value.size() == 0) { + headers_[row_id] = 0; + return true; + } + Int offset = bodies_.size(); + if (value.size() < 0xFFFF) { + if (!bodies_.resize(error, offset + value.size())) { + return false; + } + for (Int i = 0; i < value.size(); ++i) { + bodies_[offset + i] = value[i]; + } + headers_[row_id] = (offset << 16) | value.size(); + } else { + // The size of a long vector is stored in front of the body. + if (!bodies_.resize(error, offset + 1 + value.size())) { + return false; + } + bodies_[offset] = value.size(); + for (Int i = 0; i < value.size(); ++i) { + bodies_[offset + 1 + i] = value[i]; + } + headers_[row_id] = (offset << 16) | 0xFFFF; + } + return true; +} + +bool ColumnImpl<Vector<Int>>::get(Error *error, Int row_id, + Datum *datum) const { + if (!table_->test_row(error, row_id)) { + return false; + } + *datum = get(row_id); + return true; +} + +unique_ptr<ColumnImpl<Vector<Int>>> ColumnImpl<Vector<Int>>::create( + Error *error, + Table *table, + String name, + const ColumnOptions &options) { + unique_ptr<ColumnImpl> column(new (nothrow) ColumnImpl); + if (!column) { + GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed"); + return nullptr; + } + if (!column->initialize_base(error, table, name, INT_VECTOR_DATA, options)) { + return nullptr; + } + if (!column->headers_.resize(error, table->max_row_id() + 1, 0)) { + return nullptr; + } + return column; +} + +ColumnImpl<Vector<Int>>::~ColumnImpl() {} + +bool ColumnImpl<Vector<Int>>::set_default_value(Error *error, Int row_id) { + if (row_id >= headers_.size()) { + if (!headers_.resize(error, row_id + 1)) { + return false; + } + } + headers_[row_id] = 0; + return true; +} + +void ColumnImpl<Vector<Int>>::unset(Int row_id) { + headers_[row_id] = 0; +} + +ColumnImpl<Vector<Int>>::ColumnImpl() : Column(), headers_(), bodies_() {} + +// -- ColumnImpl<Vector<Float>> -- + +bool ColumnImpl<Vector<Float>>::set(Error *error, Int row_id, + const Datum &datum) { + if (datum.type() != FLOAT_VECTOR_DATA) { + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong data type"); + return false; + } + if (!table_->test_row(error, row_id)) { + return false; + } + Vector<Float> value = datum.force_float_vector(); + if (value.size() == 0) { + headers_[row_id] = 0; + return true; + } + Int offset = bodies_.size(); + if (value.size() < 0xFFFF) { + if (!bodies_.resize(error, offset + value.size())) { + return false; + } + for (Int i = 0; i < value.size(); ++i) { + bodies_[offset + i] = value[i]; + } + headers_[row_id] = (offset << 16) | value.size(); + } else { + // The size of a long vector is stored in front of the body. + if (!bodies_.resize(error, offset + 1 + value.size())) { + return false; + } + Int size_for_copy = value.size(); + std::memcpy(&bodies_[offset], &size_for_copy, sizeof(Int)); + for (Int i = 0; i < value.size(); ++i) { + bodies_[offset + 1 + i] = value[i]; + } + headers_[row_id] = (offset << 16) | 0xFFFF; + } + return true; +} + +bool ColumnImpl<Vector<Float>>::get(Error *error, Int row_id, + Datum *datum) const { + if (!table_->test_row(error, row_id)) { + return false; + } + *datum = get(row_id); + return true; +} + +unique_ptr<ColumnImpl<Vector<Float>>> ColumnImpl<Vector<Float>>::create( + Error *error, + Table *table, + String name, + const ColumnOptions &options) { + unique_ptr<ColumnImpl> column(new (nothrow) ColumnImpl); + if (!column) { + GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed"); + return nullptr; + } + if (!column->initialize_base(error, table, name, + FLOAT_VECTOR_DATA, options)) { + return nullptr; + } + if (!column->headers_.resize(error, table->max_row_id() + 1, 0)) { + return nullptr; + } + return column; +} + +ColumnImpl<Vector<Float>>::~ColumnImpl() {} + +bool ColumnImpl<Vector<Float>>::set_default_value(Error *error, Int row_id) { + if (row_id >= headers_.size()) { + if (!headers_.resize(error, row_id + 1)) { + return false; + } + } + headers_[row_id] = 0; + return true; +} + +void ColumnImpl<Vector<Float>>::unset(Int row_id) { + headers_[row_id] = 0; +} + +ColumnImpl<Vector<Float>>::ColumnImpl() : Column(), headers_(), bodies_() {} + } // namespace grnxx Modified: lib/grnxx/column_impl.hpp (+100 -0) =================================================================== --- lib/grnxx/column_impl.hpp 2014-08-28 13:24:20 +0900 (1e0b6c5) +++ lib/grnxx/column_impl.hpp 2014-08-28 13:43:11 +0900 (55f71e5) @@ -94,6 +94,106 @@ class ColumnImpl<Text> : public Column { ColumnImpl(); }; +template <> +class ColumnImpl<Vector<Int>> : public Column { + public: + // -- Public API -- + + bool set(Error *error, Int row_id, const Datum &datum); + bool get(Error *error, Int row_id, Datum *datum) const; + + // -- Internal API -- + + // Create a new column. + // + // Returns a pointer to the column on success. + // On failure, returns nullptr and stores error information into "*error" if + // "error" != nullptr. + static unique_ptr<ColumnImpl> create(Error *error, + Table *table, + String name, + const ColumnOptions &options); + + ~ColumnImpl(); + + bool set_default_value(Error *error, Int row_id); + void unset(Int row_id); + + // Return a value identified by "row_id". + // + // Assumes that "row_id" is valid. Otherwise, the result is undefined. + Vector<Int> get(Int row_id) const { + Int size = static_cast<Int>(headers_[row_id] & 0xFFFF); + if (size == 0) { + return Vector<Int>(nullptr, 0); + } + Int offset = static_cast<Int>(headers_[row_id] >> 16); + if (size < 0xFFFF) { + return Vector<Int>(&bodies_[offset], size); + } else { + // The size of a long vector is stored in front of the body. + size = bodies_[offset]; + return Vector<Int>(&bodies_[offset + 1], size); + } + } + + protected: + Array<uint64_t> headers_; + Array<Int> bodies_; + + ColumnImpl(); +}; + +template <> +class ColumnImpl<Vector<Float>> : public Column { + public: + // -- Public API -- + + bool set(Error *error, Int row_id, const Datum &datum); + bool get(Error *error, Int row_id, Datum *datum) const; + + // -- Internal API -- + + // Create a new column. + // + // Returns a pointer to the column on success. + // On failure, returns nullptr and stores error information into "*error" if + // "error" != nullptr. + static unique_ptr<ColumnImpl> create(Error *error, + Table *table, + String name, + const ColumnOptions &options); + + ~ColumnImpl(); + + bool set_default_value(Error *error, Int row_id); + void unset(Int row_id); + + // Return a value identified by "row_id". + // + // Assumes that "row_id" is valid. Otherwise, the result is undefined. + Vector<Float> get(Int row_id) const { + Int size = static_cast<Int>(headers_[row_id] & 0xFFFF); + if (size == 0) { + return Vector<Float>(nullptr, 0); + } + Int offset = static_cast<Int>(headers_[row_id] >> 16); + if (size < 0xFFFF) { + return Vector<Float>(&bodies_[offset], size); + } else { + // The size of a long vector is stored in front of the body. + std::memcpy(&size, &bodies_[offset], sizeof(Int)); + return Vector<Float>(&bodies_[offset + 1], size); + } + } + + protected: + Array<uint64_t> headers_; + Array<Float> bodies_; + + ColumnImpl(); +}; + } // namespace grnxx #endif // GRNXX_COLUMN_IMPL_HPP -------------- next part -------------- HTML����������������������������... 下载