susumu.yata
null+****@clear*****
Wed May 29 12:49:14 JST 2013
susumu.yata 2013-05-29 12:49:14 +0900 (Wed, 29 May 2013) New Revision: 4707a8adb6aaacc3fee9b2095d8357d3b5b5114f https://github.com/groonga/grnxx/commit/4707a8adb6aaacc3fee9b2095d8357d3b5b5114f Message: Add grnxx::Array<bool>. Modified files: lib/grnxx/array.hpp Modified: lib/grnxx/array.hpp (+153 -0) =================================================================== --- lib/grnxx/array.hpp 2013-05-29 11:45:43 +0900 (a23ebdb) +++ lib/grnxx/array.hpp 2013-05-29 12:49:14 +0900 (6eaff94) @@ -26,6 +26,7 @@ #include "grnxx/array_impl.hpp" #include "grnxx/logger.hpp" +#include "grnxx/traits.hpp" #include "grnxx/types.hpp" namespace grnxx { @@ -155,6 +156,158 @@ class Array { } }; +// Bit array. +template <uint64_t PAGE_SIZE_IN_BITS, + uint64_t TABLE_SIZE, + uint64_t SECONDARY_TABLE_SIZE> +class Array<bool, PAGE_SIZE_IN_BITS, TABLE_SIZE, SECONDARY_TABLE_SIZE> { + public: + // Internal type to store bits. + using Unit = uint64_t; + + private: + static constexpr uint64_t UNIT_SIZE = sizeof(Unit) * 8; + static constexpr uint64_t PAGE_SIZE = PAGE_SIZE_IN_BITS / UNIT_SIZE; + + static_assert((PAGE_SIZE_IN_BITS % UNIT_SIZE) == 0, + "(PAGE_SIZE_IN_BITS % UNIT_SIZE) != 0"); + using ArrayImpl = ArrayImpl<Unit, PAGE_SIZE, TABLE_SIZE, + SECONDARY_TABLE_SIZE>; + + public: + using Value = typename Traits<bool>::Type; + using ValueArg = typename Traits<bool>::ArgumentType; + + ~Array() {} + + // Create an array. + static Array *create(Storage *storage, uint32_t storage_node_id) { + std::unique_ptr<Array> array(create_instance()); + if (!array) { + return nullptr; + } + if (!array->impl_.create(storage, storage_node_id)) { + return nullptr; + } + return array.release(); + } + + // Create an array with the default value. + static Array *create(Storage *storage, uint32_t storage_node_id, + ValueArg default_value) { + std::unique_ptr<Array> array(create_instance()); + if (!array) { + return nullptr; + } + if (!array->impl_.create(storage, storage_node_id, + default_value ? ~Unit(0) : Unit(0))) { + return nullptr; + } + return array.release(); + } + + // Open an array. + static Array *open(Storage *storage, uint32_t storage_node_id) { + std::unique_ptr<Array> array(create_instance()); + if (!array) { + return nullptr; + } + if (!array->impl_.open(storage, storage_node_id)) { + return nullptr; + } + return array.release(); + } + + // Unlink an array. + static bool unlink(Storage *storage, uint32_t storage_node_id) { + return ArrayImpl::unlink(storage, storage_node_id); + } + + // Return the number of values in each unit. + static constexpr uint64_t unit_size() { + return UNIT_SIZE; + } + // Return the number of values in each page. + static constexpr uint64_t page_size() { + return PAGE_SIZE_IN_BITS; + } + // Return the number of pages in each table. + static constexpr uint64_t table_size() { + return TABLE_SIZE; + } + // Return the number of tables in each secondary table. + static constexpr uint64_t secondary_table_size() { + return SECONDARY_TABLE_SIZE; + } + // Return the number of values in Array. + static constexpr uint64_t size() { + return page_size() * table_size() * secondary_table_size(); + } + + // Return the storage node ID. + uint32_t storage_node_id() const { + return impl_.storage_node_id(); + } + + // Get a value and return true on success. + // The value is assigned to "*value" iff "value" != nullptr. + bool get(uint64_t value_id, Value *value) { + const uint64_t unit_id = value_id / UNIT_SIZE; + const Unit * const page = get_page(unit_id / PAGE_SIZE); + if (!page) { + return false; + } + if (value) { + *value = (page[unit_id % PAGE_SIZE] & + (Unit(1) << (value_id % UNIT_SIZE))) != 0; + } + return true; + } + + // Set a value and return true on success. + // Note that if bits in the same byte are set at the same time, the result is + // undefined. + bool set(uint64_t value_id, ValueArg value) { + const uint64_t unit_id = value_id / UNIT_SIZE; + Unit * const page = get_page(unit_id / PAGE_SIZE); + if (!page) { + return false; + } + if (value) { + page[unit_id % PAGE_SIZE] |= Unit(1) << (value_id % UNIT_SIZE); + } else { + page[unit_id % PAGE_SIZE] &= ~(Unit(1) << (value_id % UNIT_SIZE)); + } + return true; + } + + // Get a unit and return its address on success. + Unit *get_unit(uint64_t unit_id) { + return impl_.get_pointer(unit_id); + } + // Get a page and return its starting address on success. + Unit *get_page(uint64_t page_id) { + return impl_.get_page(page_id); + } + + private: + ArrayImpl impl_; + + Array() : impl_() {} + + static Array *create_instance() { + Array * const array = new (std::nothrow) Array; + if (!array) { + GRNXX_ERROR() << "new grnxx::Array failed: " + << "value_size = " << sizeof(Value) + << ", page_size = " << PAGE_SIZE + << ", table_size = " << TABLE_SIZE + << ", secondary_table_size = " << SECONDARY_TABLE_SIZE; + } + return array; + } +}; + } // namespace grnxx #endif // GRNXX_ARRAY_HPP -------------- next part -------------- HTML����������������������������... ダウンロード