diff --git a/include/etl/unordered_multimap.h b/include/etl/unordered_multimap.h index 80ff8d91..1ca8434d 100644 --- a/include/etl/unordered_multimap.h +++ b/include/etl/unordered_multimap.h @@ -681,10 +681,9 @@ namespace etl // Just add the pointer to the bucket; bucket.insert_after(bucket.before_begin(), node); + adjust_first_last_markers_after_insert(pbucket); result = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin()); - - adjust_first_last_markers(pbucket); } else { @@ -711,6 +710,7 @@ namespace etl // Add the node to the end of the bucket; bucket.insert_after(inode_previous, node); + adjust_first_last_markers_after_insert(&bucket); ++inode_previous; result = iterator((pbuckets + number_of_buckets), pbucket, inode_previous); @@ -768,6 +768,7 @@ namespace etl bucket.erase_after(iprevious); // Unlink from the bucket. icurrent->key_value_pair.~value_type(); // Destroy the value. pnodepool->release(&*icurrent); // Release it back to the pool. + adjust_first_last_markers_after_erase(&bucket); ++n; icurrent = iprevious; ETL_DECREMENT_DEBUG_COUNT @@ -806,6 +807,7 @@ namespace etl bucket.erase_after(iprevious); // Unlink from the bucket. icurrent->key_value_pair.~value_type(); // Destroy the value. pnodepool->release(&*icurrent); // Release it back to the pool. + adjust_first_last_markers_after_erase(&bucket); ETL_DECREMENT_DEBUG_COUNT return inext; @@ -841,6 +843,7 @@ namespace etl local_iterator inext = pbucket->erase_after(iprevious); // Unlink from the bucket. icurrent->key_value_pair.~value_type(); // Destroy the value. pnodepool->release(&*icurrent); // Release it back to the pool. + adjust_first_last_markers_after_erase(pbucket); ETL_DECREMENT_DEBUG_COUNT icurrent = inext; @@ -1157,16 +1160,69 @@ namespace etl //********************************************************************* /// Adjust the first and last markers according to the new entry. //********************************************************************* - void adjust_first_last_markers(bucket_t* pbucket) + void adjust_first_last_markers_after_insert(bucket_t* pbucket) { - if (pbucket < first) + if (size() == 1) { first = pbucket; - } - else if (pbucket > last) - { last = pbucket; } + else + { + if (pbucket < first) + { + first = pbucket; + } + else if (pbucket > last) + { + last = pbucket; + } + } + } + + //********************************************************************* + /// Adjust the first and last markers according to the erased entry. + //********************************************************************* + void adjust_first_last_markers_after_erase(bucket_t* pbucket) + { + if (empty()) + { + first = pbuckets; + last = pbuckets; + } + else + { + if (pbucket == first) + { + // We erased the first so, we need to search again from where we erased. + while (first->empty()) + { + ++first; + } + } + else if (pbucket == last) + { + // We erased the last, so we need to search again. Start from the first, go no further than the current last. + bucket_t* pbucket = first; + bucket_t* pend = last; + + last = first; + + while (pbucket != pend) + { + if (!pbucket->empty()) + { + last = pbucket; + } + + ++pbucket; + } + } + else + { + // Nothing to do. + } + } } // Disable copy construction. diff --git a/include/etl/unordered_multiset.h b/include/etl/unordered_multiset.h index c6e57901..2f87bd0e 100644 --- a/include/etl/unordered_multiset.h +++ b/include/etl/unordered_multiset.h @@ -674,11 +674,10 @@ namespace etl // Just add the pointer to the bucket; bucket.insert_after(bucket.before_begin(), node); + adjust_first_last_markers_after_insert(&bucket); result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin()); result.second = true; - - adjust_first_last_markers(pbucket); } else { @@ -705,6 +704,7 @@ namespace etl // Add the node to the end of the bucket; bucket.insert_after(inode_previous, node); + adjust_first_last_markers_after_insert(&bucket); ++inode_previous; result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous); @@ -763,6 +763,7 @@ namespace etl bucket.erase_after(iprevious); // Unlink from the bucket. icurrent->key.~value_type(); // Destroy the value. pnodepool->release(&*icurrent); // Release it back to the pool. + adjust_first_last_markers_after_erase(&bucket); ++n; icurrent = iprevious; ETL_DECREMENT_DEBUG_COUNT @@ -801,6 +802,7 @@ namespace etl bucket.erase_after(iprevious); // Unlink from the bucket. icurrent->key.~value_type(); // Destroy the value. pnodepool->release(&*icurrent); // Release it back to the pool. + adjust_first_last_markers_after_erase(&bucket); ETL_DECREMENT_DEBUG_COUNT return inext; @@ -836,6 +838,7 @@ namespace etl local_iterator inext = pbucket->erase_after(iprevious); // Unlink from the bucket. icurrent->key.~value_type(); // Destroy the value. pnodepool->release(&*icurrent); // Release it back to the pool. + adjust_first_last_markers_after_erase(pbucket); ETL_DECREMENT_DEBUG_COUNT icurrent = inext; @@ -1152,16 +1155,69 @@ namespace etl //********************************************************************* /// Adjust the first and last markers according to the new entry. //********************************************************************* - void adjust_first_last_markers(bucket_t* pbucket) + void adjust_first_last_markers_after_insert(bucket_t* pbucket) { - if (pbucket < first) + if (size() == 1) { first = pbucket; - } - else if (pbucket > last) - { last = pbucket; } + else + { + if (pbucket < first) + { + first = pbucket; + } + else if (pbucket > last) + { + last = pbucket; + } + } + } + + //********************************************************************* + /// Adjust the first and last markers according to the erased entry. + //********************************************************************* + void adjust_first_last_markers_after_erase(bucket_t* pbucket) + { + if (empty()) + { + first = pbuckets; + last = pbuckets; + } + else + { + if (pbucket == first) + { + // We erased the first so, we need to search again from where we erased. + while (first->empty()) + { + ++first; + } + } + else if (pbucket == last) + { + // We erased the last, so we need to search again. Start from the first, go no further than the current last. + bucket_t* pbucket = first; + bucket_t* pend = last; + + last = first; + + while (pbucket != pend) + { + if (!pbucket->empty()) + { + last = pbucket; + } + + ++pbucket; + } + } + else + { + // Nothing to do. + } + } } // Disable copy construction. diff --git a/include/etl/unordered_set.h b/include/etl/unordered_set.h index fb208cb4..7331cdc0 100644 --- a/include/etl/unordered_set.h +++ b/include/etl/unordered_set.h @@ -675,11 +675,10 @@ namespace etl // Just add the pointer to the bucket; bucket.insert_after(bucket.before_begin(), node); + adjust_first_last_markers_after_insert(&bucket); result.first = iterator(pbuckets + number_of_buckets, pbucket, pbucket->begin()); result.second = true; - - adjust_first_last_markers(pbucket); } else { @@ -709,6 +708,7 @@ namespace etl // Add the node to the end of the bucket; bucket.insert_after(inode_previous, node); + adjust_first_last_markers_after_insert(&bucket); ++inode_previous; result.first = iterator(pbuckets + number_of_buckets, pbucket, inode_previous); @@ -774,6 +774,7 @@ namespace etl bucket.erase_after(iprevious); // Unlink from the bucket. icurrent->key.~value_type(); // Destroy the value. pnodepool->release(&*icurrent); // Release it back to the pool. + adjust_first_last_markers_after_erase(&bucket); n = 1; ETL_DECREMENT_DEBUG_COUNT } @@ -804,6 +805,7 @@ namespace etl bucket.erase_after(iprevious); // Unlink from the bucket. icurrent->key.~value_type(); // Destroy the value. pnodepool->release(&*icurrent); // Release it back to the pool. + adjust_first_last_markers_after_erase(&bucket); ETL_DECREMENT_DEBUG_COUNT return inext; @@ -839,6 +841,7 @@ namespace etl local_iterator inext = pbucket->erase_after(iprevious); // Unlink from the bucket. icurrent->key.~value_type(); // Destroy the value. pnodepool->release(&*icurrent); // Release it back to the pool. + adjust_first_last_markers_after_erase(pbucket); ETL_DECREMENT_DEBUG_COUNT icurrent = inext; @@ -1129,16 +1132,69 @@ namespace etl //********************************************************************* /// Adjust the first and last markers according to the new entry. //********************************************************************* - void adjust_first_last_markers(bucket_t* pbucket) + void adjust_first_last_markers_after_insert(bucket_t* pbucket) { - if (pbucket < first) + if (size() == 1) { first = pbucket; - } - else if (pbucket > last) - { last = pbucket; } + else + { + if (pbucket < first) + { + first = pbucket; + } + else if (pbucket > last) + { + last = pbucket; + } + } + } + + //********************************************************************* + /// Adjust the first and last markers according to the erased entry. + //********************************************************************* + void adjust_first_last_markers_after_erase(bucket_t* pbucket) + { + if (empty()) + { + first = pbuckets; + last = pbuckets; + } + else + { + if (pbucket == first) + { + // We erased the first so, we need to search again from where we erased. + while (first->empty()) + { + ++first; + } + } + else if (pbucket == last) + { + // We erased the last, so we need to search again. Start from the first, go no further than the current last. + bucket_t* pbucket = first; + bucket_t* pend = last; + + last = first; + + while (pbucket != pend) + { + if (!pbucket->empty()) + { + last = pbucket; + } + + ++pbucket; + } + } + else + { + // Nothing to do. + } + } } // Disable copy construction. diff --git a/test/vs2017/.vs/etl/v15/.gitignore b/test/vs2017/.vs/etl/v15/.gitignore new file mode 100644 index 00000000..83235bb7 --- /dev/null +++ b/test/vs2017/.vs/etl/v15/.gitignore @@ -0,0 +1 @@ +*.VC.opendb