static void AddNewElement (TRI_hash_array_t* array, TRI_hash_index_element_t* element) { uint64_t hash; uint64_t i; // ........................................................................... // compute the hash // ........................................................................... hash = HashElement(array, element); // ........................................................................... // search the table // ........................................................................... i = hash % array->_nrAlloc; while (! IsEmptyElement(array, &array->_table[i])) { i = (i + 1) % array->_nrAlloc; #ifdef TRI_INTERNAL_STATS array->_nrProbesR++; #endif } // ........................................................................... // add a new element to the associative array // memcpy ok here since are simply moving array items internally // ........................................................................... memcpy(&array->_table[i], element, sizeof(TRI_hash_index_element_t)); array->_nrUsed++; }
void JingleFileTransferFileInfoParser::handleEndElement(const std::string& element, const std::string&) { --level; if (level == 1) { if (element == "date") { getPayloadInternal()->setDate(stringToDateTime(charData)); } else if (element == "desc") { getPayloadInternal()->setDescription(charData); } else if (element == "media-type") { getPayloadInternal()->setMediaType(charData); } else if (element == "name") { getPayloadInternal()->setName(charData); } else if (element == "size") { boost::optional<boost::uintmax_t> size = safeLexicalCast<boost::uintmax_t>(charData); if (size) { getPayloadInternal()->setSize(size.get()); } } else if (element == "range") { getPayloadInternal()->setSupportsRangeRequests(true); if (rangeOffset) { getPayloadInternal()->setRangeOffset(rangeOffset.get_value_or(0)); } } else if (element == "hash") { getPayloadInternal()->addHash(HashElement(hashAlg, Base64::decode(charData))); } } }
TRI_vector_pointer_t TRI_LookupByElementHashArrayMulti (TRI_hash_array_t* array, TRI_hash_index_element_t* element) { TRI_vector_pointer_t result; uint64_t hash; uint64_t i; // ........................................................................... // initialise the vector which will hold the result if any // ........................................................................... TRI_InitVectorPointer(&result, TRI_UNKNOWN_MEM_ZONE); // ........................................................................... // compute the hash // ........................................................................... hash = HashElement(array, element); i = hash % array->_nrAlloc; // ........................................................................... // update statistics // ........................................................................... #ifdef TRI_INTERNAL_STATS array->_nrFinds++; #endif // ........................................................................... // search the table // ........................................................................... while (! IsEmptyElement(array, &array->_table[i])) { if (IsEqualElementElement(array, element, &array->_table[i])) { TRI_PushBackVectorPointer(&result, &array->_table[i]); } #ifdef TRI_INTERNAL_STATS else { array->_nrProbesF++; } #endif i = (i + 1) % array->_nrAlloc; } // ........................................................................... // return whatever we found -- which could be an empty vector list if nothing // matches. Note that we allow multiple elements (compare with pointer impl). // ........................................................................... return result; }
static int ResizeHashArray (TRI_hash_array_multi_t* array, uint64_t targetSize, bool allowShrink) { if (array->_nrAlloc >= targetSize && ! allowShrink) { return TRI_ERROR_NO_ERROR; } TRI_hash_index_element_multi_t* oldTable = array->_table; TRI_hash_index_element_multi_t* oldTablePtr = array->_tablePtr; uint64_t oldAlloc = array->_nrAlloc; TRI_ASSERT(targetSize > 0); int res = AllocateTable(array, targetSize); if (res != TRI_ERROR_NO_ERROR) { return res; } if (array->_nrUsed > 0) { uint64_t const n = array->_nrAlloc; for (uint64_t j = 0; j < oldAlloc; j++) { TRI_hash_index_element_multi_t* element = &oldTable[j]; if (element->_document != nullptr) { uint64_t i, k; i = k = HashElement(array, element) % n; for (; i < n && array->_table[i]._document != nullptr; ++i); if (i == n) { for (i = 0; i < k && array->_table[i]._document != nullptr; ++i); } TRI_ASSERT_EXPENSIVE(i < n); // ........................................................................... // add a new element to the associative array // memcpy ok here since are simply moving array items internally // ........................................................................... memcpy(&array->_table[i], element, TableEntrySize()); } } } TRI_Free(TRI_UNKNOWN_MEM_ZONE, oldTablePtr); return TRI_ERROR_NO_ERROR; }
TRI_hash_index_element_t* TRI_LookupByElementHashArray (TRI_hash_array_t* array, TRI_hash_index_element_t* element) { uint64_t hash; uint64_t i; // ........................................................................... // compute the hash // ........................................................................... hash = HashElement(array, element); i = hash % array->_nrAlloc; // ........................................................................... // update statistics // ........................................................................... #ifdef TRI_INTERNAL_STATS array->_nrFinds++; #endif // ........................................................................... // search the table // ........................................................................... while (! IsEmptyElement(array, &array->_table[i]) && ! IsEqualElementElement(array, element, &array->_table[i])) { i = (i + 1) % array->_nrAlloc; #ifdef TRI_INTERNAL_STATS array->_nrProbesF++; #endif } // ........................................................................... // return whatever we found // ........................................................................... return &array->_table[i]; }
int TRI_RemoveElementHashArrayMulti (TRI_hash_array_multi_t* array, TRI_index_search_value_t const* key, TRI_hash_index_element_multi_t* element) { uint64_t const n = array->_nrAlloc; uint64_t i, k; i = k = HashKey(array, key) % n; for (; i < n && array->_table[i]._document != nullptr && ! IsEqualKeyElement(array, key, &array->_table[i]); ++i); if (i == n) { for (i = 0; i < k && array->_table[i]._document != nullptr && ! IsEqualKeyElement(array, key, &array->_table[i]); ++i); } TRI_ASSERT_EXPENSIVE(i < n); TRI_hash_index_element_multi_t* arrayElement = &array->_table[i]; bool found = (arrayElement->_document != nullptr); if (! found) { return TRI_RESULT_ELEMENT_NOT_FOUND; } if (arrayElement->_document != element->_document) { // look in the overflow list for the sought document auto next = &(arrayElement->_next); while (*next != nullptr) { if ((*next)->_document == element->_document) { auto ptr = (*next)->_next; DestroyElement(array, *next); ReturnToFreelist(array, *next); *next = ptr; return TRI_ERROR_NO_ERROR; } next = &((*next)->_next); } return TRI_RESULT_ELEMENT_NOT_FOUND; } // the element itself is the document to remove TRI_ASSERT(arrayElement->_document == element->_document); if (arrayElement->_next != nullptr) { auto next = arrayElement->_next; // destroy our own data first, otherwise we'll leak TRI_ASSERT(arrayElement->_subObjects != nullptr); TRI_Free(TRI_UNKNOWN_MEM_ZONE, arrayElement->_subObjects); // copy data from first overflow element into ourselves arrayElement->_document = next->_document; arrayElement->_subObjects = next->_subObjects; arrayElement->_next = next->_next; // and remove the first overflow element next->_subObjects = nullptr; DestroyElement(array, next); ReturnToFreelist(array, next); return TRI_ERROR_NO_ERROR; } TRI_ASSERT(arrayElement->_next == nullptr); DestroyElement(array, arrayElement); array->_nrUsed--; // ........................................................................... // and now check the following places for items to move here // ........................................................................... k = TRI_IncModU64(i, n); while (array->_table[k]._document != nullptr) { uint64_t j = HashElement(array, &array->_table[k]) % n; if ((i < k && ! (i < j && j <= k)) || (k < i && ! (i < j || j <= k))) { array->_table[i] = array->_table[k]; array->_table[k]._document = nullptr; array->_table[k]._next = nullptr; array->_table[k]._subObjects = nullptr; i = k; } k = TRI_IncModU64(k, n); } if (array->_nrUsed == 0) { TRI_ASSERT(array->_nrOverflowUsed == 0); ResizeHashArray(array, InitialSize(), true); } return TRI_ERROR_NO_ERROR; }
int TRI_RemoveKeyHashArray (TRI_hash_array_t* array, TRI_index_search_value_t* key) { uint64_t hash; uint64_t i; uint64_t k; bool found; void* arrayElement; // ........................................................................... // compute the hash // ........................................................................... hash = HashKey(array, key); i = hash % array->_nrAlloc; // ........................................................................... // update statistics // ........................................................................... #ifdef TRI_INTERNAL_STATS array->_nrRems++; #endif // ........................................................................... // search the table // ........................................................................... while (! IsEmptyElement(array, &array->_table[i]) && ! IsEqualKeyElement(array, key, &array->_table[i])) { i = (i + 1) % array->_nrAlloc; #ifdef TRI_INTERNAL_STATS array->_nrProbesD++; #endif } arrayElement = &array->_table[i]; // ........................................................................... // if we did not find such an item return false // ........................................................................... found = ! IsEmptyElement(array, arrayElement); if (! found) { return TRI_RESULT_KEY_NOT_FOUND; } // ........................................................................... // remove item // ........................................................................... DestroyElement(array, arrayElement); array->_nrUsed--; // ........................................................................... // and now check the following places for items to move here // ........................................................................... k = (i + 1) % array->_nrAlloc; while (! IsEmptyElement(array, &array->_table[k])) { uint64_t j = HashElement(array, &array->_table[k]) % array->_nrAlloc; if ((i < k && !(i < j && j <= k)) || (k < i && !(i < j || j <= k))) { array->_table[i] = array->_table[k]; ClearElement(array, &array->_table[k]); i = k; } k = (k + 1) % array->_nrAlloc; } // ........................................................................... // return success // ........................................................................... return TRI_ERROR_NO_ERROR; }
int TRI_RemoveElementHashArray (TRI_hash_array_t* array, TRI_hash_index_element_t* element) { uint64_t hash; uint64_t i; uint64_t k; bool found; void* arrayElement; // ........................................................................... // compute the hash // ........................................................................... hash = HashElement(array, element); i = hash % array->_nrAlloc; // ........................................................................... // update statistics // ........................................................................... #ifdef TRI_INTERNAL_STATS array->_nrRems++; #endif // ........................................................................... // search the table // ........................................................................... while (! IsEmptyElement(array, &array->_table[i]) && ! IsEqualElementElement(array, element, &array->_table[i])) { i = (i + 1) % array->_nrAlloc; #ifdef TRI_INTERNAL_STATS array->_nrProbesD++; #endif } arrayElement = &array->_table[i]; // ........................................................................... // if we did not find such an item return false // ........................................................................... found = ! IsEmptyElement(array, arrayElement); if (! found) { return TRI_RESULT_ELEMENT_NOT_FOUND; } // ........................................................................... // remove item - destroy any internal memory associated with the element structure // ........................................................................... DestroyElement(array, arrayElement); array->_nrUsed--; // ........................................................................... // and now check the following places for items to move closer together // so that there are no gaps in the array // ........................................................................... k = (i + 1) % array->_nrAlloc; while (! IsEmptyElement(array, &array->_table[k])) { uint64_t j = HashElement(array, &array->_table[k]) % array->_nrAlloc; if ((i < k && !(i < j && j <= k)) || (k < i && !(i < j || j <= k))) { array->_table[i] = array->_table[k]; ClearElement(array, &array->_table[k]); i = k; } k = (k + 1) % array->_nrAlloc; } return TRI_ERROR_NO_ERROR; }
int TRI_InsertElementHashArray (TRI_hash_array_t* array, TRI_hash_index_element_t* element, bool overwrite) { uint64_t hash; uint64_t i; bool found; int res; TRI_hash_index_element_t* arrayElement; // ........................................................................... // compute the hash // ........................................................................... hash = HashElement(array, element); i = hash % array->_nrAlloc; // ........................................................................... // update statistics // ........................................................................... #ifdef TRI_INTERNAL_STATS array->_nrAdds++; #endif // ........................................................................... // search the table // ........................................................................... while (! IsEmptyElement(array, &array->_table[i]) && ! IsEqualElementElement(array, element, &array->_table[i])) { i = (i + 1) % array->_nrAlloc; #ifdef TRI_INTERNAL_STATS array->_nrProbesA++; #endif } arrayElement = &array->_table[i]; // ........................................................................... // if we found an element, return // ........................................................................... found = ! IsEmptyElement(array, arrayElement); if (found) { if (overwrite) { // destroy the underlying element since we are going to stomp on top if it DestroyElement(array, arrayElement); *arrayElement = *element; } else { DestroyElement(array, element); } return TRI_RESULT_ELEMENT_EXISTS; } // ........................................................................... // add a new element to the hash array (existing item is empty so no need to // destroy it) // ........................................................................... *arrayElement = *element; array->_nrUsed++; // ........................................................................... // we are adding and the table is more than half full, extend it // ........................................................................... if (array->_nrAlloc < 2 * array->_nrUsed) { res = ResizeHashArray(array); if (res != TRI_ERROR_NO_ERROR) { return res; } } return TRI_ERROR_NO_ERROR; }
int TRI_InsertElementHashArrayMulti (TRI_hash_array_t* array, TRI_hash_index_element_t* element, bool overwrite) { uint64_t hash; uint64_t i; bool found; int res; TRI_hash_index_element_t* arrayElement; // ........................................................................... // compute the hash // ........................................................................... hash = HashElement(array, element); i = hash % array->_nrAlloc; // ........................................................................... // update statistics // ........................................................................... #ifdef TRI_INTERNAL_STATS array->_nrAdds++; #endif // ........................................................................... // search the table // ........................................................................... while (! IsEmptyElement(array, &array->_table[i]) && ! IsEqualElementElement(array, element, &array->_table[i])) { i = (i + 1) % array->_nrAlloc; #ifdef TRI_INTERNAL_STATS array->_nrProbesA++; #endif } arrayElement = &array->_table[i]; // ........................................................................... // If we found an element, return. While we allow duplicate entries in the // hash table, we do not allow duplicate elements. Elements would refer to the // (for example) an actual row in memory. This is different from the // TRI_InsertElementMultiArray function below where we only have keys to // differentiate between elements. // ........................................................................... found = ! IsEmptyElement(array, arrayElement); if (found) { if (overwrite) { // destroy the underlying element since we are going to stomp on top if it DestroyElement(array, arrayElement); *arrayElement = *element; } else { DestroyElement(array, element); } return TRI_RESULT_ELEMENT_EXISTS; } // ........................................................................... // add a new element to the associative array // ........................................................................... *arrayElement = *element; array->_nrUsed++; // ........................................................................... // if we were adding and the table is more than half full, extend it // ........................................................................... if (array->_nrAlloc < 2 * array->_nrUsed) { res = ResizeHashArray(array); if (res != TRI_ERROR_NO_ERROR) { return res; } } return TRI_ERROR_NO_ERROR; }