]> gitweb.hamatoma.de Git - crepublib/commitdiff
Refactoring: ReSeqList to ReSeqArray, test of binarySearch()
authorhama <hama@siduction.net>
Tue, 13 Jan 2015 23:18:44 +0000 (00:18 +0100)
committerhama <hama@siduction.net>
Tue, 13 Jan 2015 23:18:44 +0000 (00:18 +0100)
14 files changed:
base/ReHashList.cpp
base/ReHashList.hpp
base/ReSeqArray.cpp [new file with mode: 0644]
base/ReSeqArray.hpp [new file with mode: 0644]
base/ReSeqList.cpp [deleted file]
base/ReSeqList.hpp [deleted file]
base/ReStringList.cpp
base/ReStringList.hpp
base/baselocations.hpp
base/rebase.hpp
cunit/basetest.cpp
cunit/cuReSeqArray.cpp [new file with mode: 0644]
cunit/cuReSeqList.cpp [deleted file]
cunit/testall.cpp

index abcfd025a092297e41ff756822f9eab1daeafa68..1b32acc1dcfad45200c34e4d81db3a3beb126a08 100644 (file)
@@ -25,14 +25,14 @@ ReArrayPosition::ReArrayPosition() :
  * Calling <code>ReHashList::prior() returns the last element.
  */
 void ReArrayPosition::behindLast(){
-       m_position = (ReSeqList::Index) -2;
+       m_position = (ReSeqArray::Index) -2;
 }
 /**
  * Sets the cursor behind the last position.
  * Calling <code>ReHashList::next() returns the first element.
  */
 void ReArrayPosition::priorFirst(){
-       m_position = (ReSeqList::Index) -1;
+       m_position = (ReSeqArray::Index) -1;
 }
 
 /** Constructor.
@@ -81,11 +81,11 @@ int ReHashList::find(const Byte* key, size_t length) const{
  */
 bool ReHashList::get(const Byte* key, size_t keyLength,
                ReByteBuffer& value) const{
-       ReSeqList::Index index;
-       ReSeqList::Tag tag;
+       ReSeqArray::Index index;
+       ReSeqArray::Tag tag;
        bool rc = m_keys.binarySearch(key, keyLength, index, &tag);
        if (rc){
-               m_values.get(ReSeqList::Index(tag), value);
+               m_values.get(ReSeqArray::Index(tag), value);
        }
        return rc;
 }
