susumu.yata
null+****@clear*****
Thu Sep 18 16:04:30 JST 2014
susumu.yata 2014-09-18 16:04:30 +0900 (Thu, 18 Sep 2014) New Revision: 71e3eef005511dafed52f02697f850884f37415a https://github.com/groonga/grnxx/commit/71e3eef005511dafed52f02697f850884f37415a Message: Update the interface of Cursor. (#61) Added files: lib/grnxx/cursor.cpp Modified files: include/grnxx/cursor.hpp lib/grnxx/Makefile.am Modified: include/grnxx/cursor.hpp (+14 -7) =================================================================== --- include/grnxx/cursor.hpp 2014-09-17 16:48:23 +0900 (c085589) +++ include/grnxx/cursor.hpp 2014-09-18 16:04:30 +0900 (8db43d5) @@ -16,23 +16,30 @@ class Cursor { // Read the next records. // - // Reads at most "max_count" records and stores the records into "*records". + // Reads at most "max_count" records into "*records". // // On success, returns the number of records read. // On failure, returns -1 and stores error information into "*error" if // "error" != nullptr. - virtual Int read(Error *error, - Int max_count, - Array<Record> *records) = 0; + virtual Int read(Error *error, Int max_count, Array<Record> *records); + + // TODO: should be pure virtual. + // + // Read the next records. + // + // Reads at most "records.size()" records into "records". + // + // On success, returns the number of records read. + // On failure, returns -1 and stores error information into "*error" if + // "error" != nullptr. + virtual Int read(Error *error, ArrayRef<Record> records); // Read all the remaining records. // // On success, returns the number of records read. // On failure, returns -1 and stores error information into "*error" if // "error" != nullptr. - virtual Int read_all(Error *error, Array<Record> *records) { - return read(error, numeric_limits<Int>::max(), records); - } + virtual Int read_all(Error *error, Array<Record> *records); protected: const Table *table_; Modified: lib/grnxx/Makefile.am (+1 -0) =================================================================== --- lib/grnxx/Makefile.am 2014-09-17 16:48:23 +0900 (87fa27e) +++ lib/grnxx/Makefile.am 2014-09-18 16:04:30 +0900 (8d7bf41) @@ -11,6 +11,7 @@ libgrnxx_la_LDFLAGS = @AM_LTLDFLAGS@ libgrnxx_la_SOURCES = \ array.cpp \ column.cpp \ + cursor.cpp \ db.cpp \ error.cpp \ expression.cpp \ Added: lib/grnxx/cursor.cpp (+86 -0) 100644 =================================================================== --- /dev/null +++ lib/grnxx/cursor.cpp 2014-09-18 16:04:30 +0900 (ae21991) @@ -0,0 +1,86 @@ +#include "grnxx/cursor.hpp" + +namespace grnxx { +namespace { + +constexpr Int CURSOR_BLOCK_SIZE = 1024; + +} // namespace + +Int Cursor::read(Error *error, Int max_count, Array<Record> *records) { + if (max_count < 0) { + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Invalid argument"); + return -1; + } else if (max_count == 0) { + return read(error, records->ref(0, 0)); + } + + Int offset = records->size(); + if (offset > (numeric_limits<Int>::max() - max_count)) { + // Reduce "max_count" to avoid overflow. + max_count = numeric_limits<Int>::max() - offset; + } + + Int next_size = offset + max_count; + if (next_size <= records->capacity()) { + // There are enough space for requested records. + records->resize(nullptr, next_size); + Int count = read(error, records->ref(offset, max_count)); + records->resize(nullptr, offset + ((count != -1) ? count : 0)); + return count; + } + + // Read the first block. + Int block_size = max_count; + if (block_size > CURSOR_BLOCK_SIZE) { + block_size = CURSOR_BLOCK_SIZE; + } + if (!records->resize(error, offset + block_size)) { + return -1; + } + Int count = read(error, records->ref(offset, block_size)); + if (count != block_size) { + records->resize(nullptr, offset + ((count != -1) ? count : 0)); + if (count <= 0) { + return count; + } + } + + // Read the remaining blocks. + while (count < max_count) { + block_size = max_count - count; + if (block_size > CURSOR_BLOCK_SIZE) { + block_size = CURSOR_BLOCK_SIZE; + } + Int this_offset = offset + count; + if (!records->resize(error, this_offset + block_size)) { + return count; + } + Int this_count = read(error, records->ref(this_offset, block_size)); + if (this_count != block_size) { + records->resize(nullptr, + this_offset + ((this_count != -1) ? this_count : 0)); + if (this_count <= 0) { + return count; + } + } + count += this_count; + } + return count; +} + +// TODO: To be removed! +Int Cursor::read(Error *, ArrayRef<Record>) { + return -1; +} + +Int Cursor::read_all(Error *error, Array<Record> *records) { + Int total_count = 0; + Int count; + while ((count = read(error, numeric_limits<Int>::max(), records)) > 0) { + total_count += count; + } + return (count == 0) ? total_count : count; +} + +} // namespace grnxx -------------- next part -------------- HTML����������������������������... Download