kcplantdb.h | kcplantdb.h | |||
---|---|---|---|---|
skipping to change at line 2567 | skipping to change at line 2567 | |||
* Save a leaf node. | * Save a leaf node. | |||
* @param node the leaf node. | * @param node the leaf node. | |||
* @return true on success, or false on failure. | * @return true on success, or false on failure. | |||
*/ | */ | |||
bool save_leaf_node(LeafNode* node) { | bool save_leaf_node(LeafNode* node) { | |||
_assert_(node); | _assert_(node); | |||
ScopedRWLock lock(&node->lock, false); | ScopedRWLock lock(&node->lock, false); | |||
if (!node->dirty) return true; | if (!node->dirty) return true; | |||
bool err = false; | bool err = false; | |||
char hbuf[NUMBUFSIZ]; | char hbuf[NUMBUFSIZ]; | |||
size_t hsiz = std::sprintf(hbuf, "%c%llX", LNPREFIX, (long long)node->i d); | size_t hsiz = write_key(hbuf, LNPREFIX, node->id); | |||
if (node->dead) { | if (node->dead) { | |||
if (!db_.remove(hbuf, hsiz) && db_.error().code() != Error::NOREC) er r = true; | if (!db_.remove(hbuf, hsiz) && db_.error().code() != Error::NOREC) er r = true; | |||
} else { | } else { | |||
char* rbuf = new char[node->size]; | char* rbuf = new char[node->size]; | |||
char* wp = rbuf; | char* wp = rbuf; | |||
wp += writevarnum(wp, node->prev); | wp += writevarnum(wp, node->prev); | |||
wp += writevarnum(wp, node->next); | wp += writevarnum(wp, node->next); | |||
typename RecordArray::const_iterator rit = node->recs.begin(); | typename RecordArray::const_iterator rit = node->recs.begin(); | |||
typename RecordArray::const_iterator ritend = node->recs.end(); | typename RecordArray::const_iterator ritend = node->recs.end(); | |||
while (rit != ritend) { | while (rit != ritend) { | |||
skipping to change at line 2622 | skipping to change at line 2622 | |||
np = slot->warm->migrate(id, slot->hot, LeafCache::MLAST); | np = slot->warm->migrate(id, slot->hot, LeafCache::MLAST); | |||
if (np) { | if (np) { | |||
(*np)->hot = true; | (*np)->hot = true; | |||
return *np; | return *np; | |||
} | } | |||
} else { | } else { | |||
LeafNode** np = slot->warm->get(id, LeafCache::MLAST); | LeafNode** np = slot->warm->get(id, LeafCache::MLAST); | |||
if (np) return *np; | if (np) return *np; | |||
} | } | |||
char hbuf[NUMBUFSIZ]; | char hbuf[NUMBUFSIZ]; | |||
size_t hsiz = std::sprintf(hbuf, "%c%llX", LNPREFIX, (long long)id); | size_t hsiz = write_key(hbuf, LNPREFIX, id); | |||
class VisitorImpl : public DB::Visitor { | class VisitorImpl : public DB::Visitor { | |||
public: | public: | |||
explicit VisitorImpl() : node_(NULL) {} | explicit VisitorImpl() : node_(NULL) {} | |||
LeafNode* pop() { | LeafNode* pop() { | |||
return node_; | return node_; | |||
} | } | |||
private: | private: | |||
const char* visit_full(const char* kbuf, size_t ksiz, | const char* visit_full(const char* kbuf, size_t ksiz, | |||
const char* vbuf, size_t vsiz, size_t* sp) { | const char* vbuf, size_t vsiz, size_t* sp) { | |||
uint64_t prev; | uint64_t prev; | |||
skipping to change at line 2945 | skipping to change at line 2945 | |||
/** | /** | |||
* Save a inner node. | * Save a inner node. | |||
* @param node the inner node. | * @param node the inner node. | |||
* @return true on success, or false on failure. | * @return true on success, or false on failure. | |||
*/ | */ | |||
bool save_inner_node(InnerNode* node) { | bool save_inner_node(InnerNode* node) { | |||
_assert_(true); | _assert_(true); | |||
if (!node->dirty) return true; | if (!node->dirty) return true; | |||
bool err = false; | bool err = false; | |||
char hbuf[NUMBUFSIZ]; | char hbuf[NUMBUFSIZ]; | |||
size_t hsiz = std::sprintf(hbuf, "%c%llX", | size_t hsiz = write_key(hbuf, INPREFIX, node->id - INIDBASE); | |||
INPREFIX, (long long)(node->id - INIDBASE)); | ||||
if (node->dead) { | if (node->dead) { | |||
if (!db_.remove(hbuf, hsiz) && db_.error().code() != Error::NOREC) er r = true; | if (!db_.remove(hbuf, hsiz) && db_.error().code() != Error::NOREC) er r = true; | |||
} else { | } else { | |||
char* rbuf = new char[node->size]; | char* rbuf = new char[node->size]; | |||
char* wp = rbuf; | char* wp = rbuf; | |||
wp += writevarnum(wp, node->heir); | wp += writevarnum(wp, node->heir); | |||
typename LinkArray::const_iterator lit = node->links.begin(); | typename LinkArray::const_iterator lit = node->links.begin(); | |||
typename LinkArray::const_iterator litend = node->links.end(); | typename LinkArray::const_iterator litend = node->links.end(); | |||
while (lit != litend) { | while (lit != litend) { | |||
Link* link = *lit; | Link* link = *lit; | |||
skipping to change at line 2983 | skipping to change at line 2982 | |||
* @return the loaded inner node. | * @return the loaded inner node. | |||
*/ | */ | |||
InnerNode* load_inner_node(int64_t id) { | InnerNode* load_inner_node(int64_t id) { | |||
_assert_(id > 0); | _assert_(id > 0); | |||
int32_t sidx = id % SLOTNUM; | int32_t sidx = id % SLOTNUM; | |||
InnerSlot* slot = islots_ + sidx; | InnerSlot* slot = islots_ + sidx; | |||
ScopedMutex lock(&slot->lock); | ScopedMutex lock(&slot->lock); | |||
InnerNode** np = slot->warm->get(id, InnerCache::MLAST); | InnerNode** np = slot->warm->get(id, InnerCache::MLAST); | |||
if (np) return *np; | if (np) return *np; | |||
char hbuf[NUMBUFSIZ]; | char hbuf[NUMBUFSIZ]; | |||
size_t hsiz = std::sprintf(hbuf, "%c%llX", INPREFIX, (long long)(id - I NIDBASE)); | size_t hsiz = write_key(hbuf, INPREFIX, id - INIDBASE); | |||
class VisitorImpl : public DB::Visitor { | class VisitorImpl : public DB::Visitor { | |||
public: | public: | |||
explicit VisitorImpl() : node_(NULL) {} | explicit VisitorImpl() : node_(NULL) {} | |||
InnerNode* pop() { | InnerNode* pop() { | |||
return node_; | return node_; | |||
} | } | |||
private: | private: | |||
const char* visit_full(const char* kbuf, size_t ksiz, | const char* visit_full(const char* kbuf, size_t ksiz, | |||
const char* vbuf, size_t vsiz, size_t* sp) { | const char* vbuf, size_t vsiz, size_t* sp) { | |||
uint64_t heir; | uint64_t heir; | |||
skipping to change at line 3834 | skipping to change at line 3833 | |||
*/ | */ | |||
bool fix_auto_synchronization() { | bool fix_auto_synchronization() { | |||
_assert_(true); | _assert_(true); | |||
bool err = false; | bool err = false; | |||
if (!flush_leaf_cache(true)) err = true; | if (!flush_leaf_cache(true)) err = true; | |||
if (!flush_inner_cache(true)) err = true; | if (!flush_inner_cache(true)) err = true; | |||
if (!dump_meta()) err = true; | if (!dump_meta()) err = true; | |||
if (!db_.synchronize(true, NULL)) err = true; | if (!db_.synchronize(true, NULL)) err = true; | |||
return !err; | return !err; | |||
} | } | |||
/** | ||||
* Write the key pattern into a buffer. | ||||
* @param kbuf the destination buffer. | ||||
* @param pc the prefix character. | ||||
* @param id the ID number of the page. | ||||
* @return the size of the key pattern. | ||||
*/ | ||||
size_t write_key(char* kbuf, int32_t pc, int64_t num) { | ||||
_assert_(kbuf && num >= 0); | ||||
char* wp = kbuf; | ||||
*(wp++) = pc; | ||||
bool hit = false; | ||||
for (size_t i = 0; i < sizeof(num); i++) { | ||||
uint8_t c = num >> ((sizeof(num) - 1 - i) * 8); | ||||
uint8_t h = c >> 4; | ||||
if (h < 10) { | ||||
if (hit || h != 0) { | ||||
*(wp++) = '0' + h; | ||||
hit = true; | ||||
} | ||||
} else { | ||||
*(wp++) = 'A' - 10 + h; | ||||
hit = true; | ||||
} | ||||
uint8_t l = c & 0xf; | ||||
if (l < 10) { | ||||
if (hit || l != 0) { | ||||
*(wp++) = '0' + l; | ||||
hit = true; | ||||
} | ||||
} else { | ||||
*(wp++) = 'A' - 10 + l; | ||||
hit = true; | ||||
} | ||||
} | ||||
return wp - kbuf; | ||||
} | ||||
/** Dummy constructor to forbid the use. */ | /** Dummy constructor to forbid the use. */ | |||
PlantDB(const PlantDB&); | PlantDB(const PlantDB&); | |||
/** Dummy Operator to forbid the use. */ | /** Dummy Operator to forbid the use. */ | |||
PlantDB& operator =(const PlantDB&); | PlantDB& operator =(const PlantDB&); | |||
/** The method lock. */ | /** The method lock. */ | |||
RWLock mlock_; | RWLock mlock_; | |||
/** The internal meta operation trigger. */ | /** The internal meta operation trigger. */ | |||
MetaTrigger* mtrigger_; | MetaTrigger* mtrigger_; | |||
/** The open mode. */ | /** The open mode. */ | |||
uint32_t omode_; | uint32_t omode_; | |||
End of changes. 5 change blocks. | ||||
5 lines changed or deleted | 41 lines changed or added | |||
kctextdb.h | kctextdb.h | |||
---|---|---|---|---|
skipping to change at line 62 | skipping to change at line 62 | |||
/** | /** | |||
* Cursor to indicate a record. | * Cursor to indicate a record. | |||
*/ | */ | |||
class Cursor : public BasicDB::Cursor { | class Cursor : public BasicDB::Cursor { | |||
friend class TextDB; | friend class TextDB; | |||
public: | public: | |||
/** | /** | |||
* Constructor. | * Constructor. | |||
* @param db the container database object. | * @param db the container database object. | |||
*/ | */ | |||
explicit Cursor(TextDB* db) : db_(db), off_(INT64MAX), end_(0), queue_( ) { | explicit Cursor(TextDB* db) : db_(db), off_(INT64MAX), end_(0), queue_( ), line_() { | |||
_assert_(db); | _assert_(db); | |||
ScopedRWLock lock(&db_->mlock_, true); | ScopedRWLock lock(&db_->mlock_, true); | |||
db_->curs_.push_back(this); | db_->curs_.push_back(this); | |||
} | } | |||
/** | /** | |||
* Destructor. | * Destructor. | |||
*/ | */ | |||
virtual ~Cursor() { | virtual ~Cursor() { | |||
_assert_(true); | _assert_(true); | |||
if (!db_) return; | if (!db_) return; | |||
skipping to change at line 114 | skipping to change at line 114 | |||
bool jump() { | bool jump() { | |||
_assert_(true); | _assert_(true); | |||
ScopedRWLock lock(&db_->mlock_, false); | ScopedRWLock lock(&db_->mlock_, false); | |||
if (db_->omode_ == 0) { | if (db_->omode_ == 0) { | |||
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened"); | db_->set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |||
return false; | return false; | |||
} | } | |||
off_ = 0; | off_ = 0; | |||
end_ = db_->file_.size(); | end_ = db_->file_.size(); | |||
queue_.clear(); | queue_.clear(); | |||
line_.clear(); | ||||
if (off_ >= end_) { | if (off_ >= end_) { | |||
db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | |||
return false; | return false; | |||
} | } | |||
return true; | return true; | |||
} | } | |||
/** | /** | |||
* Jump the cursor to a record for forward scan. | * Jump the cursor to a record for forward scan. | |||
* @param kbuf the pointer to the key region. | * @param kbuf the pointer to the key region. | |||
* @param ksiz the size of the key region. | * @param ksiz the size of the key region. | |||
skipping to change at line 136 | skipping to change at line 137 | |||
bool jump(const char* kbuf, size_t ksiz) { | bool jump(const char* kbuf, size_t ksiz) { | |||
_assert_(kbuf && ksiz <= MEMMAXSIZ); | _assert_(kbuf && ksiz <= MEMMAXSIZ); | |||
ScopedRWLock lock(&db_->mlock_, true); | ScopedRWLock lock(&db_->mlock_, true); | |||
if (db_->omode_ == 0) { | if (db_->omode_ == 0) { | |||
db_->set_error(_KCCODELINE_, Error::INVALID, "not opened"); | db_->set_error(_KCCODELINE_, Error::INVALID, "not opened"); | |||
return false; | return false; | |||
} | } | |||
off_ = atoin(kbuf, ksiz); | off_ = atoin(kbuf, ksiz); | |||
end_ = db_->file_.size(); | end_ = db_->file_.size(); | |||
queue_.clear(); | queue_.clear(); | |||
line_.clear(); | ||||
if (off_ >= end_) { | if (off_ >= end_) { | |||
db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | |||
return false; | return false; | |||
} | } | |||
return true; | return true; | |||
} | } | |||
/** | /** | |||
* Jump the cursor to a record for forward scan. | * Jump the cursor to a record for forward scan. | |||
* @note Equal to the original Cursor::jump method except that the para meter is std::string. | * @note Equal to the original Cursor::jump method except that the para meter is std::string. | |||
*/ | */ | |||
skipping to change at line 244 | skipping to change at line 246 | |||
bool accept_impl(Visitor* visitor, bool step) { | bool accept_impl(Visitor* visitor, bool step) { | |||
_assert_(visitor); | _assert_(visitor); | |||
if (queue_.empty() && !read_next()) return false; | if (queue_.empty() && !read_next()) return false; | |||
if (queue_.empty()) { | if (queue_.empty()) { | |||
db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | db_->set_error(_KCCODELINE_, Error::NOREC, "no record"); | |||
return false; | return false; | |||
} | } | |||
bool err = false; | bool err = false; | |||
const Record& rec = queue_.front(); | const Record& rec = queue_.front(); | |||
char kbuf[NUMBUFSIZ]; | char kbuf[NUMBUFSIZ]; | |||
size_t ksiz = std::sprintf(kbuf, "%020lld", (long long)rec.first); | size_t ksiz = db_->write_key(kbuf, rec.first); | |||
size_t vsiz; | size_t vsiz; | |||
const char* vbuf = visitor->visit_full(kbuf, ksiz, | const char* vbuf = visitor->visit_full(kbuf, ksiz, | |||
rec.second.data(), rec.second. size(), &vsiz); | rec.second.data(), rec.second. size(), &vsiz); | |||
if (vbuf != Visitor::NOP && vbuf != Visitor::REMOVE) { | if (vbuf != Visitor::NOP && vbuf != Visitor::REMOVE) { | |||
char stack[IOBUFSIZ]; | char stack[IOBUFSIZ]; | |||
size_t rsiz = vsiz + 1; | size_t rsiz = vsiz + 1; | |||
char* rbuf = rsiz > sizeof(stack) ? new char[rsiz] : stack; | char* rbuf = rsiz > sizeof(stack) ? new char[rsiz] : stack; | |||
std::memcpy(rbuf, vbuf, vsiz); | std::memcpy(rbuf, vbuf, vsiz); | |||
rbuf[vsiz] = '\n'; | rbuf[vsiz] = '\n'; | |||
if (!db_->file_.append(rbuf, rsiz)) { | if (!db_->file_.append(rbuf, rsiz)) { | |||
skipping to change at line 273 | skipping to change at line 275 | |||
} | } | |||
if (step) queue_.pop_front(); | if (step) queue_.pop_front(); | |||
return !err; | return !err; | |||
} | } | |||
/** | /** | |||
* Read the next record. | * Read the next record. | |||
* @return true on success, or false on failure. | * @return true on success, or false on failure. | |||
*/ | */ | |||
bool read_next() { | bool read_next() { | |||
_assert_(true); | _assert_(true); | |||
std::string line; | ||||
while (off_ < end_) { | while (off_ < end_) { | |||
char stack[IOBUFSIZ]; | char stack[IOBUFSIZ]; | |||
int64_t rsiz = end_ - off_; | int64_t rsiz = end_ - off_; | |||
if (rsiz > (int64_t)IOBUFSIZ) rsiz = IOBUFSIZ; | if (rsiz > (int64_t)sizeof(stack)) rsiz = sizeof(stack); | |||
if (!db_->file_.read_fast(off_, stack, rsiz)) { | if (!db_->file_.read_fast(off_, stack, rsiz)) { | |||
db_->set_error(_KCCODELINE_, Error::SYSTEM, db_->file_.error()); | db_->set_error(_KCCODELINE_, Error::SYSTEM, db_->file_.error()); | |||
return false; | return false; | |||
} | } | |||
const char* rp = stack; | const char* rp = stack; | |||
const char* pv = rp; | const char* pv = rp; | |||
const char* ep = rp + rsiz; | const char* ep = rp + rsiz; | |||
while (rp < ep) { | while (rp < ep) { | |||
if (*rp == '\n') { | if (*rp == '\n') { | |||
line.append(pv, rp - pv); | line_.append(pv, rp - pv); | |||
Record rec; | Record rec; | |||
rec.first = off_ + pv - stack; | rec.first = off_ + pv - stack; | |||
rec.second = line; | rec.second = line_; | |||
queue_.push_back(rec); | queue_.push_back(rec); | |||
line.clear(); | line_.clear(); | |||
rp++; | rp++; | |||
pv = rp; | pv = rp; | |||
} else { | } else { | |||
rp++; | rp++; | |||
} | } | |||
} | } | |||
line_.append(pv, rp - pv); | ||||
off_ += rsiz; | off_ += rsiz; | |||
if (!queue_.empty()) break; | if (!queue_.empty()) break; | |||
} | } | |||
return true; | return true; | |||
} | } | |||
/** Dummy constructor to forbid the use. */ | /** Dummy constructor to forbid the use. */ | |||
Cursor(const Cursor&); | Cursor(const Cursor&); | |||
/** Dummy Operator to forbid the use. */ | /** Dummy Operator to forbid the use. */ | |||
Cursor& operator =(const Cursor&); | Cursor& operator =(const Cursor&); | |||
/** The inner database. */ | /** The inner database. */ | |||
TextDB* db_; | TextDB* db_; | |||
/** The current offset. */ | /** The current offset. */ | |||
int64_t off_; | int64_t off_; | |||
/** The end offset. */ | /** The end offset. */ | |||
int64_t end_; | int64_t end_; | |||
/** The queue of read lines. */ | /** The queue of read lines. */ | |||
std::deque<Record> queue_; | std::deque<Record> queue_; | |||
/** The current line. */ | ||||
std::string line_; | ||||
}; | }; | |||
/** | /** | |||
* Default constructor. | * Default constructor. | |||
*/ | */ | |||
explicit TextDB() : | explicit TextDB() : | |||
error_(), logger_(NULL), logkinds_(0), mtrigger_(NULL), | error_(), logger_(NULL), logkinds_(0), mtrigger_(NULL), | |||
omode_(0), writer_(false), autotran_(false), autosync_(false), | omode_(0), writer_(false), autotran_(false), autosync_(false), | |||
file_(), curs_(), path_("") { | file_(), curs_(), path_("") { | |||
_assert_(true); | _assert_(true); | |||
} | } | |||
skipping to change at line 934 | skipping to change at line 938 | |||
bool iterate_impl(Visitor* visitor, ProgressChecker* checker) { | bool iterate_impl(Visitor* visitor, ProgressChecker* checker) { | |||
_assert_(visitor); | _assert_(visitor); | |||
if (checker && !checker->check("iterate", "beginning", 0, -1)) { | if (checker && !checker->check("iterate", "beginning", 0, -1)) { | |||
set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); | set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); | |||
return false; | return false; | |||
} | } | |||
int64_t off = 0; | int64_t off = 0; | |||
int64_t end = file_.size(); | int64_t end = file_.size(); | |||
int64_t curcnt = 0; | int64_t curcnt = 0; | |||
std::string line; | std::string line; | |||
char stack[IOBUFSIZ]; | char stack[IOBUFSIZ*4]; | |||
while (off < end) { | while (off < end) { | |||
int64_t rsiz = end - off; | int64_t rsiz = end - off; | |||
if (rsiz > (int64_t)IOBUFSIZ) rsiz = IOBUFSIZ; | if (rsiz > (int64_t)sizeof(stack)) rsiz = sizeof(stack); | |||
if (!file_.read_fast(off, stack, rsiz)) { | if (!file_.read_fast(off, stack, rsiz)) { | |||
set_error(_KCCODELINE_, Error::SYSTEM, file_.error()); | set_error(_KCCODELINE_, Error::SYSTEM, file_.error()); | |||
return false; | return false; | |||
} | } | |||
const char* rp = stack; | const char* rp = stack; | |||
const char* pv = rp; | const char* pv = rp; | |||
const char* ep = rp + rsiz; | const char* ep = rp + rsiz; | |||
while (rp < ep) { | while (rp < ep) { | |||
if (*rp == '\n') { | if (*rp == '\n') { | |||
line.append(pv, rp - pv); | ||||
char kbuf[NUMBUFSIZ]; | char kbuf[NUMBUFSIZ]; | |||
size_t ksiz = std::sprintf(kbuf, "%020lld", (long long)(off + pv | size_t ksiz = write_key(kbuf, off + pv - stack); | |||
- stack)); | const char* vbuf; | |||
size_t vsiz; | size_t vsiz; | |||
const char* vbuf = visitor->visit_full(kbuf, ksiz, line.data(), l | if (line.empty()) { | |||
ine.size(), &vsiz); | vbuf = visitor->visit_full(kbuf, ksiz, pv, rp - pv, &vsiz); | |||
} else { | ||||
line.append(pv, rp - pv); | ||||
vbuf = visitor->visit_full(kbuf, ksiz, line.data(), line.size() | ||||
, &vsiz); | ||||
line.clear(); | ||||
} | ||||
if (vbuf != Visitor::NOP && vbuf != Visitor::REMOVE) { | if (vbuf != Visitor::NOP && vbuf != Visitor::REMOVE) { | |||
char tstack[IOBUFSIZ]; | char tstack[IOBUFSIZ]; | |||
size_t trsiz = vsiz + 1; | size_t trsiz = vsiz + 1; | |||
char* trbuf = trsiz > sizeof(tstack) ? new char[trsiz] : tstack ; | char* trbuf = trsiz > sizeof(tstack) ? new char[trsiz] : tstack ; | |||
std::memcpy(trbuf, vbuf, vsiz); | std::memcpy(trbuf, vbuf, vsiz); | |||
trbuf[vsiz] = '\n'; | trbuf[vsiz] = '\n'; | |||
if (!file_.append(trbuf, trsiz)) { | if (!file_.append(trbuf, trsiz)) { | |||
set_error(_KCCODELINE_, Error::SYSTEM, file_.error()); | set_error(_KCCODELINE_, Error::SYSTEM, file_.error()); | |||
if (trbuf != stack) delete[] trbuf; | if (trbuf != stack) delete[] trbuf; | |||
return false; | return false; | |||
} | } | |||
if (trbuf != tstack) delete[] trbuf; | if (trbuf != tstack) delete[] trbuf; | |||
} | } | |||
curcnt++; | curcnt++; | |||
if (checker && !checker->check("iterate", "processing", curcnt, - 1)) { | if (checker && !checker->check("iterate", "processing", curcnt, - 1)) { | |||
set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); | set_error(_KCCODELINE_, Error::LOGIC, "checker failed"); | |||
return false; | return false; | |||
} | } | |||
line.clear(); | ||||
rp++; | rp++; | |||
pv = rp; | pv = rp; | |||
} else { | } else { | |||
rp++; | rp++; | |||
} | } | |||
} | } | |||
line.append(pv, rp - pv); | line.append(pv, rp - pv); | |||
off += rsiz; | off += rsiz; | |||
} | } | |||
if (checker && !checker->check("iterate", "ending", -1, -1)) { | if (checker && !checker->check("iterate", "ending", -1, -1)) { | |||
skipping to change at line 1062 | skipping to change at line 1071 | |||
} | } | |||
private: | private: | |||
void run() { | void run() { | |||
TextDB* db = db_; | TextDB* db = db_; | |||
File* file = &db->file_; | File* file = &db->file_; | |||
Visitor* visitor = visitor_; | Visitor* visitor = visitor_; | |||
ProgressChecker* checker = checker_; | ProgressChecker* checker = checker_; | |||
int64_t off = begoff_; | int64_t off = begoff_; | |||
int64_t end = endoff_; | int64_t end = endoff_; | |||
std::string line; | std::string line; | |||
char stack[IOBUFSIZ]; | char stack[IOBUFSIZ*4]; | |||
while (off < end) { | while (off < end) { | |||
int64_t rsiz = end - off; | int64_t rsiz = end - off; | |||
if (rsiz > (int64_t)IOBUFSIZ) rsiz = IOBUFSIZ; | if (rsiz > (int64_t)sizeof(stack)) rsiz = sizeof(stack); | |||
if (!file->read_fast(off, stack, rsiz)) { | if (!file->read_fast(off, stack, rsiz)) { | |||
db->set_error(_KCCODELINE_, Error::SYSTEM, file->error()); | db->set_error(_KCCODELINE_, Error::SYSTEM, file->error()); | |||
return; | return; | |||
} | } | |||
const char* rp = stack; | const char* rp = stack; | |||
const char* pv = rp; | const char* pv = rp; | |||
const char* ep = rp + rsiz; | const char* ep = rp + rsiz; | |||
while (rp < ep) { | while (rp < ep) { | |||
if (*rp == '\n') { | if (*rp == '\n') { | |||
line.append(pv, rp - pv); | ||||
char kbuf[NUMBUFSIZ]; | char kbuf[NUMBUFSIZ]; | |||
size_t ksiz = std::sprintf(kbuf, "%020lld", (long long)(off | size_t ksiz = db->write_key(kbuf, off + pv - stack); | |||
+ pv - stack)); | if (line.empty()) { | |||
size_t vsiz; | size_t vsiz; | |||
const char* vbuf = visitor->visit_full(kbuf, ksiz, line.dat | visitor->visit_full(kbuf, ksiz, pv, rp - pv, &vsiz); | |||
a(), line.size(), | } else { | |||
&vsiz); | line.append(pv, rp - pv); | |||
if (vbuf != Visitor::NOP && vbuf != Visitor::REMOVE) { | size_t vsiz; | |||
char tstack[IOBUFSIZ]; | visitor->visit_full(kbuf, ksiz, line.data(), line.size(), | |||
size_t trsiz = vsiz + 1; | &vsiz); | |||
char* trbuf = trsiz > sizeof(tstack) ? new char[trsiz] : | line.clear(); | |||
tstack; | ||||
std::memcpy(trbuf, vbuf, vsiz); | ||||
trbuf[vsiz] = '\n'; | ||||
if (!file->append(trbuf, trsiz)) { | ||||
db->set_error(_KCCODELINE_, Error::SYSTEM, file->error( | ||||
)); | ||||
if (trbuf != stack) delete[] trbuf; | ||||
return; | ||||
} | ||||
if (trbuf != tstack) delete[] trbuf; | ||||
} | } | |||
if (checker && !checker->check("iterate", "processing", -1, -1)) { | if (checker && !checker->check("iterate", "processing", -1, -1)) { | |||
db->set_error(_KCCODELINE_, Error::LOGIC, "checker failed "); | db->set_error(_KCCODELINE_, Error::LOGIC, "checker failed "); | |||
return; | return; | |||
} | } | |||
line.clear(); | ||||
rp++; | rp++; | |||
pv = rp; | pv = rp; | |||
} else { | } else { | |||
rp++; | rp++; | |||
} | } | |||
} | } | |||
line.append(pv, rp - pv); | line.append(pv, rp - pv); | |||
off += rsiz; | off += rsiz; | |||
} | } | |||
} | } | |||
skipping to change at line 1187 | skipping to change at line 1187 | |||
_assert_(true); | _assert_(true); | |||
if (curs_.empty()) return; | if (curs_.empty()) return; | |||
CursorList::const_iterator cit = curs_.begin(); | CursorList::const_iterator cit = curs_.begin(); | |||
CursorList::const_iterator citend = curs_.end(); | CursorList::const_iterator citend = curs_.end(); | |||
while (cit != citend) { | while (cit != citend) { | |||
Cursor* cur = *cit; | Cursor* cur = *cit; | |||
cur->off_ = INT64MAX; | cur->off_ = INT64MAX; | |||
++cit; | ++cit; | |||
} | } | |||
} | } | |||
/** | ||||
* Write the key pattern into a buffer. | ||||
* @param kbuf the destination buffer. | ||||
* @param off the offset of the record. | ||||
* @return the size of the key pattern. | ||||
*/ | ||||
size_t write_key(char* kbuf, int64_t off) { | ||||
_assert_(kbuf && off >= 0); | ||||
for (size_t i = 0; i < sizeof(off); i++) { | ||||
uint8_t c = off >> ((sizeof(off) - 1 - i) * 8); | ||||
uint8_t h = c >> 4; | ||||
if (h < 10) { | ||||
*(kbuf++) = '0' + h; | ||||
} else { | ||||
*(kbuf++) = 'A' - 10 + h; | ||||
} | ||||
uint8_t l = c & 0xf; | ||||
if (l < 10) { | ||||
*(kbuf++) = '0' + l; | ||||
} else { | ||||
*(kbuf++) = 'A' - 10 + l; | ||||
} | ||||
} | ||||
return sizeof(off) * 2; | ||||
} | ||||
/** Dummy constructor to forbid the use. */ | /** Dummy constructor to forbid the use. */ | |||
TextDB(const TextDB&); | TextDB(const TextDB&); | |||
/** Dummy Operator to forbid the use. */ | /** Dummy Operator to forbid the use. */ | |||
TextDB& operator =(const TextDB&); | TextDB& operator =(const TextDB&); | |||
/** The method lock. */ | /** The method lock. */ | |||
RWLock mlock_; | RWLock mlock_; | |||
/** The last happened error. */ | /** The last happened error. */ | |||
TSD<Error> error_; | TSD<Error> error_; | |||
/** The internal logger. */ | /** The internal logger. */ | |||
Logger* logger_; | Logger* logger_; | |||
End of changes. 23 change blocks. | ||||
39 lines changed or deleted | 60 lines changed or added | |||
kcutil.h | kcutil.h | |||
---|---|---|---|---|
skipping to change at line 352 | skipping to change at line 352 | |||
std::string* strtoupper(std::string* str); | std::string* strtoupper(std::string* str); | |||
/** | /** | |||
* Convert the letters of a string into lower case. | * Convert the letters of a string into lower case. | |||
* @param str the string to convert. | * @param str the string to convert. | |||
* @return the string itself. | * @return the string itself. | |||
*/ | */ | |||
std::string* strtolower(std::string* str); | std::string* strtolower(std::string* str); | |||
/** | /** | |||
* Check whether a string begins with a key. | ||||
* @param str the string. | ||||
* @param key the forward matching key string. | ||||
* @return true if the target string begins with the key, else, it is false | ||||
. | ||||
*/ | ||||
bool strfwm(const std::string& str, const std::string& key); | ||||
/** | ||||
* Check whether a string ends with a key. | ||||
* @param str the string. | ||||
* @param key the backward matching key string. | ||||
* @return true if the target string ends with the key, else, it is false. | ||||
*/ | ||||
bool strbwm(const std::string& str, const std::string& key); | ||||
/** | ||||
* Cut space characters at head or tail of a string. | * Cut space characters at head or tail of a string. | |||
* @param str the string to convert. | * @param str the string to convert. | |||
* @return the string itself. | * @return the string itself. | |||
*/ | */ | |||
std::string* strtrim(std::string* str); | std::string* strtrim(std::string* str); | |||
/** | /** | |||
* Convert a UTF-8 string into a UCS-4 vector. | * Convert a UTF-8 string into a UCS-4 array. | |||
* @param src the source object. | * @param src the source object. | |||
* @param dest the destination object. | * @param dest the destination object. | |||
*/ | */ | |||
void strutftoucs(const std::string& src, std::vector<uint32_t>* dest); | void strutftoucs(const std::string& src, std::vector<uint32_t>* dest); | |||
/** | /** | |||
* Convert a UCS-4 vector into a UTF-8 string. | * Convert a UCS-4 array into a UTF-8 string. | |||
* @param src the source object. | * @param src the source object. | |||
* @param dest the destination object. | * @param dest the destination object. | |||
*/ | */ | |||
void strucstoutf(const std::vector<uint32_t>& src, std::string* dest); | void strucstoutf(const std::vector<uint32_t>& src, std::string* dest); | |||
/** | /** | |||
* Serialize a string vector object into a string object. | * Serialize a string vector object into a string object. | |||
* @param src the source object. | * @param src the source object. | |||
* @param dest the destination object. | * @param dest the destination object. | |||
*/ | */ | |||
skipping to change at line 639 | skipping to change at line 655 | |||
/** | /** | |||
* Check whether a string ends with a key by case insensitive evaluation. | * Check whether a string ends with a key by case insensitive evaluation. | |||
* @param str the string. | * @param str the string. | |||
* @param key the backward matching key string. | * @param key the backward matching key string. | |||
* @return true if the target string ends with the key, else, it is false. | * @return true if the target string ends with the key, else, it is false. | |||
*/ | */ | |||
bool stribwm(const char* str, const char* key); | bool stribwm(const char* str, const char* key); | |||
/** | /** | |||
* Convert a UTF-8 string into a UCS-4 vector. | * Get the number of characters in a UTF-8 string. | |||
* @param str the UTF-8 string. | ||||
* @return the number of characters in the string. | ||||
*/ | ||||
size_t strutflen(const char* str); | ||||
/** | ||||
* Convert a UTF-8 string into a UCS-4 array. | ||||
* @param src the source object. | * @param src the source object. | |||
* @param dest the destination object. It must have enough size. | * @param dest the destination object. It must have enough size. | |||
* @param np the pointer to the variable into which the number of elements in the destination | * @param np the pointer to the variable into which the number of elements in the destination | |||
* object is assgined. | * object is assgined. | |||
*/ | */ | |||
void strutftoucs(const char* src, uint32_t* dest, size_t* np); | void strutftoucs(const char* src, uint32_t* dest, size_t* np); | |||
/** | /** | |||
* Convert a UCS-4 vector into a UTF-8 string. | * Convert a UCS-4 array into a UTF-8 string. | |||
* @param src the source object. | * @param src the source object. | |||
* @param snum the number of elements in the source object. | * @param snum the number of elements in the source object. | |||
* @param dest the destination object. It must have enough size. | * @param dest the destination object. It must have enough size. | |||
* @return the size of the result string. | * @return the size of the result string. | |||
*/ | */ | |||
size_t strucstoutf(const uint32_t* src, size_t snum, char* dest); | size_t strucstoutf(const uint32_t* src, size_t snum, char* dest); | |||
/** | /** | |||
* Allocate a region on memory. | * Allocate a region on memory. | |||
* @param size the size of the region. | * @param size the size of the region. | |||
skipping to change at line 1547 | skipping to change at line 1570 | |||
_assert_(str); | _assert_(str); | |||
size_t size = str->size(); | size_t size = str->size(); | |||
for (size_t i = 0; i < size; i++) { | for (size_t i = 0; i < size; i++) { | |||
int32_t c = (unsigned char)(*str)[i]; | int32_t c = (unsigned char)(*str)[i]; | |||
if (c >= 'A' && c <= 'Z') (*str)[i] = c + ('a' - 'A'); | if (c >= 'A' && c <= 'Z') (*str)[i] = c + ('a' - 'A'); | |||
} | } | |||
return str; | return str; | |||
} | } | |||
/** | /** | |||
* Check whether a string begins with a key. | ||||
*/ | ||||
inline bool strfwm(const std::string& str, const std::string& key) { | ||||
_assert_(true); | ||||
size_t ksiz = key.size(); | ||||
if (ksiz > str.size()) return false; | ||||
return !std::memcmp(str.data(), key.data(), ksiz); | ||||
} | ||||
/** | ||||
* Check whether a string ends with a key. | ||||
*/ | ||||
inline bool strbwm(const std::string& str, const std::string& key) { | ||||
_assert_(true); | ||||
size_t ksiz = key.size(); | ||||
if (ksiz > str.size()) return false; | ||||
return !std::memcmp(str.data() + str.size() - ksiz, key.data(), ksiz); | ||||
} | ||||
/** | ||||
* Cut space characters at head or tail of a string. | * Cut space characters at head or tail of a string. | |||
*/ | */ | |||
inline std::string* strtrim(std::string* str) { | inline std::string* strtrim(std::string* str) { | |||
_assert_(str); | _assert_(str); | |||
size_t size = str->size(); | size_t size = str->size(); | |||
size_t wi = 0; | size_t wi = 0; | |||
size_t li = 0; | size_t li = 0; | |||
for (size_t i = 0; i < size; i++) { | for (size_t i = 0; i < size; i++) { | |||
int32_t c = (unsigned char)(*str)[i]; | int32_t c = (unsigned char)(*str)[i]; | |||
if (c >= '\0' && c <= ' ') { | if (c >= '\0' && c <= ' ') { | |||
skipping to change at line 1568 | skipping to change at line 1611 | |||
} else { | } else { | |||
(*str)[wi++] = c; | (*str)[wi++] = c; | |||
li = wi; | li = wi; | |||
} | } | |||
} | } | |||
str->resize(li); | str->resize(li); | |||
return str; | return str; | |||
} | } | |||
/** | /** | |||
* Convert a UTF-8 string into a UCS-4 vector. | * Convert a UTF-8 string into a UCS-4 array. | |||
*/ | */ | |||
inline void strutftoucs(const std::string& src, std::vector<uint32_t>* dest ) { | inline void strutftoucs(const std::string& src, std::vector<uint32_t>* dest ) { | |||
_assert_(dest); | _assert_(dest); | |||
dest->reserve(dest->size() + src.size()); | dest->reserve(dest->size() + src.size()); | |||
size_t size = src.size(); | size_t size = src.size(); | |||
size_t ri = 0; | size_t ri = 0; | |||
while (ri < size) { | while (ri < size) { | |||
uint32_t c = (unsigned char)src[ri]; | uint32_t c = (unsigned char)src[ri]; | |||
if (c < 0x80) { | if (c < 0x80) { | |||
dest->push_back(c); | dest->push_back(c); | |||
} else if (c < 0xe0) { | } else if (c < 0xe0) { | |||
if (ri + 1 < size) { | if (c >= 0xc0 && ri + 1 < size) { | |||
dest->push_back(((c & 0x1f) << 6) | (src[ri+1] & 0x3f)); | c = ((c & 0x1f) << 6) | (src[ri+1] & 0x3f); | |||
if (c >= 0x80) dest->push_back(c); | ||||
ri++; | ri++; | |||
} | } | |||
} else if (c < 0xf0) { | } else if (c < 0xf0) { | |||
if (ri + 2 < size) { | if (ri + 2 < size) { | |||
dest->push_back(((c & 0x0f) << 12) | ((src[ri+1] & 0x3f) << 6) | (s | c = ((c & 0x0f) << 12) | ((src[ri+1] & 0x3f) << 6) | (src[ri+2] & 0 | |||
rc[ri+2] & 0x3f)); | x3f); | |||
if (c >= 0x800) dest->push_back(c); | ||||
ri += 2; | ri += 2; | |||
} | } | |||
} else if (c < 0xf8) { | } else if (c < 0xf8) { | |||
if (ri + 3 < size) { | if (ri + 3 < size) { | |||
dest->push_back(((c & 0x07) << 18) | ((src[ri+1] & 0x3f) << 12) | | c = ((c & 0x07) << 18) | ((src[ri+1] & 0x3f) << 12) | ((src[ri+2] & | |||
((src[ri+2] & 0x3f) << 6) | (src[ri+3] & 0x3f)); | 0x3f) << 6) | | |||
(src[ri+3] & 0x3f); | ||||
if (c >= 0x10000) dest->push_back(c); | ||||
ri += 3; | ri += 3; | |||
} | } | |||
} else if (c < 0xfc) { | } else if (c < 0xfc) { | |||
if (ri + 4 < size) { | if (ri + 4 < size) { | |||
dest->push_back(((c & 0x03) << 24) | ((src[ri+1] & 0x3f) << 18) | | c = ((c & 0x03) << 24) | ((src[ri+1] & 0x3f) << 18) | ((src[ri+2] & | |||
((src[ri+2] & 0x3f) << 12) | ((src[ri+3] & 0x3f) << | 0x3f) << 12) | | |||
6) | | ((src[ri+3] & 0x3f) << 6) | (src[ri+4] & 0x3f); | |||
(src[ri+4] & 0x3f)); | if (c >= 0x200000) dest->push_back(c); | |||
ri += 4; | ri += 4; | |||
} | } | |||
} else if (c < 0xfe) { | } else if (c < 0xfe) { | |||
if (ri + 5 < size) { | if (ri + 5 < size) { | |||
dest->push_back(((c & 0x01) << 30) | ((src[ri+1] & 0x3f) << 24) | | c = ((c & 0x01) << 30) | ((src[ri+1] & 0x3f) << 24) | ((src[ri+2] & | |||
((src[ri+2] & 0x3f) << 18) | ((src[ri+3] & 0x3f) << | 0x3f) << 18) | | |||
12) | | ((src[ri+3] & 0x3f) << 12) | ((src[ri+4] & 0x3f) << 6) | (src[r | |||
((src[ri+4] & 0x3f) << 6) | (src[ri+5] & 0x3f)); | i+5] & 0x3f); | |||
if (c >= 0x4000000) dest->push_back(c); | ||||
ri += 5; | ri += 5; | |||
} | } | |||
} | } | |||
ri++; | ri++; | |||
} | } | |||
} | } | |||
/** | /** | |||
* Convert a UCS-4 array into a UTF-8 string. | * Convert a UCS-4 array into a UTF-8 string. | |||
*/ | */ | |||
skipping to change at line 2434 | skipping to change at line 2480 | |||
int32_t sc = str[slen-i]; | int32_t sc = str[slen-i]; | |||
if (sc >= 'A' && sc <= 'Z') sc += 'a' - 'A'; | if (sc >= 'A' && sc <= 'Z') sc += 'a' - 'A'; | |||
int32_t kc = key[klen-i]; | int32_t kc = key[klen-i]; | |||
if (kc >= 'A' && kc <= 'Z') kc += 'a' - 'A'; | if (kc >= 'A' && kc <= 'Z') kc += 'a' - 'A'; | |||
if (sc != kc) return false; | if (sc != kc) return false; | |||
} | } | |||
return true; | return true; | |||
} | } | |||
/** | /** | |||
* Convert a UTF-8 string into a UCS-4 vector. | * Get the number of characters in a UTF-8 string. | |||
*/ | ||||
inline size_t strutflen(const char* str) { | ||||
_assert_(str); | ||||
size_t len = 0; | ||||
while (*str != '\0') { | ||||
len += (*(unsigned char*)str & 0xc0) != 0x80; | ||||
str++; | ||||
} | ||||
return len; | ||||
} | ||||
/** | ||||
* Convert a UTF-8 string into a UCS-4 array. | ||||
*/ | */ | |||
inline void strutftoucs(const char* src, uint32_t* dest, size_t* np) { | inline void strutftoucs(const char* src, uint32_t* dest, size_t* np) { | |||
_assert_(src && dest && np); | _assert_(src && dest && np); | |||
const unsigned char* rp = (unsigned char*)src; | const unsigned char* rp = (unsigned char*)src; | |||
size_t dnum = 0; | size_t dnum = 0; | |||
while (*rp != '\0') { | while (*rp != '\0') { | |||
uint32_t c = *rp; | uint32_t c = *rp; | |||
if (c < 0x80) { | if (c < 0x80) { | |||
dest[dnum++] = c; | dest[dnum++] = c; | |||
} else if (c < 0xe0) { | } else if (c < 0xe0) { | |||
if (rp[1] != '\0') { | if (rp[1] != '\0') { | |||
dest[dnum++] = ((c & 0x1f) << 6) | (rp[1] & 0x3f); | c = ((c & 0x1f) << 6) | (rp[1] & 0x3f); | |||
if (c >= 0x80) dest[dnum++] = c; | ||||
rp++; | rp++; | |||
} | } | |||
} else if (c < 0xf0) { | } else if (c < 0xf0) { | |||
if (rp[1] != '\0' && rp[2] != '\0') { | if (rp[1] != '\0' && rp[2] != '\0') { | |||
dest[dnum++] = ((c & 0x0f) << 12) | ((rp[1] & 0x3f) << 6) | (rp[2] | c = ((c & 0x0f) << 12) | ((rp[1] & 0x3f) << 6) | (rp[2] & 0x3f); | |||
& 0x3f); | if (c >= 0x800) dest[dnum++] = c; | |||
rp += 2; | rp += 2; | |||
} | } | |||
} else if (c < 0xf8) { | } else if (c < 0xf8) { | |||
if (rp[1] != '\0' && rp[2] != '\0' && rp[3] != '\0') { | if (rp[1] != '\0' && rp[2] != '\0' && rp[3] != '\0') { | |||
dest[dnum++] = ((c & 0x07) << 18) | ((rp[1] & 0x3f) << 12) | c = ((c & 0x07) << 18) | ((rp[1] & 0x3f) << 12) | ((rp[2] & 0x3f) < | |||
| ((rp[2] & 0x3f) << 6) | (rp[3] & 0x3f); | < 6) | | |||
(rp[3] & 0x3f); | ||||
if (c >= 0x10000) dest[dnum++] = c; | ||||
rp += 3; | rp += 3; | |||
} | } | |||
} else if (c < 0xfc) { | } else if (c < 0xfc) { | |||
if (rp[1] != '\0' && rp[2] != '\0' && rp[3] != '\0' && rp[4] != '\0') { | if (rp[1] != '\0' && rp[2] != '\0' && rp[3] != '\0' && rp[4] != '\0') { | |||
dest[dnum++] = ((c & 0x03) << 24) | ((rp[1] & 0x3f) << 18) | | c = ((c & 0x03) << 24) | ((rp[1] & 0x3f) << 18) | ((rp[2] & 0x3f) < | |||
((rp[2] & 0x3f) << 12) | ((rp[3] & 0x3f) << 6) | (rp[4] & 0x3f) | < 12) | | |||
; | ((rp[3] & 0x3f) << 6) | (rp[4] & 0x3f); | |||
if (c >= 0x200000) dest[dnum++] = c; | ||||
rp += 4; | rp += 4; | |||
} | } | |||
} else if (c < 0xfe) { | } else if (c < 0xfe) { | |||
if (rp[1] != '\0' && rp[2] != '\0' && rp[3] != '\0' && rp[4] != '\0' && rp[5] != '\0') { | if (rp[1] != '\0' && rp[2] != '\0' && rp[3] != '\0' && rp[4] != '\0' && rp[5] != '\0') { | |||
dest[dnum++] = ((c & 0x01) << 30) | ((rp[1] & 0x3f) << 24) | | c = ((c & 0x01) << 30) | ((rp[1] & 0x3f) << 24) | ((rp[2] & 0x3f) < | |||
((rp[2] & 0x3f) << 18) | ((rp[3] & 0x3f) << 12) | | < 18) | | |||
((rp[4] & 0x3f) << 6) | (rp[5] & 0x3f); | ((rp[3] & 0x3f) << 12) | ((rp[4] & 0x3f) << 6) | (rp[5] & 0x3f) | |||
; | ||||
if (c >= 0x4000000) dest[dnum++] = c; | ||||
rp += 5; | rp += 5; | |||
} | } | |||
} | } | |||
rp++; | rp++; | |||
} | } | |||
*np = dnum; | *np = dnum; | |||
} | } | |||
/** | /** | |||
* Convert a UCS-4 array into a UTF-8 string. | * Convert a UCS-4 array into a UTF-8 string. | |||
End of changes. 18 change blocks. | ||||
31 lines changed or deleted | 99 lines changed or added | |||