@@ -117,7 +117,7 @@ bool ReHashList::next(ReArrayPosition& position, ReByteBuffer* key,
        bool rc = position.m_position < m_keys.count();
        if (rc){
                ReByteBuffer dummy;
-               ReSeqList::Tag tag;
+               ReSeqArray::Tag tag;
                if (key == NULL)
                        key = &dummy;
                if (! m_keys.get(++position.m_position, *key, &tag)){
@@ -146,14 +146,14 @@ void ReHashList::put(const Byte* key, size_t keyLength,
                keyLength = strlen(key);
        if (valueLength == (size_t) -1)
                valueLength = strlen(value);
-       ReSeqList::Index index;
-       ReSeqList::Tag tag;
+       ReSeqArray::Index index;
+       ReSeqArray::Tag tag;
        if (m_keys.binarySearch(key, keyLength, index, &tag)){
                // replace the value:
-               m_values.set((ReSeqList::Index) tag, value, valueLength, 0);
+               m_values.set((ReSeqArray::Index) tag, value, valueLength, 0);
        } else {
                // insert a new value.
-               tag = (ReSeqList::Tag) m_values.count();
+               tag = (ReSeqArray::Tag) m_values.count();
                m_values.add(-1, value, valueLength);
                m_keys.add(index, key, keyLength, tag);
        }
index 719f519bb78300a8be5e8ad3038994364b0083bf..9eaf36c95d5d7305ce891f631d9cf3f98225a310 100644 (file)
@@ -15,7 +15,7 @@ public:
        void behindLast();
        void priorFirst();
 public:
-       ReSeqList::Index m_position;
+       ReSeqArray::Index m_position;
        bool m_forward;
 };
 /** @brief A simple associative array.
@@ -27,7 +27,7 @@ public:
 class ReHashList {
 public:
        typedef char Byte;
-       typedef ReSeqList::Sequence Sequence;
+       typedef ReSeqArray::Sequence Sequence;
 public:
        ReHashList(bool ignoreCase = false, int keyTagSize = 1,
                        int contentLengthSize = 1, int keyLengthSize = 1);
@@ -45,10 +45,10 @@ protected:
 
 protected:
        //@ Containing an array of keys.
-       ReSeqList m_keys;
+       ReSeqArray m_keys;
        //@ Containing the values. The tag of <code>m_key</code> is the index
        //@ in <code>m_values</code>.
-       ReSeqList m_values;
+       ReSeqArray m_values;
 };
 
 #endif /* REHASHLIST_H_ */
diff --git a/base/ReSeqArray.cpp b/base/ReSeqArray.cpp
new file mode 100644 (file)
index 0000000..e266dcd
--- /dev/null
@@ -0,0 +1,661 @@
+/*
+ * ReSeqArray.cpp
+ *
+ *  Created on: 19.05.2010
+ *      Author: wk
+ */
+
+#include "base/rebase.hpp"
+
+enum RELOC_SEQARRAY {
+       LC_SET_SIZES_1  = LC_SEQARRAY + 1, // 50201
+       LC_SET_SIZES_2,         // 50202
+       LC_SET_SIZES_3,         // 50203
+};
+/**
+ * @file
+ * Implementation:
+ * <b>ReSeqArray</b> is a storage for byte sequences.
+ * Each stored element is accessible by its index.
+ *
+ * A <b>Sequence</b> is a tuple (m_index, m_length, m_tag).
+ * <ul>
+ * <li>m_index is the index in a content buffer</li>
+ * <li>m_length is the length of byte sequence in the content</li>
+ * <li>m_tag is a additional info used by the list user, not in the container</li<
+ * <ul>
+ * If the lengths of the byte sequences are equal there is no need for saving
+ * the length. In this case the length is stored one time (in
+ * <code>m_commonSize</code>).
+ * The tag can be omitted if there is no need. This is controlled by
+ * <code>m_sequSize</code>.
+ *
+ * ReSeqArray contains a content buffer (<code>m_content</code>) and a table of
+ * content (<code>m_list</code>).
+ * <ul>
+ * <li>m_content stores a sequences of byte sequences. No separator is used.
+ *     The start and the length of the byte sequences are stored in m_list.</li>
+ * <li>m_list is a potentially sorted array of Sequence blocks.</li>
+ * </ul>
+ * Each new element is stored at the end of m_content, even if is a replacement
+ * for a existing element. Also deletion of an element does not free the space
+ * in m_content. But there is a method <b>pack()</b>, which removes the gaps.
+ * The lost space is available in <code>m_lost</code>.
+ */
+
+/** @brief Constructor.
+ *
+ * @param deltaList            If there is not enough space in the list (array)
+ *                                             this amount is the minimum to reserve.
+ * @param deltaList            If there is not enough space in the content buffer
+ *                                             this amount of bytes is the minimum to reserve.
+ */
+ReSeqArray::ReSeqArray(size_t deltaList, int deltaBuffer) :
+       m_content(deltaBuffer),
+       m_list(deltaList),
+       m_lost(0),
+       m_entrySize(sizeof(Index) + 1 + 8),
+       m_commonSize(INDIVIDUAL_SIZE),
+       m_sizeOfTag(sizeof (void*)),
+       m_sizeOfLength(1),
+       m_offsetOfTag(sizeof(Index) + 1),
+       m_offsetOfLength(sizeof(Index)),
+       m_sorted(false),
+       m_ignoreCase(false)
+{
+}
+/** @brief Destructor.
+ */
+ReSeqArray::~ReSeqArray() {
+}
+/** @brief Copy constructor.
+ *
+ * @param source       This instance will be copied.
+ */
+ReSeqArray::ReSeqArray(const ReSeqArray& source)
+       :
+       m_content(source.m_content),
+       m_list(source.m_list),
+       m_lost(source.m_lost),
+       m_entrySize(source.m_entrySize),
+       m_commonSize(source.m_commonSize),
+       m_sizeOfTag(source.m_sizeOfTag),
+       m_sizeOfLength(source.m_sizeOfLength),
+       m_offsetOfTag(source.m_offsetOfTag),
+       m_offsetOfLength(source.m_offsetOfLength),
+       m_sorted(source.m_sorted),
+       m_ignoreCase(false)
+{
+}
+/** @brief Assignment operator.
+ *
+ * @param source       This instance will be copied.
+ *
+ * @result     The instance itself.
+ */
+ReSeqArray& ReSeqArray::operator = (const ReSeqArray& source){
+       m_content = source.m_content;
+       m_list = source.m_list;
+       m_lost = source.m_lost;
+       m_entrySize = source.m_entrySize;
+       m_commonSize = source.m_commonSize;
+       m_sizeOfTag = source.m_sizeOfTag;
+       m_sizeOfLength = source.m_sizeOfLength;
+       m_offsetOfTag = source.m_offsetOfTag;
+       m_offsetOfLength = source.m_offsetOfLength;
+       m_sorted = source.m_sorted;
+       m_ignoreCase = source.m_ignoreCase;
+       return *this;
+}
+/** @brief Adds an element to the list.
+ *
+ * @param index                        the index of the new entry. If greater than the list length
+ *                                             it will be appended.<br>
+ *                                             For sorted arrays and this value is -1 the index position will
+ *                                             be automatically found. If sorted and not -1 the index must be
+ *                                             correct or the array will be unsorted
+ * @param source               the pointer of the byte sequence to insert
+ * @param sourceLength the length of the byte sequence to insert
+ * @param tag                  an item stored with the byte sequence. We know nothing about this
+ * @return                             the index of the element
+ */
+ReSeqArray::Index ReSeqArray::add(Index index, const Byte* source,
+               size_t sourceLength, Tag tag){
+       if (sourceLength == (size_t) -1)
+               sourceLength = strlen(source);
+       Sequence seq;
+       setSequence(&seq, m_content.length(), sourceLength, tag);
+       m_content.append(source, sourceLength);
+       Index rc = index;
+       if (m_sorted && index == (Index) -1){
+               binarySearch(source, sourceLength, rc);
+               m_list.insert(rc * m_entrySize, (Byte*) &seq, m_entrySize);
+       } else {
+               if (index >= count()){
+                       rc = m_content.length();
+                       m_list.append((Byte*) &seq, m_entrySize);
+               }else{
+                       m_list.insert(index * m_entrySize, (Byte*) &seq, m_entrySize);
+               }
+       }
+       return rc;
+}
+
+/**
+ * @brief Searches the an element with binary search.
+ *
+ * @param toFind       the value which should be found
+ * @param length       -1 or the length of <code>toFind</code>
+ * @param index     OUT: the index usable for insert:
+ *                                     index is the smallest value with content[index] >= toFind
+ * @param tag          OUT: the tag of the element (only if it was found).<br>
+ *                                     May be NULL
+ * @return                     -1: the key has been found.
+ */
+bool ReSeqArray::binarySearch(const Byte* toFind, int length, Index& index,
+                       Tag* tag) const
+{
+       assert(m_sorted);
+       if (length < 0)
+               length = strlen(toFind);
+       bool rc = false;
+   int lbound = 0;
+       int theCount = count();
+    int ubound = theCount;
+       int compareRc = 0;
+    // binary search over the sorted vector:
+    while(lbound <= ubound){
+        int half = (ubound + lbound) / 2;
+        const Sequence* seq = reinterpret_cast<const Sequence*>(
+                       m_list.str() + half * m_entrySize);
+        int currentLength = getLength(seq);
+               int minLength = currentLength < length ? currentLength : length;
+               const char* current = m_content.str() + seq->m_index;
+               compareRc = m_ignoreCase
+                       ? _memicmp(toFind, current, minLength)
+                       : _memcmp(toFind, current, minLength);
+        if (compareRc == 0 && currentLength != length)
+            compareRc = currentLength > length ? -1 : 1;
+        if (compareRc < 0)
+            ubound = half - 1;
+        else if (compareRc > 0)
+            lbound = half + 1;
+        else {
+                       rc = true;
+            index = half;
+            break;
+        }
+    }
+    if (! rc)
+               index = ubound > lbound ? ubound : lbound > theCount ? theCount : lbound;
+    return rc;
+}
+
+/** @brief Deletes all entries in the list.
+ */
+void ReSeqArray::clear(){
+       m_content.setLength(0);
+       m_list.setLength(0);
+}
+
+/**
+ * Compares two elements.
+ *
+ * @param index1       the index of the first element
+ * @param index2       the index of the second element
+ * @return                     0: element1 == element2<br>
+ *                                     < 0: element1 < element2<br>
+ *                                     > 0: element1 > element2
+ */
+int ReSeqArray::compare(Index index1, Index index2){
+       Sequence* seq1 = getInfo(index1);
+       Sequence* seq2 = getInfo(index2);
+       size_t length1 = getLength(seq1);
+       size_t length2 = getLength(seq2);
+       int minLength = length1 < length2 ? length1 : length2;
+       int rc = m_ignoreCase
+               ? _memicmp(m_content.str() + seq1->m_index,
+                                       m_content.str() + seq2->m_index, minLength)
+               : _memcmp(m_content.str() + seq1->m_index,
+                                       m_content.str() + seq2->m_index, minLength);
+       if (rc == 0 && length1 != length2)
+               rc = length1 < length2 ? -1 : 1;
+       return rc;
+}
+/**
+ * Writes the content to a stream.
+ *
+ * @param fp   target file pointer
+ */
+void ReSeqArray::dump(FILE* fp) const{
+       ReByteBuffer buffer;
+       Tag tag;
+       for (int ix = 0; ix < (int) count(); ix++){
+               get(ix, buffer, &tag);
+               fprintf(fp, "%d: (%ld) [%d] %s\n", ix, (int64_t) tag, (int) buffer.length(),
+                       buffer.str());
+       }
+}
+
+/** @brief Returns the index of a stored byte sequence.
+ *
+ * @param toFind               the byte sequence to find
+ * @param length               -1 or the length of <code>toFind</code>.
+ *
+ * @return: -1: The key was not found. Otherwise: The index of the key in the key sequence array.
+ */
+ReSeqArray::Index ReSeqArray::find(const Byte* toFind, size_t length,
+                       Tag* tag) const{
+       if (length == (size_t) -1)
+               length = strlen(toFind);
+       int rc = -1;
+       int theCount = count();
+       for (int ix = 0; ix < theCount; ix++){
+               const ReSeqArray::Sequence* seq = getInfo(ix);
+               Tag currentTag;
+               size_t currentLength = getLengthAndTag(seq, currentTag);
+               if (currentLength == length){
+                       const Byte* ptr = reinterpret_cast<const Byte*>(m_content.str()
+                                               + seq->m_index);
+                       int comparison = m_ignoreCase ? _memicmp(ptr, toFind, length)
+                                               : _memcmp(ptr, toFind, length);
+                       if (comparison == 0){
+                               rc = ix;
+                               if (tag != NULL)
+                                       *tag = currentTag;
+                               break;
+                       }
+               }
+       }
+       return rc;
+}
+
+/** @brief Returns an element from the list.
+ *
+ * @param index                The index of the sequence in the list.
+ * @param value                Out: The stored sequence will be copied here.
+ * @param tag          Out: The info which is stored with the entry. May be <code>NULL</code>.
+ *
+ * @param      true: The index is ok, the sequence is in the output buffer.
+ *                     false: No copy has been done.
+ */
+bool ReSeqArray::get(Index index, ReByteBuffer& value, Tag* tag) const{
+       bool rc = false;
+       if (index < count()){
+               const Sequence* seq = getInfo(index);
+               size_t length = tag == NULL ? getLength(seq) : getLengthAndTag(seq, *tag);
+               value.set(m_content.str() + seq->m_index, length);
+               rc = true;
+       }
+       return rc;
+}
+/** @brief Returns the byte sequence length of the element.
+ *
+ * @return     the length of the element described in the Sequence seq
+ */
+size_t ReSeqArray::getLength(const Sequence* seq) const{
+       size_t rc;
+       if (m_commonSize != INDIVIDUAL_SIZE)
+               rc = m_commonSize;
+       else {
+               const uint8_t* ptr = reinterpret_cast<const uint8_t*>(seq) + m_offsetOfLength;
+               switch (m_sizeOfLength){
+               case 1:
+                       rc = *ptr;
+                       break;
+               case 2:
+                       rc = ptr[0] + (ptr[1] << 8);
+                       break;
+               case 3:
+                       rc = ptr[0] + (ptr[1] << 8) + (ptr[1] << 16);
+                       break;
+               case 4:
+                       rc = ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24);
+                       break;
+               case 5:
+                       rc = ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24)
+                               + ((int64_t)ptr[4] << 32);
+                       break;
+               default:
+                       assert(false);
+                       rc = 0;
+                       break;
+               }
+       }
+       return rc;
+}
+/** @brief Returns the byte sequence length and the tag of an element.
+ *
+ * @param tag  OUT: the tag of the element.
+ * @return             the byte sequence length of the element
+ */
+size_t ReSeqArray::getLengthAndTag(const Sequence* seq, Tag& tag) const{
+       size_t rc;
+       if (m_commonSize != INDIVIDUAL_SIZE)
+               rc = m_commonSize;
+       else {
+               const uint8_t* ptr = reinterpret_cast<const uint8_t*>(seq) + m_offsetOfLength;
+               switch (m_sizeOfLength){
+               case 1:
+                       rc = *ptr;
+                       break;
+               case 2:
+                       rc = ptr[0] + (ptr[1] << 8);
+                       break;
+               case 3:
+                       rc = ptr[0] + (ptr[1] << 8) + (ptr[1] << 16);
+                       break;
+               case 4:
+                       rc = ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24);
+                       break;
+               case 5:
+                       rc = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24)
+                               | ((uint64_t)ptr[4] << 32);
+                       break;
+               default:
+                       assert(false);
+                       rc = 0;
+                       break;
+               }
+       }
+       const uint8_t* ptr = reinterpret_cast<const uint8_t*>(seq) + m_offsetOfTag;
+       switch (m_sizeOfTag){
+       case 0:
+               tag = 0;
+               break;
+       case 1:
+               tag = *ptr;
+               break;
+       case 2:
+               tag = ptr[0] + (ptr[1] << 8);
+               break;
+       case 3:
+               tag = ptr[0] + (ptr[1] << 8) + (ptr[2] << 16);
+               break;
+       case 4:
+               tag = ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24);
+               break;
+       case 5:
+               tag = Tag(ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (uint64_t(ptr[3]) << 24)
+                       | (uint64_t(ptr[4]) << 32));
+               break;
+       case 8:
+               tag = Tag(ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (uint64_t(ptr[3]) << 24)
+                       | (uint64_t(ptr[4]) << 32) | (uint64_t(ptr[5]) << 40)
+                       | (uint64_t(ptr[6]) << 48) | (uint64_t(ptr[7]) << 56));
+               break;
+       default:
+               assert(false);
+               tag = 0;
+               break;
+       }
+       return rc;
+}
+
+/** @brief Removes an element given by its index.
+ *
+ * @param index The index of the entry to remove.
+ */
+void ReSeqArray::remove(Index index){
+       if (index <= count()){
+               Sequence* seq = getInfo(index);
+               size_t currentLength = getLength(seq);
+               // Is this the last entry in m_content?
+               if (seq->m_index + currentLength >= m_content.length()){
+                       // We can free the content:
+                       m_content.setLength(seq->m_index);
+               } else {
+                       m_lost += currentLength;
+               }
+               // Remove the entry from the list:
+               m_list.remove(index * m_entrySize, m_entrySize);
+       }
+}
+/** @brief Replaces the byte sequence in the list.
+ *
+ * @param index                        The index of the sequence to replace.
+ * @param source               The new value.
+ * @param sourceLength The length of the new value.
+ * @param tag                  An additional info associated to the source.
+ */
+void ReSeqArray::set(Index index, const Byte* source,
+                       size_t sourceLength, Tag tag){
+       if (index >= count())
+               add(index, source, sourceLength, tag);
+       else {
+               if (sourceLength == (size_t) -1)
+                       sourceLength = strlen(source) + 1;
+               Sequence* seq = getInfo(index);
+               size_t currentLength = getLength(seq);
+               size_t indexContent;
+               if (currentLength >= sourceLength){
+                       // Use the existing space:
+                       indexContent = seq->m_index;
+                       memcpy(m_content.buffer() + indexContent, source, sourceLength);
+                       m_lost += currentLength - sourceLength;
+               } else {
+                       // New space must be allocated:
+                       m_lost += currentLength;
+                       indexContent = m_content.length();
+                       m_content.append(source, sourceLength);
+               }
+               setSequence(seq, indexContent, sourceLength, tag);
+       }
+}
+/** @brief Sets the Sequence of an element.
+ *
+ * @param seq          the target sequence
+ * @param index        the index in m_content
+ * @param length       the length of the content
+ * @param tag          the tag of the element
+ */
+void ReSeqArray::setSequence(Sequence* seq, Index index, size_t length, Tag tag){
+       seq->m_index = index;
+       if (m_commonSize == INDIVIDUAL_SIZE){
+               uint8_t* ptr = reinterpret_cast<uint8_t*>(seq) + m_offsetOfLength;
+               switch (m_sizeOfLength){
+               case 1:
+                       ptr[0] = length & 0xff;
+                       break;
+               case 2:
+                       ptr[0] = length & 0xff;
+                       ptr[1] = (length >> 8) & 0xff;
+                       break;
+               case 3:
+                       ptr[0] = length & 0xff;
+                       ptr[1] = (length >> 8) & 0xff;
+                       ptr[2] = (length >> 16) & 0xff;
+                       break;
+               case 4:
+                       ptr[0] = length & 0xff;
+                       ptr[1] = (length >> 8) & 0xff;
+                       ptr[2] = (length >> 16) & 0xff;
+                       ptr[3] = (length >> 24) & 0xff;
+                       break;
+               case 5:
+                       ptr[0] = length & 0xff;
+                       ptr[1] = (length >> 8) & 0xff;
+                       ptr[2] = (length >> 16) & 0xff;
+                       ptr[3] = (length >> 24) & 0xff;
+                       ptr[4] = (int64_t(length) >> 32) & 0xff;
+                       break;
+               default:
+                       assert(false);
+                       break;
+               }
+       }
+       if (m_sizeOfTag > 0){
+               uint8_t* ptr = reinterpret_cast<uint8_t*>(seq) + m_offsetOfTag;
+               switch (m_sizeOfTag){
+               case 1:
+                       ptr[0] = tag & 0xff;
+                       break;
+               case 2:
+                       ptr[0] = length & 0xff;
+                       ptr[1] = (tag >> 8) & 0xff;
+                       break;
+               case 3:
+                       ptr[0] = tag & 0xff;
+                       ptr[1] = (tag >> 8) & 0xff;
+                       ptr[2] = (tag >> 16) & 0xff;
+                       break;
+               case 4:
+                       ptr[0] = tag & 0xff;
+                       ptr[1] = (tag >> 8) & 0xff;
+                       ptr[2] = (tag >> 16) & 0xff;
+                       ptr[3] = (tag >> 24) & 0xff;
+                       break;
+               case 5:
+                       ptr[0] = tag & 0xff;
+                       ptr[1] = (tag >> 8) & 0xff;
+                       ptr[2] = (tag >> 16) & 0xff;
+                       ptr[3] = (tag >> 24) & 0xff;
+                       ptr[4] = (tag >> 32) & 0xff;
+                       break;
+               case 8:
+                       ptr[0] = tag & 0xff;
+                       ptr[1] = (tag >> 8) & 0xff;
+                       ptr[2] = (tag >> 16) & 0xff;
+                       ptr[3] = (tag >> 24) & 0xff;
+                       ptr[4] = (tag >> 32) & 0xff;
+                       ptr[5] = (tag >> 40) & 0xff;
+                       ptr[6] = (tag >> 48) & 0xff;
+                       ptr[7] = (tag >> 56) & 0xff;
+                       break;
+               default:
+                       assert(false);
+                       break;
+               }
+       }
+}
+
+/** @brief Sets the switch for case sensitivity.
+ *
+ * @param onNotOff     <code>true</code>: the comparison will be case insensitive
+ */
+void ReSeqArray::setIgnoreCase(bool onNotOff){
+       if (m_ignoreCase != onNotOff){
+               m_ignoreCase = onNotOff;
+               if (m_sorted)
+                       sort();
+       }
+}
+
+/** @brief Sets the switch for sorting.
+ *
+ * @param onNotOff     <code>true</code>: the list will be sorted
+ */
+void ReSeqArray::setSorted(bool onNotOff){
+       if (m_sorted != onNotOff){
+               m_sorted = onNotOff;
+               if (m_sorted)
+                       sort();
+       }
+}
+
+/**
+ * Sets the length of the stored items tag and length (in Sequence).
+ *
+ * @param sizeOfTag            0: no tag stored.
+ *                                                     Otherwise: length in byte: 1,2,3,4,5 or 8
+ * @param sizeOfLength 0: no length stored (constant length, stored in
+ *                                                     m_commonSize).
+ *                                                     Otherwise: length in byte: 1, 2, 3, 4 or 5
+ * @param constantSize  0 or the size of the sequence if the length is not
+ *                                                     indiviually stored. <br>
+ *                                                     If > 0 <code>sizeOfLength</code>must be 0!
+ */
+void ReSeqArray::setSizes(int sizeOfTag, int sizeOfLength, int constantSize){
+       switch(m_sizeOfLength = sizeOfLength){
+       case 0:
+       case 1:
+       case 2:
+       case 3:
+       case 4:
+       case 5:
+               break;
+       default:
+               globalLogger()->sayF(LOG_ERROR | CAT_LIB, LC_SET_SIZES_2,
+                       i18n("Invalid length length: $1 (instead of 0,1,2,4,5)")).arg(sizeOfTag).end();
+               m_sizeOfLength = 8;
+               break;
+       }
+       switch(m_sizeOfTag = sizeOfTag){
+       case 0:
+       case 1:
+       case 2:
+       case 3:
+       case 4:
+       case 8:
+               break;
+       default:
+               globalLogger()->sayF(LOG_ERROR | CAT_LIB, LC_SET_SIZES_1,
+                       i18n("Invalid tag length: $1 (instead of 0,1,2,3,4,8)")).arg(sizeOfTag).end();
+               m_sizeOfTag = 8;
+               break;
+       }
+       m_offsetOfLength = sizeof(Index);
+       m_offsetOfTag = sizeof(Index) + m_sizeOfLength;
+       if (sizeOfLength > 0 && constantSize > 0){
+               globalLogger()->sayF(LOG_ERROR | CAT_LIB, LC_SET_SIZES_1,
+                                       i18n("collision of sizeOfLength $1 and constantSize $2"))
+                                       .arg(sizeOfLength).arg(constantSize).end();
+               constantSize = 0;
+       }
+       m_commonSize = constantSize;
+}
+
+/** @brief Sorts the list.
+ * Note: the comparison is controlled by <code>m_ignoreCase</code>.
+ */
+void ReSeqArray::sort(){
+       // Build the heap in array so that largest value is at the root:
+       int theCount = (int) count();
+       for (int start = (theCount - 2) / 2; start >= 0; start--) {
+               // (shift down the node at index 'start' to the proper place such
+               // that all nodes below the start index are in heap order)
+               shiftDown(start, theCount);
+       }
+       // The following loop maintains the invariants that array[0:end] is a heap
+       // and every element beyond end is greater than everything before it
+       // (so array[end:count] is in sorted order)
+       for (int end = theCount - 1; end > 0; end--) {
+               // swap [end] with [0]:
+               Sequence seq;
+               Byte* ptrEnd = m_list.buffer() + end * m_entrySize;
+               memcpy(&seq, ptrEnd, m_entrySize);
+               memcpy(ptrEnd, m_list.buffer(), m_entrySize);
+               memcpy(m_list.buffer(), &seq, m_entrySize);
+               shiftDown(0, end);
+       }
+}
+/**
+ * Correct the order in the heap.
+ *
+ * @param start                the lower bound of the interval to inspect
+ * @param endEnd       the upper bound of the interval to inspect
+ */
+void ReSeqArray::shiftDown(int start, int end){
+   int root = start;
+       Sequence seq;
+       // while the root has at least one child:
+       while (root * 2 + 1 < end ) {
+               // left child:
+               int child = 2 * root + 1;
+               if (child + 1 < end && compare(child, child + 1) < 0)
+           child++;
+       if (compare(root, child) >= 0)
+                  break;
+       else
+       {
+                       // swap [child] with [root]
+                       Byte* ptrRoot = m_list.buffer() + root * m_entrySize;
+                       Byte* ptrChild = m_list.buffer() + child * m_entrySize;
+                       memcpy(&seq, ptrRoot, m_entrySize);
+                       memcpy(ptrRoot, ptrChild, m_entrySize);
+                       memcpy(ptrChild, &seq, m_entrySize);
+                       root = child;
+       }
+   }
+}
+
diff --git a/base/ReSeqArray.hpp b/base/ReSeqArray.hpp
new file mode 100644 (file)
index 0000000..92aec3b
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * ReSeqArray.h
+ *
+ *  Created on: 19.05.2010
+ *      Author: wk
+ */
+
+#ifndef RESEQLIST_H_
+#define RESEQLIST_H_
+
+#define INDIVIDUAL_SIZE (size_t(-1))
+/** @brief This class implements a dynamic (self growing) array of elements.
+ *
+ * An <b>element</b> is a tuple of a byte sequences and a tag.
+ * A <b>tag</b> is an integer value which is interpreted only by the user
+ * of the list. The list knows nothing abbout it.
+ *
+ * A <b>byte sequence</b> is an array of byte.
+ * The byte sequences may have different lengths.
+ * This implies the handling of C string arrays too.
+ */
+class ReSeqArray {
+public:
+       typedef char Byte;
+       typedef unsigned int Index;
+       typedef int64_t Tag;
+       typedef struct {
+               Index   m_index;
+               uint64_t m_length;
+               Tag             m_tag;
+       } Sequence;
+public:
+       ReSeqArray(size_t deltaList = 128, int deltaBuffer = 1024);
+       virtual ~ReSeqArray();
+       ReSeqArray(const ReSeqArray& source);
+       ReSeqArray& operator = (const ReSeqArray& source);
+public:
+       Index add(Index index, const Byte* source, size_t sourceLength, Tag tag = 0);
+       bool binarySearch(const Byte* toFind, int length, Index& index,
+                               Tag* tag = NULL) const;
+       void clear();
+       int compare(Index index1, Index index2);
+       /** @brief Returns the count of defined entries in the list.
+        * @return The number of defined entries in the list (array).
+        */
+       inline Index count() const {
+               return m_list.length() / m_entrySize;
+       }
+       void dump(FILE* fp) const;
+       Index find(const Byte* toFind, size_t length, Tag* tag = NULL) const;
+       bool get(Index index, ReByteBuffer& value, Tag* tag = NULL) const;
+       /** Returns whether the list is sorted automatically.
+        * Note: comparison is controlled by <code>m_ignoreCase</code>.
+        * @return <code>true</code> the byte sequences will be sorted
+        */
+       bool isSorted() const {
+               return m_sorted;
+       }
+       /** Returns whether the comparisons inside the list are case insensitive.
+        * @return <code>true</code> the comparisons inside the list are case insensitive
+        */
+       bool ignoreCase() const {
+               return m_ignoreCase;
+       }
+       void remove(Index index);
+       void set(Index index, const Byte* source, size_t sourceLength, Tag tag);
+       void setSizes(int sizeOfTag, int sizeOfLength, int constantLength = 0);
+       void setSorted(bool onNotOff);
+       void setIgnoreCase(bool onNotOff);
+       void sort();
+protected:
+       /** @brief Returns a pointer of the content buffer.
+        * @return A pointer of the first byte of the content buffer.
+        */
+       inline const Byte* getContent() const {
+               return m_content.buffer();
+       }
+       friend class ReHashList;
+       /** @brief Returns the info of an entry of the list.
+        * @param index         The index of the wanted entry.
+        * @return The pointer of the entry.
+        */
+       inline Sequence* getInfo(Index index) const {
+               return reinterpret_cast<Sequence*>(m_list.buffer() + m_entrySize * index);
+       }
+       size_t getLength(const Sequence* seq) const;
+       size_t getLengthAndTag(const Sequence* seq, Tag& tag) const;
+       void setSequence(Sequence* seq, Index index, size_t length, Tag tag);
+       void shiftDown(int from, int to);
+protected:
+       //@ Contains the sequences itself.
+       ReByteBuffer m_content;
+       //@ Contains an array of <code>Sequence</code>s.
+       ReByteBuffer m_list;
+       //@ If strings have been replaced/deleted the space in m_content is still allocated.
+       //@ This is the sum of lost space.
+       size_t m_lost;
+       //@ The length of a Sequence block: sizeof(seq->m_index)+m_lengthTag+m_lengthLength
+       size_t m_entrySize;
+       //@ -1: The Sequence block contains the individual length.
+       //@ 0: no content will be stored
+       //@ Otherwise: the common length of all elements in m_content
+       size_t m_commonSize;
+       //@ length of the tag: 0,1,2,4,8
+       size_t m_sizeOfTag;
+       //@ length of the length element in Sequence: 0,1,2,4
+       size_t m_sizeOfLength;
+       //@ offset of the tag (from start of Sequence)
+       size_t m_offsetOfTag;
+       //@ offset of the length (from start of Sequence)
+       size_t m_offsetOfLength;
+       bool m_sorted;
+       //@ true: the comparison will be case insensitive
+       bool m_ignoreCase;
+};
+
+#endif /* RESEQLIST_H_ */
diff --git a/base/ReSeqList.cpp b/base/ReSeqList.cpp
deleted file mode 100644 (file)
index bc9457a..0000000
+++ /dev/null
@@ -1,651 +0,0 @@
-/*
- * ReSeqList.cpp
- *
- *  Created on: 19.05.2010
- *      Author: wk
- */
-
-#include "base/rebase.hpp"
-
-enum RELOC_SEQLIST {
-       LC_SET_SIZES_1  = LC_SEQLIST + 1, // 50201
-       LC_SET_SIZES_2,         // 50202
-       LC_SET_SIZES_3,         // 50203
-};
-/**
- * Implementation:
- * <b>ReSeqList</b> is a storage for byte sequences.
- * Each stored element is accessible by its index.
- *
- * A <b>Sequence</b> is a tuple (m_index, m_length, m_tag).
- * <ul>
- * <li>m_index is the index in a content buffer</li>
- * <li>m_length is the length of byte sequence in the content</li>
- * <li>m_tag is a additional info used by the list user, not in the container</li<
- * <ul>
- * If the lengths of the byte sequences are equal there is no need for saving
- * the length. In this case the length is stored one time (in
- * <code>m_commonSize</code>).
- * The tag can be omitted if there is no need. This is controlled by
- * <code>m_sequSize</code>.
- *
- * ReSeqList contains a content buffer (<code>m_content</code>) and a table of
- * content (<code>m_list</code>).
- * <ul>
- * <li>m_content stores a sequences of byte sequences. No separator is used.
- *     The start and the length of the byte sequences are stored in m_list.</li>
- * <li>m_list is a potentially sorted array of Sequence blocks.</li>
- * </ul>
- * Each new element is stored at the end of m_content, even if is a replacement
- * for a existing element. Also deletion of an element does not free the space
- * in m_content. But there is a method <b>pack()</b>, which removes the gaps.
- * The lost space is available in <code>m_lost</code>.
- */
-
-/** @brief Constructor.
- *
- * @param deltaList            If there is not enough space in the list (array)
- *                                             this amount is the minimum to reserve.
- * @param deltaList            If there is not enough space in the content buffer
- *                                             this amount of bytes is the minimum to reserve.
- */
-ReSeqList::ReSeqList(size_t deltaList, int deltaBuffer)
-       :
-       m_content(deltaBuffer),
-       m_list(deltaList),
-       m_lost(0),
-       m_entrySize(sizeof(Index) + 1 + 8),
-       m_commonSize(INDIVIDUAL_SIZE),
-       m_sizeOfTag(sizeof (void*)),
-       m_sizeOfLength(1),
-       m_offsetOfTag(sizeof(Index) + 1),
-       m_offsetOfLength(sizeof(Index)),
-       m_sorted(false),
-       m_ignoreCase(false)
-{
-}
-/** @brief Destructor.
- */
-ReSeqList::~ReSeqList() {
-}
-/** @brief Copy constructor.
- *
- * @param source       This instance will be copied.
- */
-ReSeqList::ReSeqList(const ReSeqList& source)
-       :
-       m_content(source.m_content),
-       m_list(source.m_list),
-       m_lost(source.m_lost),
-       m_entrySize(source.m_entrySize),
-       m_commonSize(source.m_commonSize),
-       m_sizeOfTag(source.m_sizeOfTag),
-       m_sizeOfLength(source.m_sizeOfLength),
-       m_offsetOfTag(source.m_offsetOfTag),
-       m_offsetOfLength(source.m_offsetOfLength),
-       m_sorted(source.m_sorted),
-       m_ignoreCase(false)
-{
-}
-/** @brief Assignment operator.
- *
- * @param source       This instance will be copied.
- *
- * @result     The instance itself.
- */
-ReSeqList& ReSeqList::operator = (const ReSeqList& source){
-       m_content = source.m_content;
-       m_list = source.m_list;
-       m_lost = source.m_lost;
-       m_entrySize = source.m_entrySize;
-       m_commonSize = source.m_commonSize;
-       m_sizeOfTag = source.m_sizeOfTag;
-       m_sizeOfLength = source.m_sizeOfLength;
-       m_offsetOfTag = source.m_offsetOfTag;
-       m_offsetOfLength = source.m_offsetOfLength;
-       m_sorted = source.m_sorted;
-       m_ignoreCase = source.m_ignoreCase;
-       return *this;
-}
-/** @brief Adds an element to the list.
- *
- * @param index                        The index of the new entry. If greater than the list length it will be appended.
- * @param source               The pointer of the byte sequence to insert.
- * @param sourceLength The length of the byte sequence to insert.
- * @param tag                  An item stored with the byte sequence. We know nothing about this.
- */
-void ReSeqList::add(Index index, const Byte* source, size_t sourceLength, Tag tag){
-       Sequence seq;
-       if (sourceLength == (size_t) -1)
-               sourceLength = strlen(source);
-       setSequence(&seq, m_content.length(), sourceLength, tag);
-       m_content.append(source, sourceLength);
-       if (m_sorted){
-               //@ToDo
-               assert(false);
-       } else {
-               if (index >= count()){
-                       m_list.append((Byte*) &seq, m_entrySize);
-               }else{
-                       m_list.insert(index * m_entrySize, (Byte*) &seq, m_entrySize);
-               }
-       }
-}
-
-/**
- * @brief Searches the an element with binary search.
- *
- * @param toFind       the value which should be found
- * @param length       -1 or the length of <code>toFind</code>
- * @param index     OUT: the index usable for insert:
- *                                     index is the smallest value with content[index] >= toFind
- * @param tag          OUT: the tag of the element (only if it was found).<br>
- *                                     May be NULL
- * @return                     -1: the key has been found.
- */
-bool ReSeqList::binarySearch(const Byte* toFind, int length, Index& index,
-                       Tag* tag) const
-{
-       assert(m_sorted);
-       if (length < 0)
-               length = strlen(toFind);
-       Index rc = (Index) -1;
-   int lbound = 0;
-       int theCount = count();
-    int ubound = theCount;
-    // binary search over the sorted vector:
-    while(lbound <= ubound){
-        int half = (ubound + lbound) / 2;
-        const Sequence* seq = reinterpret_cast<const Sequence*>(
-                       m_list.str() + half * m_entrySize);
-        int currentLength = getLength(seq);
-               int minLength = currentLength < length ? currentLength : length;
-               const char* current = m_content.str() + seq->m_index;
-               int compareRc = m_ignoreCase
-                       ? _memicmp(toFind, current, minLength)
-                       : _memcmp(toFind, current, minLength);
-        if (compareRc == 0 && currentLength != length)
-            compareRc = currentLength > length ? -1 : 1;
-        if (compareRc < 0)
-            ubound = half - 1;
-        else if (compareRc > 0)
-            lbound = half + 1;
-        else {
-                       rc = true;
-            index = half;
-            break;
-        }
-    }
-    if (! rc)
-               index = ubound;
-    return rc;
-}
-
-/** @brief Deletes all entries in the list.
- */
-void ReSeqList::clear(){
-       m_content.setLength(0);
-       m_list.setLength(0);
-}
-
-/**
- * Compares two elements.
- *
- * @param index1       the index of the first element
- * @param index2       the index of the second element
- * @return                     0: element1 == element2<br>
- *                                     < 0: element1 < element2<br>
- *                                     > 0: element1 > element2
- */
-int ReSeqList::compare(Index index1, Index index2){
-       Sequence* seq1 = getInfo(index1);
-       Sequence* seq2 = getInfo(index2);
-       size_t length1 = getLength(seq1);
-       size_t length2 = getLength(seq2);
-       int minLength = length1 < length2 ? length1 : length2;
-       int rc = m_ignoreCase
-               ? _memicmp(m_content.str() + seq1->m_index,
-                                       m_content.str() + seq2->m_index, minLength)
-               : _memcmp(m_content.str() + seq1->m_index,
-                                       m_content.str() + seq2->m_index, minLength);
-       if (rc == 0 && length1 != length2)
-               rc = length1 < length2 ? -1 : 1;
-       return rc;
-}
-/**
- * Writes the content to a stream.
- *
- * @param fp   target file pointer
- */
-void ReSeqList::dump(FILE* fp) const{
-       ReByteBuffer buffer;
-       Tag tag;
-       for (int ix = 0; ix < (int) count(); ix++){
-               get(ix, buffer, &tag);
-               fprintf(fp, "%d: (%ld) [%d] %s\n", ix, (int64_t) tag, (int) buffer.length(),
-                       buffer.str());
-       }
-}
-
-/** @brief Returns the index of a stored byte sequence.
- *
- * @param toFind               the byte sequence to find
- * @param length               -1 or the length of <code>toFind</code>.
- *
- * @return: -1: The key was not found. Otherwise: The index of the key in the key sequence array.
- */
-ReSeqList::Index ReSeqList::find(const Byte* toFind, size_t length,
-                       Tag* tag) const{
-       if (length == (size_t) -1)
-               length = strlen(toFind);
-       int rc = -1;
-       int theCount = count();
-       for (int ix = 0; ix < theCount; ix++){
-               const ReSeqList::Sequence* seq = getInfo(ix);
-               Tag currentTag;
-               size_t currentLength = getLengthAndTag(seq, currentTag);
-               if (currentLength == length){
-                       const Byte* ptr = reinterpret_cast<const Byte*>(m_content.str()
-                                               + seq->m_index);
-                       int comparison = m_ignoreCase ? _memicmp(ptr, toFind, length)
-                                               : _memcmp(ptr, toFind, length);
-                       if (comparison == 0){
-                               rc = ix;
-                               if (tag != NULL)
-                                       *tag = currentTag;
-                               break;
-                       }
-               }
-       }
-       return rc;
-}
-
-/** @brief Returns an element from the list.
- *
- * @param index                The index of the sequence in the list.
- * @param value                Out: The stored sequence will be copied here.
- * @param tag          Out: The info which is stored with the entry. May be <code>NULL</code>.
- *
- * @param      true: The index is ok, the sequence is in the output buffer.
- *                     false: No copy has been done.
- */
-bool ReSeqList::get(Index index, ReByteBuffer& value, Tag* tag) const{
-       bool rc = false;
-       if (index < count()){
-               const Sequence* seq = getInfo(index);
-               size_t length = tag == NULL ? getLength(seq) : getLengthAndTag(seq, *tag);
-               value.set(m_content.str() + seq->m_index, length);
-               rc = true;
-       }
-       return rc;
-}
-/** @brief Returns the byte sequence length of the element.
- *
- * @return     the length of the element described in the Sequence seq
- */
-size_t ReSeqList::getLength(const Sequence* seq) const{
-       size_t rc;
-       if (m_commonSize != INDIVIDUAL_SIZE)
-               rc = m_commonSize;
-       else {
-               const uint8_t* ptr = reinterpret_cast<const uint8_t*>(seq) + m_offsetOfLength;
-               switch (m_sizeOfLength){
-               case 1:
-                       rc = *ptr;
-                       break;
-               case 2:
-                       rc = ptr[0] + (ptr[1] << 8);
-                       break;
-               case 3:
-                       rc = ptr[0] + (ptr[1] << 8) + (ptr[1] << 16);
-                       break;
-               case 4:
-                       rc = ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24);
-                       break;
-               case 5:
-                       rc = ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24)
-                               + ((int64_t)ptr[4] << 32);
-                       break;
-               default:
-                       assert(false);
-                       rc = 0;
-                       break;
-               }
-       }
-       return rc;
-}
-/** @brief Returns the byte sequence length and the tag of an element.
- *
- * @param tag  OUT: the tag of the element.
- * @return             the byte sequence length of the element
- */
-size_t ReSeqList::getLengthAndTag(const Sequence* seq, Tag& tag) const{
-       size_t rc;
-       if (m_commonSize != INDIVIDUAL_SIZE)
-               rc = m_commonSize;
-       else {
-               const uint8_t* ptr = reinterpret_cast<const uint8_t*>(seq) + m_offsetOfLength;
-               switch (m_sizeOfLength){
-               case 1:
-                       rc = *ptr;
-                       break;
-               case 2:
-                       rc = ptr[0] + (ptr[1] << 8);
-                       break;
-               case 3:
-                       rc = ptr[0] + (ptr[1] << 8) + (ptr[1] << 16);
-                       break;
-               case 4:
-                       rc = ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24);
-                       break;
-               case 5:
-                       rc = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24)
-                               | ((uint64_t)ptr[4] << 32);
-                       break;
-               default:
-                       assert(false);
-                       rc = 0;
-                       break;
-               }
-       }
-       const uint8_t* ptr = reinterpret_cast<const uint8_t*>(seq) + m_offsetOfTag;
-       switch (m_sizeOfTag){
-       case 0:
-               tag = 0;
-               break;
-       case 1:
-               tag = *ptr;
-               break;
-       case 2:
-               tag = ptr[0] + (ptr[1] << 8);
-               break;
-       case 3:
-               tag = ptr[0] + (ptr[1] << 8) + (ptr[2] << 16);
-               break;
-       case 4:
-               tag = ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24);
-               break;
-       case 5:
-               tag = Tag(ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (uint64_t(ptr[3]) << 24)
-                       | (uint64_t(ptr[4]) << 32));
-               break;
-       case 8:
-               tag = Tag(ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (uint64_t(ptr[3]) << 24)
-                       | (uint64_t(ptr[4]) << 32) | (uint64_t(ptr[5]) << 40)
-                       | (uint64_t(ptr[6]) << 48) | (uint64_t(ptr[7]) << 56));
-               break;
-       default:
-               assert(false);
-               tag = 0;
-               break;
-       }
-       return rc;
-}
-
-/** @brief Removes an element given by its index.
- *
- * @param index The index of the entry to remove.
- */
-void ReSeqList::remove(Index index){
-       if (index <= count()){
-               Sequence* seq = getInfo(index);
-               size_t currentLength = getLength(seq);
-               // Is this the last entry in m_content?
-               if (seq->m_index + currentLength >= m_content.length()){
-                       // We can free the content:
-                       m_content.setLength(seq->m_index);
-               } else {
-                       m_lost += currentLength;
-               }
-               // Remove the entry from the list:
-               m_list.remove(index * m_entrySize, m_entrySize);
-       }
-}
-/** @brief Replaces the byte sequence in the list.
- *
- * @param index                        The index of the sequence to replace.
- * @param source               The new value.
- * @param sourceLength The length of the new value.
- * @param tag                  An additional info associated to the source.
- */
-void ReSeqList::set(Index index, const Byte* source,
-                       size_t sourceLength, Tag tag){
-       if (index >= count())
-               add(index, source, sourceLength, tag);
-       else {
-               if (sourceLength == (size_t) -1)
-                       sourceLength = strlen(source) + 1;
-               Sequence* seq = getInfo(index);
-               size_t currentLength = getLength(seq);
-               size_t indexContent;
-               if (currentLength >= sourceLength){
-                       // Use the existing space:
-                       indexContent = seq->m_index;
-                       memcpy(m_content.buffer() + indexContent, source, sourceLength);
-                       m_lost += currentLength - sourceLength;
-               } else {
-                       // New space must be allocated:
-                       m_lost += currentLength;
-                       indexContent = m_content.length();
-                       m_content.append(source, sourceLength);
-               }
-               setSequence(seq, indexContent, sourceLength, tag);
-       }
-}
-/** @brief Sets the Sequence of an element.
- *
- * @param seq          the target sequence
- * @param index        the index in m_content
- * @param length       the length of the content
- * @param tag          the tag of the element
- */
-void ReSeqList::setSequence(Sequence* seq, Index index, size_t length, Tag tag){
-       seq->m_index = index;
-       if (m_commonSize == INDIVIDUAL_SIZE){
-               uint8_t* ptr = reinterpret_cast<uint8_t*>(seq) + m_offsetOfLength;
-               switch (m_sizeOfLength){
-               case 1:
-                       ptr[0] = length & 0xff;
-                       break;
-               case 2:
-                       ptr[0] = length & 0xff;
-                       ptr[1] = (length >> 8) & 0xff;
-                       break;
-               case 3:
-                       ptr[0] = length & 0xff;
-                       ptr[1] = (length >> 8) & 0xff;
-                       ptr[2] = (length >> 16) & 0xff;
-                       break;
-               case 4:
-                       ptr[0] = length & 0xff;
-                       ptr[1] = (length >> 8) & 0xff;
-                       ptr[2] = (length >> 16) & 0xff;
-                       ptr[3] = (length >> 24) & 0xff;
-                       break;
-               case 5:
-                       ptr[0] = length & 0xff;
-                       ptr[1] = (length >> 8) & 0xff;
-                       ptr[2] = (length >> 16) & 0xff;
-                       ptr[3] = (length >> 24) & 0xff;
-                       ptr[4] = (int64_t(length) >> 32) & 0xff;
-                       break;
-               default:
-                       assert(false);
-                       break;
-               }
-       }
-       if (m_sizeOfTag > 0){
-               uint8_t* ptr = reinterpret_cast<uint8_t*>(seq) + m_offsetOfTag;
-               switch (m_sizeOfTag){
-               case 1:
-                       ptr[0] = tag & 0xff;
-                       break;
-               case 2:
-                       ptr[0] = length & 0xff;
-                       ptr[1] = (tag >> 8) & 0xff;
-                       break;
-               case 3:
-                       ptr[0] = tag & 0xff;
-                       ptr[1] = (tag >> 8) & 0xff;
-                       ptr[2] = (tag >> 16) & 0xff;
-                       break;
-               case 4:
-                       ptr[0] = tag & 0xff;
-                       ptr[1] = (tag >> 8) & 0xff;
-                       ptr[2] = (tag >> 16) & 0xff;
-                       ptr[3] = (tag >> 24) & 0xff;
-                       break;
-               case 5:
-                       ptr[0] = tag & 0xff;
-                       ptr[1] = (tag >> 8) & 0xff;
-                       ptr[2] = (tag >> 16) & 0xff;
-                       ptr[3] = (tag >> 24) & 0xff;
-                       ptr[4] = (tag >> 32) & 0xff;
-                       break;
-               case 8:
-                       ptr[0] = tag & 0xff;
-                       ptr[1] = (tag >> 8) & 0xff;
-                       ptr[2] = (tag >> 16) & 0xff;
-                       ptr[3] = (tag >> 24) & 0xff;
-                       ptr[4] = (tag >> 32) & 0xff;
-                       ptr[5] = (tag >> 40) & 0xff;
-                       ptr[6] = (tag >> 48) & 0xff;
-                       ptr[7] = (tag >> 56) & 0xff;
-                       break;
-               default:
-                       assert(false);
-                       break;
-               }
-       }
-}
-
-/** @brief Sets the switch for case sensitivity.
- *
- * @param onNotOff     <code>true</code>: the comparison will be case insensitive
- */
-void ReSeqList::setIgnoreCase(bool onNotOff){
-       if (m_ignoreCase != onNotOff){
-               m_ignoreCase = onNotOff;
-               if (m_sorted)
-                       sort();
-       }
-}
-
-/** @brief Sets the switch for sorting.
- *
- * @param onNotOff     <code>true</code>: the list will be sorted
- */
-void ReSeqList::setSorted(bool onNotOff){
-       if (m_sorted != onNotOff){
-               m_sorted = onNotOff;
-               if (m_sorted)
-                       sort();
-       }
-}
-
-/**
- * Sets the length of the stored items tag and length (in Sequence).
- *
- * @param sizeOfTag            0: no tag stored.
- *                                                     Otherwise: length in byte: 1,2,3,4,5 or 8
- * @param sizeOfLength 0: no length stored (constant length, stored in
- *                                                     m_commonSize).
- *                                                     Otherwise: length in byte: 1, 2, 3, 4 or 5
- * @param constantSize  0 or the size of the sequence if the length is not
- *                                                     indiviually stored. <br>
- *                                                     If > 0 <code>sizeOfLength</code>must be 0!
- */
-void ReSeqList::setSizes(int sizeOfTag, int sizeOfLength, int constantSize){
-       switch(m_sizeOfLength = sizeOfLength){
-       case 0:
-       case 1:
-       case 2:
-       case 3:
-       case 4:
-       case 5:
-               break;
-       default:
-               globalLogger()->sayF(LOG_ERROR | CAT_LIB, LC_SET_SIZES_2,
-                       i18n("Invalid length length: $1 (instead of 0,1,2,4,5)")).arg(sizeOfTag).end();
-               m_sizeOfLength = 8;
-               break;
-       }
-       switch(m_sizeOfTag = sizeOfTag){
-       case 0:
-       case 1:
-       case 2:
-       case 3:
-       case 4:
-       case 8:
-               break;
-       default:
-               globalLogger()->sayF(LOG_ERROR | CAT_LIB, LC_SET_SIZES_1,
-                       i18n("Invalid tag length: $1 (instead of 0,1,2,3,4,8)")).arg(sizeOfTag).end();
-               m_sizeOfTag = 8;
-               break;
-       }
-       m_offsetOfLength = sizeof(Index);
-       m_offsetOfTag = sizeof(Index) + m_sizeOfLength;
-       if (sizeOfLength > 0 && constantSize > 0){
-               globalLogger()->sayF(LOG_ERROR | CAT_LIB, LC_SET_SIZES_1,
-                                       i18n("collision of sizeOfLength $1 and constantSize $2"))
-                                       .arg(sizeOfLength).arg(constantSize).end();
-               constantSize = 0;
-       }
-       m_commonSize = constantSize;
-}
-
-/** @brief Sorts the list.
- * Note: the comparison is controlled by <code>m_ignoreCase</code>.
- */
-void ReSeqList::sort(){
-       // Build the heap in array so that largest value is at the root:
-       int theCount = (int) count();
-       for (int start = (theCount - 2) / 2; start >= 0; start--) {
-               // (shift down the node at index 'start' to the proper place such
-               // that all nodes below the start index are in heap order)
-               shiftDown(start, theCount);
-       }
-       // The following loop maintains the invariants that array[0:end] is a heap
-       // and every element beyond end is greater than everything before it
-       // (so array[end:count] is in sorted order)
-       for (int end = theCount - 1; end > 0; end--) {
-               // swap [end] with [0]:
-               Sequence seq;
-               Byte* ptrEnd = m_list.buffer() + end * m_entrySize;
-               memcpy(&seq, ptrEnd, m_entrySize);
-               memcpy(ptrEnd, m_list.buffer(), m_entrySize);
-               memcpy(m_list.buffer(), &seq, m_entrySize);
-               shiftDown(0, end);
-       }
-}
-/**
- * Correct the order in the heap.
- *
- * @param start                the lower bound of the interval to inspect
- * @param endEnd       the upper bound of the interval to inspect
- */
-void ReSeqList::shiftDown(int start, int end){
-   int root = start;
-       Sequence seq;
-       // while the root has at least one child:
-       while (root * 2 + 1 < end ) {
-               // left child:
-               int child = 2 * root + 1;
-               if (child + 1 < end && compare(child, child + 1) < 0)
-           child++;
-       if (compare(root, child) >= 0)
-                  break;
-       else
-       {
-                       // swap [child] with [root]
-                       Byte* ptrRoot = m_list.buffer() + root * m_entrySize;
-                       Byte* ptrChild = m_list.buffer() + child * m_entrySize;
-                       memcpy(&seq, ptrRoot, m_entrySize);
-                       memcpy(ptrRoot, ptrChild, m_entrySize);
-                       memcpy(ptrChild, &seq, m_entrySize);
-                       root = child;
-       }
-   }
-}
-
diff --git a/base/ReSeqList.hpp b/base/ReSeqList.hpp
deleted file mode 100644 (file)
index 3cdbd8f..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * ReSeqList.h
- *
- *  Created on: 19.05.2010
- *      Author: wk
- */
-
-#ifndef RESEQLIST_H_
-#define RESEQLIST_H_
-
-#define INDIVIDUAL_SIZE (size_t(-1))
-/** @brief This class implements a dynamic (self growing) array of elements.
- *
- * An <b>element</b> is a tuple of a byte sequences and a tag.
- * A <b>tag</b> is an integer value which is interpreted only by the user
- * of the list. The list knows nothing abbout it.
- *
- * A <b>byte sequence</b> is an array of byte.
- * The byte sequences may have different lengths.
- * This implies the handling of C string arrays too.
- */
-class ReSeqList {
-public:
-       typedef char Byte;
-       typedef unsigned int Index;
-       typedef int64_t Tag;
-       typedef struct {
-               Index   m_index;
-               uint64_t m_length;
-               Tag             m_tag;
-       } Sequence;
-public:
-       ReSeqList(size_t deltaList = 128, int deltaBuffer = 1024);
-       virtual ~ReSeqList();
-       ReSeqList(const ReSeqList& source);
-       ReSeqList& operator = (const ReSeqList& source);
-public:
-       void add(Index index, const Byte* source, size_t sourceLength, Tag tag = 0);
-       bool binarySearch(const Byte* toFind, int length, Index& index,
-                               Tag* tag = NULL) const;
-       void clear();
-       int compare(Index index1, Index index2);
-       /** @brief Returns the count of defined entries in the list.
-        * @return The number of defined entries in the list (array).
-        */
-       inline Index count() const {
-               return m_list.length() / m_entrySize;
-       }
-       void dump(FILE* fp) const;
-       Index find(const Byte* toFind, size_t length, Tag* tag = NULL) const;
-       bool get(Index index, ReByteBuffer& value, Tag* tag = NULL) const;
-       /** Returns whether the list is sorted automatically.
-        * Note: comparison is controlled by <code>m_ignoreCase</code>.
-        * @return <code>true</code> the byte sequences will be sorted
-        */
-       bool isSorted() const {
-               return m_sorted;
-       }
-       /** Returns whether the comparisons inside the list are case insensitive.
-        * @return <code>true</code> the comparisons inside the list are case insensitive
-        */
-       bool ignoreCase() const {
-               return m_ignoreCase;
-       }
-       void remove(Index index);
-       void set(Index index, const Byte* source, size_t sourceLength, Tag tag);
-       void setSizes(int sizeOfTag, int sizeOfLength, int constantLength = 0);
-       void setSorted(bool onNotOff);
-       void setIgnoreCase(bool onNotOff);
-       void sort();
-protected:
-       /** @brief Returns a pointer of the content buffer.
-        * @return A pointer of the first byte of the content buffer.
-        */
-       inline const Byte* getContent() const {
-               return m_content.buffer();
-       }
-       friend class ReHashList;
-       /** @brief Returns the info of an entry of the list.
-        * @param index         The index of the wanted entry.
-        * @return The pointer of the entry.
-        */
-       inline Sequence* getInfo(Index index) const {
-               return reinterpret_cast<Sequence*>(m_list.buffer() + m_entrySize * index);
-       }
-       size_t getLength(const Sequence* seq) const;
-       size_t getLengthAndTag(const Sequence* seq, Tag& tag) const;
-       void setSequence(Sequence* seq, Index index, size_t length, Tag tag);
-       void shiftDown(int from, int to);
-protected:
-       //@ Contains the sequences itself.
-       ReByteBuffer m_content;
-       //@ Contains an array of <code>Sequence</code>s.
-       ReByteBuffer m_list;
-       //@ If strings have been replaced/deleted the space in m_content is still allocated.
-       //@ This is the sum of lost space.
-       size_t m_lost;
-       //@ The length of a Sequence block: sizeof(seq->m_index)+m_lengthTag+m_lengthLength
-       size_t m_entrySize;
-       //@ -1: The Sequence block contains the individual length.
-       //@ 0: no content will be stored
-       //@ Otherwise: the common length of all elements in m_content
-       size_t m_commonSize;
-       //@ length of the tag: 0,1,2,4,8
-       size_t m_sizeOfTag;
-       //@ length of the length element in Sequence: 0,1,2,4
-       size_t m_sizeOfLength;
-       //@ offset of the tag (from start of Sequence)
-       size_t m_offsetOfTag;
-       //@ offset of the length (from start of Sequence)
-       size_t m_offsetOfLength;
-       bool m_sorted;
-       //@ true: the comparison will be case insensitive
-       bool m_ignoreCase;
-};
-
-#endif /* RESEQLIST_H_ */
index 71fb64104788ed8f24de6f550d6f235c55a6bdd1..08e0cafd9e9f4827b1aef070ad2bdc2aea761da5 100644 (file)
@@ -13,7 +13,7 @@
  * @param deltaBuffer  buffer reservation will be incremented by this amount
  */
 ReStringList::ReStringList(int deltaList, int deltaBuffer)     :
