diff options
Diffstat (limited to 'plugins/Dbx_kyoto/src/kyotocabinet/kcmap.h')
| -rw-r--r-- | plugins/Dbx_kyoto/src/kyotocabinet/kcmap.h | 1379 |
1 files changed, 0 insertions, 1379 deletions
diff --git a/plugins/Dbx_kyoto/src/kyotocabinet/kcmap.h b/plugins/Dbx_kyoto/src/kyotocabinet/kcmap.h deleted file mode 100644 index 7729c6504a..0000000000 --- a/plugins/Dbx_kyoto/src/kyotocabinet/kcmap.h +++ /dev/null @@ -1,1379 +0,0 @@ -/************************************************************************************************* - * Data mapping structures - * Copyright (C) 2009-2012 FAL Labs - * This file is part of Kyoto Cabinet. - * This program is free software: you can redistribute it and/or modify it under the terms of - * the GNU General Public License as published by the Free Software Foundation, either version - * 3 of the License, or any later version. - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. - * You should have received a copy of the GNU General Public License along with this program. - * If not, see <http://www.gnu.org/licenses/>. - *************************************************************************************************/ - - -#ifndef _KCMAP_H // duplication check -#define _KCMAP_H - -#include <kccommon.h> -#include <kcutil.h> - -namespace kyotocabinet { // common namespace - - -/** - * Doubly-linked hash map. - * @param KEY the key type. - * @param VALUE the value type. - * @param HASH the hash functor. - * @param EQUALTO the equality checking functor. - */ -template <class KEY, class VALUE, - class HASH = std::hash<KEY>, class EQUALTO = std::equal_to<KEY> > -class LinkedHashMap { - public: - class Iterator; - private: - struct Record; - /** The default bucket number of hash table. */ - static const size_t MAPDEFBNUM = 31; - /** The mininum number of buckets to use mmap. */ - static const size_t MAPZMAPBNUM = 32768; - public: - /** - * Iterator of records. - */ - class Iterator { - friend class LinkedHashMap; - public: - /** - * Copy constructor. - * @param src the source object. - */ - Iterator(const Iterator& src) : map_(src.map_), rec_(src.rec_) { - _assert_(true); - } - /** - * Get the key. - */ - const KEY& key() { - _assert_(true); - return rec_->key; - } - /** - * Get the value. - */ - VALUE& value() { - _assert_(true); - return rec_->value; - } - /** - * Assignment operator from the self type. - * @param right the right operand. - * @return the reference to itself. - */ - Iterator& operator =(const Iterator& right) { - _assert_(true); - if (&right == this) return *this; - map_ = right.map_; - rec_ = right.rec_; - return *this; - } - /** - * Equality operator with the self type. - * @param right the right operand. - * @return true if the both are equal, or false if not. - */ - bool operator ==(const Iterator& right) const { - _assert_(true); - return map_ == right.map_ && rec_ == right.rec_; - } - /** - * Non-equality operator with the self type. - * @param right the right operand. - * @return false if the both are equal, or true if not. - */ - bool operator !=(const Iterator& right) const { - _assert_(true); - return map_ != right.map_ || rec_ != right.rec_; - } - /** - * Preposting increment operator. - * @return the iterator itself. - */ - Iterator& operator ++() { - _assert_(true); - rec_ = rec_->next; - return *this; - } - /** - * Postpositive increment operator. - * @return an iterator of the old position. - */ - Iterator operator ++(int) { - _assert_(true); - Iterator old(*this); - rec_ = rec_->next; - return old; - } - /** - * Preposting decrement operator. - * @return the iterator itself. - */ - Iterator& operator --() { - _assert_(true); - if (rec_) { - rec_ = rec_->prev; - } else { - rec_ = map_->last_; - } - return *this; - } - /** - * Postpositive decrement operator. - * @return an iterator of the old position. - */ - Iterator operator --(int) { - _assert_(true); - Iterator old(*this); - if (rec_) { - rec_ = rec_->prev; - } else { - rec_ = map_->last_; - } - return old; - } - private: - /** - * Constructor. - * @param map the container. - * @param rec the pointer to the current record. - */ - explicit Iterator(LinkedHashMap* map, Record* rec) : map_(map), rec_(rec) { - _assert_(map); - } - /** The container. */ - LinkedHashMap* map_; - /** The current record. */ - Record* rec_; - }; - /** - * Moving Modes. - */ - enum MoveMode { - MCURRENT, ///< keep the current position - MFIRST, ///< move to the first - MLAST ///< move to the last - }; - /** - * Default constructor. - */ - explicit LinkedHashMap() : - buckets_(NULL), bnum_(MAPDEFBNUM), first_(NULL), last_(NULL), count_(0) { - _assert_(true); - initialize(); - } - /** - * Constructor. - * @param bnum the number of buckets of the hash table. - */ - explicit LinkedHashMap(size_t bnum) : - buckets_(NULL), bnum_(bnum), first_(NULL), last_(NULL), count_(0) { - _assert_(true); - if (bnum_ < 1) bnum_ = MAPDEFBNUM; - initialize(); - } - /** - * Destructor. - */ - ~LinkedHashMap() { - _assert_(true); - destroy(); - } - /** - * Store a record. - * @param key the key. - * @param value the value. - * @param mode the moving mode. - * @return the pointer to the value of the stored record. - */ - VALUE *set(const KEY& key, const VALUE& value, MoveMode mode) { - _assert_(true); - size_t bidx = hash_(key) % bnum_; - Record* rec = buckets_[bidx]; - Record** entp = buckets_ + bidx; - while (rec) { - if (equalto_(rec->key, key)) { - rec->value = value; - switch (mode) { - default: { - break; - } - case MFIRST: { - if (first_ != rec) { - if (last_ == rec) last_ = rec->prev; - if (rec->prev) rec->prev->next = rec->next; - if (rec->next) rec->next->prev = rec->prev; - rec->prev = NULL; - rec->next = first_; - first_->prev = rec; - first_ = rec; - } - break; - } - case MLAST: { - if (last_ != rec) { - if (first_ == rec) first_ = rec->next; - if (rec->prev) rec->prev->next = rec->next; - if (rec->next) rec->next->prev = rec->prev; - rec->prev = last_; - rec->next = NULL; - last_->next = rec; - last_ = rec; - } - break; - } - } - return &rec->value; - } else { - entp = &rec->child; - rec = rec->child; - } - } - rec = new Record(key, value); - switch (mode) { - default: { - rec->prev = last_; - if (!first_) first_ = rec; - if (last_) last_->next = rec; - last_ = rec; - break; - } - case MFIRST: { - rec->next = first_; - if (!last_) last_ = rec; - if (first_) first_->prev = rec; - first_ = rec; - break; - } - } - *entp = rec; - count_++; - return &rec->value; - } - /** - * Remove a record. - * @param key the key. - * @return true on success, or false on failure. - */ - bool remove(const KEY& key) { - _assert_(true); - size_t bidx = hash_(key) % bnum_; - Record* rec = buckets_[bidx]; - Record** entp = buckets_ + bidx; - while (rec) { - if (equalto_(rec->key, key)) { - if (rec->prev) rec->prev->next = rec->next; - if (rec->next) rec->next->prev = rec->prev; - if (rec == first_) first_ = rec->next; - if (rec == last_) last_ = rec->prev; - *entp = rec->child; - count_--; - delete rec; - return true; - } else { - entp = &rec->child; - rec = rec->child; - } - } - return false; - } - /** - * Migrate a record to another map. - * @param key the key. - * @param dist the destination map. - * @param mode the moving mode. - * @return the pointer to the value of the migrated record, or NULL on failure. - */ - VALUE* migrate(const KEY& key, LinkedHashMap* dist, MoveMode mode) { - _assert_(dist); - size_t hash = hash_(key); - size_t bidx = hash % bnum_; - Record* rec = buckets_[bidx]; - Record** entp = buckets_ + bidx; - while (rec) { - if (equalto_(rec->key, key)) { - if (rec->prev) rec->prev->next = rec->next; - if (rec->next) rec->next->prev = rec->prev; - if (rec == first_) first_ = rec->next; - if (rec == last_) last_ = rec->prev; - *entp = rec->child; - count_--; - rec->child = NULL; - rec->prev = NULL; - rec->next = NULL; - bidx = hash % dist->bnum_; - Record* drec = dist->buckets_[bidx]; - entp = dist->buckets_ + bidx; - while (drec) { - if (dist->equalto_(drec->key, key)) { - if (drec->child) rec->child = drec->child; - if (drec->prev) { - rec->prev = drec->prev; - rec->prev->next = rec; - } - if (drec->next) { - rec->next = drec->next; - rec->next->prev = rec; - } - if (dist->first_ == drec) dist->first_ = rec; - if (dist->last_ == drec) dist->last_ = rec; - *entp = rec; - delete drec; - switch (mode) { - default: { - break; - } - case MFIRST: { - if (dist->first_ != rec) { - if (dist->last_ == rec) dist->last_ = rec->prev; - if (rec->prev) rec->prev->next = rec->next; - if (rec->next) rec->next->prev = rec->prev; - rec->prev = NULL; - rec->next = dist->first_; - dist->first_->prev = rec; - dist->first_ = rec; - } - break; - } - case MLAST: { - if (dist->last_ != rec) { - if (dist->first_ == rec) dist->first_ = rec->next; - if (rec->prev) rec->prev->next = rec->next; - if (rec->next) rec->next->prev = rec->prev; - rec->prev = dist->last_; - rec->next = NULL; - dist->last_->next = rec; - dist->last_ = rec; - } - break; - } - } - return &rec->value; - } else { - entp = &drec->child; - drec = drec->child; - } - } - switch (mode) { - default: { - rec->prev = dist->last_; - if (!dist->first_) dist->first_ = rec; - if (dist->last_) dist->last_->next = rec; - dist->last_ = rec; - break; - } - case MFIRST: { - rec->next = dist->first_; - if (!dist->last_) dist->last_ = rec; - if (dist->first_) dist->first_->prev = rec; - dist->first_ = rec; - break; - } - } - *entp = rec; - dist->count_++; - return &rec->value; - } else { - entp = &rec->child; - rec = rec->child; - } - } - return NULL; - } - /** - * Retrieve a record. - * @param key the key. - * @param mode the moving mode. - * @return the pointer to the value of the corresponding record, or NULL on failure. - */ - VALUE* get(const KEY& key, MoveMode mode) { - _assert_(true); - size_t bidx = hash_(key) % bnum_; - Record* rec = buckets_[bidx]; - while (rec) { - if (equalto_(rec->key, key)) { - switch (mode) { - default: { - break; - } - case MFIRST: { - if (first_ != rec) { - if (last_ == rec) last_ = rec->prev; - if (rec->prev) rec->prev->next = rec->next; - if (rec->next) rec->next->prev = rec->prev; - rec->prev = NULL; - rec->next = first_; - first_->prev = rec; - first_ = rec; - } - break; - } - case MLAST: { - if (last_ != rec) { - if (first_ == rec) first_ = rec->next; - if (rec->prev) rec->prev->next = rec->next; - if (rec->next) rec->next->prev = rec->prev; - rec->prev = last_; - rec->next = NULL; - last_->next = rec; - last_ = rec; - } - break; - } - } - return &rec->value; - } else { - rec = rec->child; - } - } - return NULL; - } - /** - * Remove all records. - */ - void clear() { - _assert_(true); - if (count_ < 1) return; - Record* rec = last_; - while (rec) { - Record* prev = rec->prev; - delete rec; - rec = prev; - } - for (size_t i = 0; i < bnum_; i++) { - buckets_[i] = NULL; - } - first_ = NULL; - last_ = NULL; - count_ = 0; - } - /** - * Get the number of records. - */ - size_t count() { - _assert_(true); - return count_; - } - /** - * Get an iterator at the first record. - */ - Iterator begin() { - _assert_(true); - return Iterator(this, first_); - } - /** - * Get an iterator of the end sentry. - */ - Iterator end() { - _assert_(true); - return Iterator(this, NULL); - } - /** - * Get an iterator at a record. - * @param key the key. - * @return the pointer to the value of the corresponding record, or NULL on failure. - */ - Iterator find(const KEY& key) { - _assert_(true); - size_t bidx = hash_(key) % bnum_; - Record* rec = buckets_[bidx]; - while (rec) { - if (equalto_(rec->key, key)) { - return Iterator(this, rec); - } else { - rec = rec->child; - } - } - return Iterator(this, NULL); - } - /** - * Get the reference of the key of the first record. - * @return the reference of the key of the first record. - */ - const KEY& first_key() { - _assert_(true); - return first_->key; - } - /** - * Get the reference of the value of the first record. - * @return the reference of the value of the first record. - */ - VALUE& first_value() { - _assert_(true); - return first_->value; - } - /** - * Get the reference of the key of the last record. - * @return the reference of the key of the last record. - */ - const KEY& last_key() { - _assert_(true); - return last_->key; - } - /** - * Get the reference of the value of the last record. - * @return the reference of the value of the last record. - */ - VALUE& last_value() { - _assert_(true); - return last_->value; - } - private: - /** - * Record data. - */ - struct Record { - KEY key; ///< key - VALUE value; ///< value - Record* child; ///< child record - Record* prev; ///< previous record - Record* next; ///< next record - /** constructor */ - explicit Record(const KEY& k, const VALUE& v) : - key(k), value(v), child(NULL), prev(NULL), next(NULL) { - _assert_(true); - } - }; - /** - * Initialize fields. - */ - void initialize() { - _assert_(true); - if (bnum_ >= MAPZMAPBNUM) { - buckets_ = (Record**)mapalloc(sizeof(*buckets_) * bnum_); - } else { - buckets_ = new Record*[bnum_]; - for (size_t i = 0; i < bnum_; i++) { - buckets_[i] = NULL; - } - } - } - /** - * Clean up fields. - */ - void destroy() { - _assert_(true); - Record* rec = last_; - while (rec) { - Record* prev = rec->prev; - delete rec; - rec = prev; - } - if (bnum_ >= MAPZMAPBNUM) { - mapfree(buckets_); - } else { - delete[] buckets_; - } - } - /** Dummy constructor to forbid the use. */ - LinkedHashMap(const LinkedHashMap&); - /** Dummy Operator to forbid the use. */ - LinkedHashMap& operator =(const LinkedHashMap&); - /** The functor of the hash function. */ - HASH hash_; - /** The functor of the equalto function. */ - EQUALTO equalto_; - /** The bucket array. */ - Record** buckets_; - /** The number of buckets. */ - size_t bnum_; - /** The first record. */ - Record* first_; - /** The last record. */ - Record* last_; - /** The number of records. */ - size_t count_; -}; - - -/** - * Memory-saving string hash map. - */ -class TinyHashMap { - public: - class Iterator; - private: - struct Record; - struct RecordComparator; - /** The default bucket number of hash table. */ - static const size_t MAPDEFBNUM = 31; - /** The mininum number of buckets to use mmap. */ - static const size_t MAPZMAPBNUM = 32768; - public: - /** - * Iterator of records. - */ - class Iterator { - friend class TinyHashMap; - public: - /** - * Constructor. - * @param map the container. - * @note This object will not be invalidated even when the map object is updated once. - * However, phantom records may be retrieved if they are removed after creation of each - * iterator. - */ - explicit Iterator(TinyHashMap* map) : map_(map), bidx_(-1), ridx_(0), recs_() { - _assert_(map); - step(); - } - /** - * Destructor. - */ - ~Iterator() { - _assert_(true); - free_records(); - } - /** - * Get the key of the current record. - * @param sp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @return the pointer to the key region of the current record, or NULL on failure. - */ - const char* get_key(size_t* sp) { - _assert_(sp); - if (ridx_ >= recs_.size()) return NULL; - Record rec(recs_[ridx_]); - *sp = rec.ksiz_; - return rec.kbuf_; - } - /** - * Get the value of the current record. - * @param sp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @return the pointer to the value region of the current record, or NULL on failure. - */ - const char* get_value(size_t* sp) { - _assert_(sp); - if (ridx_ >= recs_.size()) return NULL; - Record rec(recs_[ridx_]); - *sp = rec.vsiz_; - return rec.vbuf_; - } - /** - * Get a pair of the key and the value of the current record. - * @param ksp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @param vbp the pointer to the variable into which the pointer to the value region is - * assigned. - * @param vsp the pointer to the variable into which the size of the value region is - * assigned. - * @return the pointer to the key region, or NULL on failure. - */ - const char* get(size_t* ksp, const char** vbp, size_t* vsp) { - _assert_(ksp && vbp && vsp); - if (ridx_ >= recs_.size()) return NULL; - Record rec(recs_[ridx_]); - *ksp = rec.ksiz_; - *vbp = rec.vbuf_; - *vsp = rec.vsiz_; - return rec.kbuf_; - } - /** - * Step the cursor to the next record. - */ - void step() { - _assert_(true); - if (++ridx_ >= recs_.size()) { - ridx_ = 0; - free_records(); - while (true) { - bidx_++; - if (bidx_ >= (int64_t)map_->bnum_) return; - read_records(); - if (recs_.size() > 0) break; - } - } - } - private: - /** - * Read records of the current bucket. - */ - void read_records() { - char* rbuf = map_->buckets_[bidx_]; - while (rbuf) { - Record rec(rbuf); - size_t rsiz = sizeof(rec.child_) + sizevarnum(rec.ksiz_) + rec.ksiz_ + - sizevarnum(rec.vsiz_) + rec.vsiz_ + sizevarnum(rec.psiz_); - char* nbuf = new char[rsiz]; - std::memcpy(nbuf, rbuf, rsiz); - recs_.push_back(nbuf); - rbuf = rec.child_; - } - } - /** - * Release recources of the current records. - */ - void free_records() { - std::vector<char*>::iterator it = recs_.begin(); - std::vector<char*>::iterator itend = recs_.end(); - while (it != itend) { - char* rbuf = *it; - delete[] rbuf; - ++it; - } - recs_.clear(); - } - /** Dummy constructor to forbid the use. */ - Iterator(const Iterator&); - /** Dummy Operator to forbid the use. */ - Iterator& operator =(const Iterator&); - /** The container. */ - TinyHashMap* map_; - /** The current bucket index. */ - int64_t bidx_; - /** The current record index. */ - size_t ridx_; - /** The current records. */ - std::vector<char*> recs_; - }; - /** - * Sorter of records. - */ - class Sorter { - public: - /** - * Constructor. - * @param map the container. - * @note This object will be invalidated when the map object is updated once. - */ - explicit Sorter(TinyHashMap* map) : map_(map), ridx_(0), recs_() { - _assert_(map); - char** buckets = map_->buckets_; - size_t bnum = map_->bnum_; - for (size_t i = 0; i < bnum; i++) { - char* rbuf = buckets[i]; - while (rbuf) { - Record rec(rbuf); - recs_.push_back(rbuf); - rbuf = *(char**)rbuf; - } - } - std::sort(recs_.begin(), recs_.end(), RecordComparator()); - } - /** - * Destructor. - */ - ~Sorter() { - _assert_(true); - } - /** - * Get the key of the current record. - * @param sp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @return the pointer to the key region of the current record, or NULL on failure. - */ - const char* get_key(size_t* sp) { - _assert_(sp); - if (ridx_ >= recs_.size()) return NULL; - Record rec(recs_[ridx_]); - *sp = rec.ksiz_; - return rec.kbuf_; - } - /** - * Get the value of the current record. - * @param sp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @return the pointer to the value region of the current record, or NULL on failure. - */ - const char* get_value(size_t* sp) { - _assert_(sp); - if (ridx_ >= recs_.size()) return NULL; - Record rec(recs_[ridx_]); - *sp = rec.vsiz_; - return rec.vbuf_; - } - /** - * Get a pair of the key and the value of the current record. - * @param ksp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @param vbp the pointer to the variable into which the pointer to the value region is - * assigned. - * @param vsp the pointer to the variable into which the size of the value region is - * assigned. - * @return the pointer to the key region, or NULL on failure. - */ - const char* get(size_t* ksp, const char** vbp, size_t* vsp) { - _assert_(ksp && vbp && vsp); - if (ridx_ >= recs_.size()) return NULL; - Record rec(recs_[ridx_]); - *ksp = rec.ksiz_; - *vbp = rec.vbuf_; - *vsp = rec.vsiz_; - return rec.kbuf_; - } - /** - * Step the cursor to the next record. - */ - void step() { - _assert_(true); - ridx_++; - } - /** The container. */ - TinyHashMap* map_; - /** The current record index. */ - size_t ridx_; - /** The current records. */ - std::vector<char*> recs_; - }; - /** - * Default constructor. - */ - explicit TinyHashMap() : buckets_(NULL), bnum_(MAPDEFBNUM), count_(0) { - _assert_(true); - initialize(); - } - /** - * Constructor. - * @param bnum the number of buckets of the hash table. - */ - explicit TinyHashMap(size_t bnum) : buckets_(NULL), bnum_(bnum), count_(0) { - _assert_(true); - if (bnum_ < 1) bnum_ = MAPDEFBNUM; - initialize(); - } - /** - * Destructor. - */ - ~TinyHashMap() { - _assert_(true); - destroy(); - } - /** - * Set the value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param vbuf the pointer to the value region. - * @param vsiz the size of the value region. - * @note If no record corresponds to the key, a new record is created. If the corresponding - * record exists, the value is overwritten. - */ - void set(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) { - _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); - size_t bidx = hash_record(kbuf, ksiz) % bnum_; - char* rbuf = buckets_[bidx]; - char** entp = buckets_ + bidx; - while (rbuf) { - Record rec(rbuf); - if (rec.ksiz_ == ksiz && !std::memcmp(rec.kbuf_, kbuf, ksiz)) { - int32_t oh = (int32_t)sizevarnum(vsiz) - (int32_t)sizevarnum(rec.vsiz_); - int64_t psiz = (int64_t)(rec.vsiz_ + rec.psiz_) - (int64_t)(vsiz + oh); - if (psiz >= 0) { - rec.overwrite(rbuf, vbuf, vsiz, psiz); - } else { - Record nrec(rec.child_, kbuf, ksiz, vbuf, vsiz, 0); - delete[] rbuf; - *entp = nrec.serialize(); - } - return; - } - entp = (char**)rbuf; - rbuf = rec.child_; - } - Record nrec(NULL, kbuf, ksiz, vbuf, vsiz, 0); - *entp = nrec.serialize(); - count_++; - } - /** - * Add a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param vbuf the pointer to the value region. - * @param vsiz the size of the value region. - * @return true on success, or false on failure. - * @note If no record corresponds to the key, a new record is created. If the corresponding - * record exists, the record is not modified and false is returned. - */ - bool add(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) { - _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); - size_t bidx = hash_record(kbuf, ksiz) % bnum_; - char* rbuf = buckets_[bidx]; - char** entp = buckets_ + bidx; - while (rbuf) { - Record rec(rbuf); - if (rec.ksiz_ == ksiz && !std::memcmp(rec.kbuf_, kbuf, ksiz)) return false; - entp = (char**)rbuf; - rbuf = rec.child_; - } - Record nrec(NULL, kbuf, ksiz, vbuf, vsiz, 0); - *entp = nrec.serialize(); - count_++; - return true; - } - /** - * Replace the value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param vbuf the pointer to the value region. - * @param vsiz the size of the value region. - * @return true on success, or false on failure. - * @note If no record corresponds to the key, no new record is created and false is returned. - * If the corresponding record exists, the value is modified. - */ - bool replace(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) { - _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); - size_t bidx = hash_record(kbuf, ksiz) % bnum_; - char* rbuf = buckets_[bidx]; - char** entp = buckets_ + bidx; - while (rbuf) { - Record rec(rbuf); - if (rec.ksiz_ == ksiz && !std::memcmp(rec.kbuf_, kbuf, ksiz)) { - int32_t oh = (int32_t)sizevarnum(vsiz) - (int32_t)sizevarnum(rec.vsiz_); - int64_t psiz = (int64_t)(rec.vsiz_ + rec.psiz_) - (int64_t)(vsiz + oh); - if (psiz >= 0) { - rec.overwrite(rbuf, vbuf, vsiz, psiz); - } else { - Record nrec(rec.child_, kbuf, ksiz, vbuf, vsiz, 0); - delete[] rbuf; - *entp = nrec.serialize(); - } - return true; - } - entp = (char**)rbuf; - rbuf = rec.child_; - } - return false; - } - /** - * Append the value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param vbuf the pointer to the value region. - * @param vsiz the size of the value region. - * @note If no record corresponds to the key, a new record is created. If the corresponding - * record exists, the given value is appended at the end of the existing value. - */ - void append(const char* kbuf, size_t ksiz, const char* vbuf, size_t vsiz) { - _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ); - size_t bidx = hash_record(kbuf, ksiz) % bnum_; - char* rbuf = buckets_[bidx]; - char** entp = buckets_ + bidx; - while (rbuf) { - Record rec(rbuf); - if (rec.ksiz_ == ksiz && !std::memcmp(rec.kbuf_, kbuf, ksiz)) { - size_t nsiz = rec.vsiz_ + vsiz; - int32_t oh = (int32_t)sizevarnum(nsiz) - (int32_t)sizevarnum(rec.vsiz_); - int64_t psiz = (int64_t)(rec.vsiz_ + rec.psiz_) - (int64_t)(nsiz + oh); - if (psiz >= 0) { - rec.append(rbuf, oh, vbuf, vsiz, psiz); - } else { - psiz = nsiz + nsiz / 2; - Record nrec(rec.child_, kbuf, ksiz, "", 0, psiz); - char* nbuf = nrec.serialize(); - oh = (int32_t)sizevarnum(nsiz) - 1; - psiz = (int64_t)psiz - (int64_t)(nsiz + oh); - rec.concatenate(nbuf, rec.vbuf_, rec.vsiz_, vbuf, vsiz, psiz); - delete[] rbuf; - *entp = nbuf; - } - return; - } - entp = (char**)rbuf; - rbuf = rec.child_; - } - Record nrec(NULL, kbuf, ksiz, vbuf, vsiz, 0); - *entp = nrec.serialize(); - count_++; - } - /** - * Remove a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @return true on success, or false on failure. - * @note If no record corresponds to the key, false is returned. - */ - bool remove(const char* kbuf, size_t ksiz) { - _assert_(kbuf && ksiz <= MEMMAXSIZ); - size_t bidx = hash_record(kbuf, ksiz) % bnum_; - char* rbuf = buckets_[bidx]; - char** entp = buckets_ + bidx; - while (rbuf) { - Record rec(rbuf); - if (rec.ksiz_ == ksiz && !std::memcmp(rec.kbuf_, kbuf, ksiz)) { - *entp = rec.child_; - delete[] rbuf; - count_--; - return true; - } - entp = (char**)rbuf; - rbuf = rec.child_; - } - return false; - } - /** - * Retrieve the value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @param sp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @return the pointer to the value region of the corresponding record, or NULL on failure. - */ - const char* get(const char* kbuf, size_t ksiz, size_t* sp) { - _assert_(kbuf && ksiz <= MEMMAXSIZ && sp); - size_t bidx = hash_record(kbuf, ksiz) % bnum_; - char* rbuf = buckets_[bidx]; - while (rbuf) { - Record rec(rbuf); - if (rec.ksiz_ == ksiz && !std::memcmp(rec.kbuf_, kbuf, ksiz)) { - *sp = rec.vsiz_; - return rec.vbuf_; - } - rbuf = rec.child_; - } - return NULL; - } - /** - * Remove all records. - */ - void clear() { - _assert_(true); - if (count_ < 1) return; - for (size_t i = 0; i < bnum_; i++) { - char* rbuf = buckets_[i]; - while (rbuf) { - Record rec(rbuf); - char* child = rec.child_; - delete[] rbuf; - rbuf = child; - } - buckets_[i] = NULL; - } - count_ = 0; - } - /** - * Get the number of records. - * @return the number of records. - */ - size_t count() { - _assert_(true); - return count_; - } - /** - * Get the hash value of a record. - * @param kbuf the pointer to the key region. - * @param ksiz the size of the key region. - * @return the hash value. - */ - static size_t hash_record(const char* kbuf, size_t ksiz) { - _assert_(kbuf && ksiz <= MEMMAXSIZ); - return hashmurmur(kbuf, ksiz); - } - private: - /** - * Record data. - */ - struct Record { - /** constructor */ - Record(char* child, const char* kbuf, uint64_t ksiz, - const char* vbuf, uint64_t vsiz, uint64_t psiz) : - child_(child), kbuf_(kbuf), ksiz_(ksiz), vbuf_(vbuf), vsiz_(vsiz), psiz_(psiz) { - _assert_(kbuf && ksiz <= MEMMAXSIZ && vbuf && vsiz <= MEMMAXSIZ && psiz <= MEMMAXSIZ); - } - /** constructor */ - Record(const char* rbuf) : - child_(NULL), kbuf_(NULL), ksiz_(0), vbuf_(NULL), vsiz_(0), psiz_(0) { - _assert_(rbuf); - deserialize(rbuf); - } - /** overwrite the buffer */ - void overwrite(char* rbuf, const char* vbuf, size_t vsiz, size_t psiz) { - _assert_(rbuf && vbuf && vsiz <= MEMMAXSIZ && psiz <= MEMMAXSIZ); - char* wp = rbuf + sizeof(child_) + sizevarnum(ksiz_) + ksiz_; - wp += writevarnum(wp, vsiz); - std::memcpy(wp, vbuf, vsiz); - wp += vsiz; - writevarnum(wp, psiz); - } - /** append a value */ - void append(char* rbuf, int32_t oh, const char* vbuf, size_t vsiz, size_t psiz) { - _assert_(rbuf && vbuf && vsiz <= MEMMAXSIZ && psiz <= MEMMAXSIZ); - char* wp = rbuf + sizeof(child_) + sizevarnum(ksiz_) + ksiz_; - if (oh > 0) { - char* pv = wp + sizevarnum(vsiz_); - std::memmove(pv + oh, pv, vsiz_); - wp += writevarnum(wp, vsiz_ + vsiz); - wp = pv + oh + vsiz_; - } else { - wp += writevarnum(wp, vsiz_ + vsiz); - wp += vsiz_; - } - std::memcpy(wp, vbuf, vsiz); - wp += vsiz; - writevarnum(wp, psiz); - } - /** concatenate two values */ - void concatenate(char* rbuf, const char* ovbuf, size_t ovsiz, - const char* nvbuf, size_t nvsiz, size_t psiz) { - _assert_(rbuf && ovbuf && ovsiz <= MEMMAXSIZ && nvbuf && nvsiz <= MEMMAXSIZ); - char* wp = rbuf + sizeof(child_) + sizevarnum(ksiz_) + ksiz_; - wp += writevarnum(wp, ovsiz + nvsiz); - std::memcpy(wp, ovbuf, ovsiz); - wp += ovsiz; - std::memcpy(wp, nvbuf, nvsiz); - wp += nvsiz; - writevarnum(wp, psiz); - } - /** serialize data into a buffer */ - char* serialize() { - _assert_(true); - uint64_t rsiz = sizeof(child_) + sizevarnum(ksiz_) + ksiz_ + sizevarnum(vsiz_) + vsiz_ + - sizevarnum(psiz_) + psiz_; - char* rbuf = new char[rsiz]; - char* wp = rbuf; - *(char**)wp = child_; - wp += sizeof(child_); - wp += writevarnum(wp, ksiz_); - std::memcpy(wp, kbuf_, ksiz_); - wp += ksiz_; - wp += writevarnum(wp, vsiz_); - std::memcpy(wp, vbuf_, vsiz_); - wp += vsiz_; - writevarnum(wp, psiz_); - return rbuf; - } - /** deserialize a buffer into object */ - void deserialize(const char* rbuf) { - _assert_(rbuf); - const char* rp = rbuf; - child_ = *(char**)rp; - rp += sizeof(child_); - rp += readvarnum(rp, sizeof(ksiz_), &ksiz_); - kbuf_ = rp; - rp += ksiz_; - rp += readvarnum(rp, sizeof(vsiz_), &vsiz_); - vbuf_ = rp; - rp += vsiz_; - readvarnum(rp, sizeof(psiz_), &psiz_); - } - char* child_; ///< region of the child - const char* kbuf_; ///< region of the key - uint64_t ksiz_; ///< size of the key - const char* vbuf_; ///< region of the value - uint64_t vsiz_; ///< size of the key - uint64_t psiz_; ///< size of the padding - }; - /** - * Comparator for records. - */ - struct RecordComparator { - /** comparing operator */ - bool operator ()(char* const& abuf, char* const& bbuf) { - const char* akbuf = abuf + sizeof(char**); - uint64_t aksiz; - akbuf += readvarnum(akbuf, sizeof(aksiz), &aksiz); - const char* bkbuf = bbuf + sizeof(char**); - uint64_t bksiz; - bkbuf += readvarnum(bkbuf, sizeof(bksiz), &bksiz); - uint64_t msiz = aksiz < bksiz ? aksiz : bksiz; - for (uint64_t i = 0; i < msiz; i++) { - if (((uint8_t*)akbuf)[i] != ((uint8_t*)bkbuf)[i]) - return ((uint8_t*)akbuf)[i] < ((uint8_t*)bkbuf)[i]; - } - return (int32_t)aksiz < (int32_t)bksiz; - } - }; - /** - * Initialize fields. - */ - void initialize() { - _assert_(true); - if (bnum_ >= MAPZMAPBNUM) { - buckets_ = (char**)mapalloc(sizeof(*buckets_) * bnum_); - } else { - buckets_ = new char*[bnum_]; - for (size_t i = 0; i < bnum_; i++) { - buckets_[i] = NULL; - } - } - } - /** - * Clean up fields. - */ - void destroy() { - _assert_(true); - for (size_t i = 0; i < bnum_; i++) { - char* rbuf = buckets_[i]; - while (rbuf) { - Record rec(rbuf); - char* child = rec.child_; - delete[] rbuf; - rbuf = child; - } - } - if (bnum_ >= MAPZMAPBNUM) { - mapfree(buckets_); - } else { - delete[] buckets_; - } - } - /** Dummy constructor to forbid the use. */ - TinyHashMap(const TinyHashMap&); - /** Dummy Operator to forbid the use. */ - TinyHashMap& operator =(const TinyHashMap&); - /** The bucket array. */ - char** buckets_; - /** The number of buckets. */ - size_t bnum_; - /** The number of records. */ - size_t count_; -}; - - -/** - * Memory-saving string array list. - */ -class TinyArrayList { - public: - /** - * Default constructor. - */ - explicit TinyArrayList() : recs_() { - _assert_(true); - } - /** - * Destructor. - */ - ~TinyArrayList() { - _assert_(true); - std::deque<char*>::iterator it = recs_.begin(); - std::deque<char*>::iterator itend = recs_.end(); - while (it != itend) { - delete[] *it; - ++it; - } - } - /** - * Insert a record at the bottom of the list. - * @param buf the pointer to the record region. - * @param size the size of the record region. - */ - void push(const char* buf, size_t size) { - _assert_(buf && size <= MEMMAXSIZ); - size_t rsiz = sizevarnum(size) + size; - char* rbuf = new char[rsiz]; - char* wp = rbuf + writevarnum(rbuf, size); - std::memcpy(wp, buf, size); - recs_.push_back(rbuf); - } - /** - * Remove a record at the bottom of the list. - * @return true if the operation success, or false if there is no record in the list. - */ - bool pop() { - _assert_(true); - if (recs_.empty()) return false; - delete[] recs_.back(); - recs_.pop_back(); - return true; - } - /** - * Insert a record at the top of the list. - * @param buf the pointer to the record region. - * @param size the size of the record region. - */ - void unshift(const char* buf, size_t size) { - _assert_(buf && size <= MEMMAXSIZ); - size_t rsiz = sizevarnum(size) + size; - char* rbuf = new char[rsiz]; - char* wp = rbuf + writevarnum(rbuf, size); - std::memcpy(wp, buf, size); - recs_.push_front(rbuf); - } - /** - * Remove a record at the top of the list. - * @return true if the operation success, or false if there is no record in the list. - */ - bool shift() { - _assert_(true); - if (recs_.empty()) return false; - delete[] recs_.front(); - recs_.pop_front(); - return true; - } - /** - * Insert a record at the position of the given index of the list. - * @param buf the pointer to the record region. - * @param size the size of the record region. - * @param idx the index of the position. It must be equal to or less than the number of - * records. - */ - void insert(const char* buf, size_t size, size_t idx) { - size_t rsiz = sizevarnum(size) + size; - char* rbuf = new char[rsiz]; - char* wp = rbuf + writevarnum(rbuf, size); - std::memcpy(wp, buf, size); - recs_.insert(recs_.begin() + idx, rbuf); - } - /** - * Remove a record at the position of the given index of the list. - * @param idx the index of the position. It must be less than the number of records. - */ - void remove(size_t idx) { - _assert_(true); - std::deque<char*>::iterator it = recs_.begin() + idx; - delete[] *it; - recs_.erase(it); - } - /** - * Retrieve a record at the position of the given index of the list. - * @param idx the index of the position. It must be less than the number of records. - * @param sp the pointer to the variable into which the size of the region of the return - * value is assigned. - * @return the pointer to the region of the retrieved record. - */ - const char* get(size_t idx, size_t* sp) { - _assert_(sp); - const char* rbuf = recs_[idx]; - uint64_t rsiz; - const char* rp = rbuf + readvarnum(rbuf, sizeof(uint64_t), &rsiz); - *sp = rsiz; - return rp; - } - /** - * Remove all records. - */ - void clear() { - _assert_(true); - std::deque<char*>::iterator it = recs_.begin(); - std::deque<char*>::iterator itend = recs_.end(); - while (it != itend) { - delete[] *it; - ++it; - } - recs_.clear(); - } - /** - * Get the number of records. - * @return the number of records. - */ - size_t count() { - _assert_(true); - return recs_.size(); - } - private: - /** Dummy constructor to forbid the use. */ - TinyArrayList(const TinyArrayList&); - /** Dummy Operator to forbid the use. */ - TinyArrayList& operator =(const TinyArrayList&); - /** The record list. */ - std::deque<char*> recs_; -}; - - -} // common namespace - -#endif // duplication check - -// END OF FILE |
