* 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.
*/
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;
}
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)){
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);
}
void behindLast();
void priorFirst();
public:
- ReSeqList::Index m_position;
+ ReSeqArray::Index m_position;
bool m_forward;
};
/** @brief A simple associative array.
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);
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_ */
--- /dev/null
+/*
+ * 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;
+ }
+ }
+}
+
--- /dev/null
+/*
+ * 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_ */
+++ /dev/null
-/*
- * 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;
- }
- }
-}
-
+++ /dev/null
-/*
- * 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_ */
* @param deltaBuffer buffer reservation will be incremented by this amount
*/
ReStringList::ReStringList(int deltaList, int deltaBuffer) :
- ReSeqList(deltaList, deltaBuffer)
+ ReSeqArray(deltaList, deltaBuffer)
{
}
* @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);
*
* @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();
*
* @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();
* listOut.writeToFile("abc.csv");
* </code></pre>
*/
-class ReStringList : public ReSeqList {
+class ReStringList : public ReSeqArray {
public:
ReStringList(int deltaList = 1024, int deltaBuffer = 1024);
virtual ~ReStringList();
enum RELOC_LIB {
LC_CONFIGFILE = 50000,
LC_DIRTOOLS = 50100,
- LC_SEQLIST = 50200,
+ LC_SEQARRAY = 50200,
LC_HASHLIST = 50300,
};
enum RELOC_UDPCONNECTION {
#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"
testReI18N();
extern void testReStringList(void);
testReStringList();
- extern void testReSeqList(void);
- testReSeqList();
+ extern void testReSeqArray(void);
+ testReSeqArray();
extern void testReHashList(void);
testReHashList();
void testReException(void);
--- /dev/null
+#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;
+}
+++ /dev/null
-#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;
-}
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);