-       ReSeqList(deltaList, deltaBuffer)
+       ReSeqArray(deltaList, deltaBuffer)
 {
 }
 
@@ -125,7 +125,7 @@ const char* ReStringList::strOf(Index index) const{
  * @return     -1: The index is too large.
  *                     Otherwise: The wanted tagOf.
  */
-ReSeqList::Tag ReStringList::tagOf(Index index) const{
+ReSeqArray::Tag ReStringList::tagOf(Index index) const{
        Tag rc = -1;
        if (index < count()){
                Sequence* seq = getInfo(index);
@@ -200,7 +200,7 @@ size_t ReStringList::sumOfStrLengths() const{
  *
  * @return -1: The string was not found. Otherwise: The index of the string.
  */
-ReSeqList::Index ReStringList::indexOf(const char* toFind,
+ReSeqArray::Index ReStringList::indexOf(const char* toFind,
                bool ignoreCase, Index start) const{
        Index rc = (Index) -1;
        Index theCount = count();
@@ -226,7 +226,7 @@ ReSeqList::Index ReStringList::indexOf(const char* toFind,
  *
  * @return -1: The string was not found. Otherwise: The index of the string.
  */
-ReSeqList::Index ReStringList::nextStartingWith(Index start,
+ReSeqArray::Index ReStringList::nextStartingWith(Index start,
                const char* prefix, bool ignoreCase){
        Index rc = (Index) -1;
        Index theCount = count();
index a12b2dbbef8fd7bc1e88a588173a4a103756000e..2807d4cf767f8c71f9c55d679267dbee7df79275 100644 (file)
@@ -28,7 +28,7 @@
  * listOut.writeToFile("abc.csv");
  * </code></pre>
  */
-class ReStringList : public ReSeqList {
+class ReStringList : public ReSeqArray {
 public:
        ReStringList(int deltaList = 1024, int deltaBuffer = 1024);
        virtual ~ReStringList();
index e132b1abeeafcc62efe241ceb7be6bf724a5d27b..86a839a18f93a9690f4210e84562155ac088feeb 100644 (file)
@@ -13,7 +13,7 @@
 enum RELOC_LIB {
        LC_CONFIGFILE   = 50000,
        LC_DIRTOOLS             = 50100,
-       LC_SEQLIST              = 50200,
+       LC_SEQARRAY             = 50200,
        LC_HASHLIST             = 50300,
 };
 enum RELOC_UDPCONNECTION {
index 0ac19fc897f275833d5c33d2924c70ff87d1fe40..19251d2b55a0717fc46189464c018de6b3013bc6 100644 (file)
@@ -53,7 +53,7 @@
 #include "base/ReException.hpp"
 #include "base/ReStringUtils.hpp"
 #include "base/ReDirectory.hpp"
-#include "base/ReSeqList.hpp"
+#include "base/ReSeqArray.hpp"
 #include "base/ReStringList.hpp"
 #include "base/ReHashList.hpp"
 #include "base/ReConfigFile.hpp"
index a04a4f02a75ea0c92dde9f45729fc150799b4949..2a7d7edaee85402909147bcbee9bc3a44fef1f4d 100644 (file)
@@ -15,8 +15,8 @@ void testReBase(void){
                testReI18N();
                extern void testReStringList(void);
                testReStringList();
-               extern void testReSeqList(void);
-               testReSeqList();
+               extern void testReSeqArray(void);
+               testReSeqArray();
                extern void testReHashList(void);
                testReHashList();
                void testReException(void);
diff --git a/cunit/cuReSeqArray.cpp b/cunit/cuReSeqArray.cpp
new file mode 100644 (file)
index 0000000..16a08e8
--- /dev/null
@@ -0,0 +1,280 @@
+#include "base/rebase.hpp"
+
+class TestReSeqList : public ReTestUnit {
+public:
+       TestReSeqList() : ReTestUnit("ReSeqArray", __FILE__){
+               run();
+       }
+private:
+       void run(){
+               testBinSearch2();
+               testBinSearch();
+               testSorted();
+               testIgnoreCase();
+               testFind();
+               testAdd();
+               testBase();
+               testRemove();
+       }
+       void checkElement(ReSeqArray& list, ReSeqArray::Index index, const char* value, ReSeqArray::Tag expectedTag){
+               ReByteBuffer buffer;
+               ReSeqArray::Tag tag;
+               checkT(list.get(index, buffer, &tag));
+               checkIEqu(value, buffer.str());
+               checkEqu(expectedTag, tag);
+       }
+       void testBinSearch(){
+               ReSeqArray list;
+               list.setIgnoreCase(true);
+               ReByteBuffer value, expectedValue;
+               list.add(-1, "abc", -1, 300);
+               list.add(-1, "abc", -1, 350);
+               list.add(-1, "abce", -1, 100);
+               list.add(-1, "bcd", -1, 200);
+               list.add(-1, "cde", -1, 400);
+               list.setSorted(true);
+               ReSeqArray::Index index;
+
+               checkF(list.binarySearch("cee", -1, index, NULL));
+               checkEqu(5ll, index);
+
+               checkF(list.binarySearch("ab", 2, index, NULL));
+               checkEqu(0ll, index);
+               checkF(list.binarySearch("ab", -1, index, NULL));
+               checkEqu(0ll, index);
+               checkF(list.binarySearch("abcd", -1, index, NULL));
+               checkEqu(2ll, index);
+               checkF(list.binarySearch("bbd", -1, index, NULL));
+               checkEqu(3ll, index);
+               checkF(list.binarySearch("bbd", -1, index, NULL));
+               checkEqu(3ll, index);
+               checkF(list.binarySearch("bc", -1, index, NULL));
+               checkEqu(3ll, index);
+               checkF(list.binarySearch("bcd0", -1, index, NULL));
+               checkEqu(4ll, index);
+               checkF(list.binarySearch("cdex", -1, index, NULL));
+               checkEqu(5ll, index);
+               checkF(list.binarySearch("cee", -1, index, NULL));
+               checkEqu(5ll, index);
+       }
+       void testBinSearch2(){
+               ReSeqArray list;
+               ReSeqArray::Tag tag;
+               ReSeqArray::Index index;
+               ReByteBuffer value;
+               list.setSorted(true);
+               value = "ab";
+               for (int count = 2; count < 16; count++){
+                       list.clear();
+                       for (int ix = 0; ix < count; ix++){
+                               value.setLength(2);
+                               value.buffer()[0] = 'a' + ix;
+                               list.add(ix, value.str(), -1, (ReSeqArray::Tag) ix*10);
+                       }
+                       for (int ix = 0; ix <= count; ix++){
+                               value.setLength(2);
+                               value.buffer()[0] = 'a' + ix;
+                               value.buffer()[1] = 'a';
+                               checkF(list.binarySearch(value.str(), -1, index));
+                               checkEqu(ReSeqArray::Index(ix), index);
+                               if (ix > 0){
+                                       value.setLength(3);
+                                       value.buffer()[0] = 'a' + ix - 1;
+                                       value.buffer()[1] = 'b';
+                                       value.buffer()[2] = '0';
+                                       bool rc = list.binarySearch(value.str(), -1, index);
+                                       checkF(rc);
+                                       checkEqu(ReSeqArray::Index(ix), index);
+                               }
+                       }
+               }
+       }
+       void testSorted(){
+               ReSeqArray list;
+               list.setIgnoreCase(true);
+               ReByteBuffer value, expectedValue;
+               list.add(-1, "bcd", -1, 200);
+               list.add(-1, "abcd", -1, 100);
+               list.add(-1, "abc", -1, 300);
+               list.add(-1, "abc", -1, 350);
+               list.add(-1, "cde", -1, 400);
+               log(false, "unsorted:");
+               list.dump(stdout);
+               list.setSorted(true);
+               log(false, "sorted:");
+               list.dump(stdout);
+               checkElement(list, 0U, "AbC", 350);
+               checkElement(list, 1U, "AbC", 300);
+               checkElement(list, 2U, "AbCd", 100);
+               checkElement(list, 3U, "bCd", 200);
+               checkElement(list, 4U, "cde", 400);
+               ReSeqArray::Index index;
+               ReSeqArray::Tag tag;
+               checkT(list.binarySearch("Abc", -1, index, &tag));
+               checkEqu(0u, index);
+               checkT(list.binarySearch("AbcD", -1, index, &tag));
+               checkEqu(2u, index);
+               checkT(list.binarySearch("bCd", -1, index, &tag));
+               checkEqu(3u, index);
+               checkT(list.binarySearch("cde", -1, index, &tag));
+               checkEqu(4u, index);
+       }
+       void testIgnoreCase(){
+               ReSeqArray list;
+               list.setIgnoreCase(true);
+               ReByteBuffer value, expectedValue;
+               list.add(-1, "bcd", -1, 200);
+               list.add(0, "abc", -1, 100);
+               list.dump(stdout);
+               checkEqu(0U, list.find("AbC", -1));
+               checkEqu(1U, list.find("BCD", -1));
+       }
+       void testAdd(){
+               ReSeqArray list;
+               ReByteBuffer value, expectedValue;
+               ReSeqArray::Tag tag = 0;
+               ReSeqArray::Tag expectedTag = 0;
+               size_t maxIx = 64;
+               for (size_t ix = 0; ix < maxIx; ix++){
+                       expectedTag = (1ll << ix);
+                       expectedValue.append("x", 1);
+                       list.add(-1, expectedValue.str(), -1, expectedTag);
+                       checkEqu(ix + 1, list.count());
+                       checkT(list.get(ix, value, &tag));
+                       checkEqu(expectedValue.str(), value.str());
+                       if (expectedTag != tag)
+                               checkEqu(expectedTag, tag);
+               }
+               expectedValue.setLength(0);
+               for (size_t ix = 0; ix < maxIx; ix++){
+                       expectedTag = (1ll << ix);
+                       expectedValue.append("x", 1);
+                       checkT(list.get(ix, value, &tag));
+                       checkEqu(expectedValue.str(), value.str());
+                       checkEqu(expectedTag, tag);
+               }
+
+       }
+       void testFind(){
+               ReSeqArray list;
+               ReByteBuffer value, expectedValue;
+               ReSeqArray::Tag tag = 0;
+               ReSeqArray::Tag expectedTag = 0;
+               size_t maxIx = 13;
+               for (size_t ix = 0; ix < maxIx; ix++){
+                       expectedTag = 10*ix;
+                       expectedValue.append("x", 1);
+                       list.add(-1, expectedValue.str(), -1, expectedTag);
+                       checkEqu(ix + 1, list.count());
+                       checkT(list.get(ix, value, &tag));
+                       checkEqu(expectedValue.str(), value.str());
+                       if (expectedTag != tag)
+                               checkEqu(expectedTag, tag);
+               }
+               list.dump(stdout);
+               expectedValue.setLength(0);
+               for (size_t ix = 0; ix < maxIx; ix++){
+                       expectedTag = -1;
+                       expectedValue.append("x", 1);
+                       if (ix >= 4)
+                               expectedTag = -1;
+                       checkEqu(ix, list.find(expectedValue.str(), expectedValue.length(), &expectedTag));
+                       checkEqu(int(10*ix), (int) expectedTag);
+               }
+       }
+       void testBase(){
+               ReSeqArray list;
+               ReByteBuffer value;
+               ReSeqArray::Tag tag = 0;
+
+               list.add(-1, "xxx", -1, ReSeqArray::Tag(1l) << 31);
+               checkT(list.get(0, value, &tag));
+               checkEqu(1ll << 31, tag);
+               checkEqu("xxx", value.str());
+
+               list.clear();
+               list.add(-1, "123", -1, 0x3344556633445566ll);
+               checkEqu(1u, list.count());
+               checkT(list.get(0, value, &tag));
+               checkEqu("123", value.str());
+               checkEqu((int64_t) 0x3344556633445566ll, tag);
+
+               list.add(-1, "ab", -1, 0x345678abcdef3344ll);
+               checkEqu(2u, list.count());
+               checkT(list.get(0, value));
+               checkEqu("123", value.str());
+               checkT(list.get(1, value, &tag));
+               checkEqu("ab", value.str());
+               checkEqu(0x345678abcdef3344ll, tag);
+
+               list.add(0, "xyz", -1, 300);
+               checkEqu(3u, list.count());
+               checkT(list.get(0, value, &tag));
+               checkEqu("xyz", value.str());
+               checkT(list.get(1, value));
+               checkEqu("123", value.str());
+               checkT(list.get(2, value));
+               checkEqu("ab", value.str());
+               checkEqu(300ll, tag);
+
+               list.add(1, "vw", -1, 400);
+               checkEqu(4u, list.count());
+               checkT(list.get(0, value));
+               checkEqu("xyz", value.str());
+               checkT(list.get(1, value, &tag));
+               checkEqu("vw", value.str());
+               checkT(list.get(2, value));
+               checkEqu("123", value.str());
+               checkT(list.get(3, value));
+               checkEqu("ab", value.str());
+               checkEqu(400ll, tag);
+
+               list.clear();
+               checkEqu(0u, list.count());
+               checkF(list.get(0, value));
+       }
+       void testRemove(){
+               ReSeqArray list;
+               ReByteBuffer value;
+               ReSeqArray::Tag tag = 0;
+
+               list.add(-1, "abc", -1, 100);
+               list.add(-1, "def12", -1, 200);
+               list.add(-1, "ghi", -1, 300);
+               list.add(-1, "jkl134", -1, 400);
+
+               list.remove(3);
+               checkEqu(3u, list.count());
+               list.get(0, value, &tag);
+               checkEqu("abc", value.str());
+               checkEqu(100ll, tag);
+               list.get(1, value, &tag);
+               checkEqu("def12", value.str());
+               checkEqu(200ll, tag);
+               list.get(2, value, &tag);
+               checkEqu("ghi", value.str());
+               checkEqu(300ll, tag);
+
+
+               list.remove(1);
+               checkEqu(2u, list.count());
+               list.get(0, value, &tag);
+               checkEqu("abc", value.str());
+               checkEqu(100ll, tag);
+               list.get(1, value, &tag);
+               checkEqu("ghi", value.str());
+               checkEqu(300ll, tag);
+
+               list.remove(0);
+               checkEqu(1u, list.count());
+               list.get(0, value, &tag);
+               checkEqu("ghi", value.str());
+               checkEqu(300ll, tag);
+
+       }
+};
+extern void testReSeqArray(void);
+
+void testReSeqArray(void){
+       TestReSeqList unit;
+}
diff --git a/cunit/cuReSeqList.cpp b/cunit/cuReSeqList.cpp
deleted file mode 100644 (file)
index 8217068..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-#include "base/rebase.hpp"
-
-class TestReSeqList : public ReTestUnit {
-public:
-       TestReSeqList() : ReTestUnit("ReSeqList", __FILE__){
-               run();
-       }
-private:
-       void run(){
-               testSorted();
-               testIgnoreCase();
-               testFind();
-               testAdd();
-               testBase();
-               testRemove();
-       }
-       void checkElement(ReSeqList& list, ReSeqList::Index index, const char* value, ReSeqList::Tag expectedTag){
-               ReByteBuffer buffer;
-               ReSeqList::Tag tag;
-               checkT(list.get(index, buffer, &tag));
-               checkIEqu(value, buffer.str());
-               checkEqu(expectedTag, tag);
-       }
-       void testSorted(){
-               ReSeqList list;
-               list.setIgnoreCase(true);
-               ReByteBuffer value, expectedValue;
-               list.add(-1, "bcd", -1, 200);
-               list.add(-1, "abcd", -1, 100);
-               list.add(-1, "abc", -1, 300);
-               list.add(-1, "abc", -1, 350);
-               list.add(-1, "cde", -1, 400);
-               log(false, "unsorted:");
-               list.dump(stdout);
-               list.setSorted(true);
-               log(false, "sorted:");
-               list.dump(stdout);
-               checkElement(list, 0U, "AbC", 350);
-               checkElement(list, 1U, "AbC", 300);
-               checkElement(list, 2U, "AbCd", 100);
-               checkElement(list, 3U, "bCd", 200);
-               checkElement(list, 4U, "cde", 400);
-               ReSeqList::Index index;
-               ReSeqList::Tag tag;
-               checkT(list.binarySearch("Abc", -1, index, &tag));
-               checkEqu(0u, index);
-               checkT(list.binarySearch("AbcD", -1, index, &tag));
-               checkEqu(2u, index);
-               checkT(list.binarySearch("bCd", -1, index, &tag));
-               checkEqu(3u, index);
-               checkT(list.binarySearch("cde", -1, index, &tag));
-               checkEqu(4u, index);
-       }
-       void testIgnoreCase(){
-               ReSeqList list;
-               list.setIgnoreCase(true);
-               ReByteBuffer value, expectedValue;
-               list.add(-1, "bcd", -1, 200);
-               list.add(0, "abc", -1, 100);
-               list.dump(stdout);
-               checkEqu(0U, list.find("AbC", -1));
-               checkEqu(1U, list.find("BCD", -1));
-       }
-       void testAdd(){
-               ReSeqList list;
-               ReByteBuffer value, expectedValue;
-               ReSeqList::Tag tag = 0;
-               ReSeqList::Tag expectedTag = 0;
-               size_t maxIx = 64;
-               for (size_t ix = 0; ix < maxIx; ix++){
-                       expectedTag = (1ll << ix);
-                       expectedValue.append("x", 1);
-                       list.add(-1, expectedValue.str(), -1, expectedTag);
-                       checkEqu(ix + 1, list.count());
-                       checkT(list.get(ix, value, &tag));
-                       checkEqu(expectedValue.str(), value.str());
-                       if (expectedTag != tag)
-                               checkEqu(expectedTag, tag);
-               }
-               expectedValue.setLength(0);
-               for (size_t ix = 0; ix < maxIx; ix++){
-                       expectedTag = (1ll << ix);
-                       expectedValue.append("x", 1);
-                       checkT(list.get(ix, value, &tag));
-                       checkEqu(expectedValue.str(), value.str());
-                       checkEqu(expectedTag, tag);
-               }
-
-       }
-       void testFind(){
-               ReSeqList list;
-               ReByteBuffer value, expectedValue;
-               ReSeqList::Tag tag = 0;
-               ReSeqList::Tag expectedTag = 0;
-               size_t maxIx = 13;
-               for (size_t ix = 0; ix < maxIx; ix++){
-                       expectedTag = 10*ix;
-                       expectedValue.append("x", 1);
-                       list.add(-1, expectedValue.str(), -1, expectedTag);
-                       checkEqu(ix + 1, list.count());
-                       checkT(list.get(ix, value, &tag));
-                       checkEqu(expectedValue.str(), value.str());
-                       if (expectedTag != tag)
-                               checkEqu(expectedTag, tag);
-               }
-               list.dump(stdout);
-               expectedValue.setLength(0);
-               for (size_t ix = 0; ix < maxIx; ix++){
-                       expectedTag = -1;
-                       expectedValue.append("x", 1);
-                       if (ix >= 4)
-                               expectedTag = -1;
-                       checkEqu(ix, list.find(expectedValue.str(), expectedValue.length(), &expectedTag));
-                       checkEqu(int(10*ix), (int) expectedTag);
-               }
-       }
-       void testBase(){
-               ReSeqList list;
-               ReByteBuffer value;
-               ReSeqList::Tag tag = 0;
-
-               list.add(-1, "xxx", -1, ReSeqList::Tag(1l) << 31);
-               checkT(list.get(0, value, &tag));
-               checkEqu(1ll << 31, tag);
-               checkEqu("xxx", value.str());
-
-               list.clear();
-               list.add(-1, "123", -1, 0x3344556633445566ll);
-               checkEqu(1u, list.count());
-               checkT(list.get(0, value, &tag));
-               checkEqu("123", value.str());
-               checkEqu((int64_t) 0x3344556633445566ll, tag);
-
-               list.add(-1, "ab", -1, 0x345678abcdef3344ll);
-               checkEqu(2u, list.count());
-               checkT(list.get(0, value));
-               checkEqu("123", value.str());
-               checkT(list.get(1, value, &tag));
-               checkEqu("ab", value.str());
-               checkEqu(0x345678abcdef3344ll, tag);
-
-               list.add(0, "xyz", -1, 300);
-               checkEqu(3u, list.count());
-               checkT(list.get(0, value, &tag));
-               checkEqu("xyz", value.str());
-               checkT(list.get(1, value));
-               checkEqu("123", value.str());
-               checkT(list.get(2, value));
-               checkEqu("ab", value.str());
-               checkEqu(300ll, tag);
-
-               list.add(1, "vw", -1, 400);
-               checkEqu(4u, list.count());
-               checkT(list.get(0, value));
-               checkEqu("xyz", value.str());
-               checkT(list.get(1, value, &tag));
-               checkEqu("vw", value.str());
-               checkT(list.get(2, value));
-               checkEqu("123", value.str());
-               checkT(list.get(3, value));
-               checkEqu("ab", value.str());
-               checkEqu(400ll, tag);
-
-               list.clear();
-               checkEqu(0u, list.count());
-               checkF(list.get(0, value));
-       }
-       void testRemove(){
-               ReSeqList list;
-               ReByteBuffer value;
-               ReSeqList::Tag tag = 0;
-
-               list.add(-1, "abc", -1, 100);
-               list.add(-1, "def12", -1, 200);
-               list.add(-1, "ghi", -1, 300);
-               list.add(-1, "jkl134", -1, 400);
-
-               list.remove(3);
-               checkEqu(3u, list.count());
-               list.get(0, value, &tag);
-               checkEqu("abc", value.str());
-               checkEqu(100ll, tag);
-               list.get(1, value, &tag);
-               checkEqu("def12", value.str());
-               checkEqu(200ll, tag);
-               list.get(2, value, &tag);
-               checkEqu("ghi", value.str());
-               checkEqu(300ll, tag);
-
-
-               list.remove(1);
-               checkEqu(2u, list.count());
-               list.get(0, value, &tag);
-               checkEqu("abc", value.str());
-               checkEqu(100ll, tag);
-               list.get(1, value, &tag);
-               checkEqu("ghi", value.str());
-               checkEqu(300ll, tag);
-
-               list.remove(0);
-               checkEqu(1u, list.count());
-               list.get(0, value, &tag);
-               checkEqu("ghi", value.str());
-               checkEqu(300ll, tag);
-
-       }
-};
-extern void testReSeqList(void);
-
-void testReSeqList(void){
-       TestReSeqList unit;
-}
index 18ac15ad6257ca2003d57561397a569097150392..d181b888b9a202a084b232a87215aa582cf469ab 100644 (file)
 void testBase(){
        extern void testReHashList(void);
        //testReHashList();
-       extern void testReSeqList();
-       testReSeqList();
+       extern void testReSeqArray();
+       testReSeqArray();
        extern void testReTestUnit();
        // testReTestUnit();
        extern void testReByteBuffer();
        testReByteBuffer();
-       extern void testReSeqList(void);
-       testReSeqList();
+       extern void testReSeqArray(void);
+       testReSeqArray();
        extern void testReHashList(void);
        testReHashList();
        void testReException(void);