@@ -611,19 +611,21 @@ void QList::AppendPlain(unsigned char* data, size_t sz) {
611611bool QList::Insert (std::string_view pivot, std::string_view elem, InsertOpt opt) {
612612 Iterator it = GetIterator (HEAD);
613613
614- while (it.Next ()) {
615- if (it.Get () == pivot) {
616- Insert (it, elem, opt);
617- return true ;
618- }
614+ if (it.Valid ()) {
615+ do {
616+ if (it.Get () == pivot) {
617+ Insert (it, elem, opt);
618+ return true ;
619+ }
620+ } while (it.Next ());
619621 }
620622
621623 return false ;
622624}
623625
624626bool QList::Replace (long index, std::string_view elem) {
625627 Iterator it = GetIterator (index);
626- if (it.Next ()) {
628+ if (it.Valid ()) {
627629 Replace (it, elem);
628630 return true ;
629631 }
@@ -650,10 +652,12 @@ void QList::Iterate(IterateFunc cb, long start, long end) const {
650652 if (end < 0 || end >= long (Size ()))
651653 end = Size () - 1 ;
652654 Iterator it = GetIterator (start);
653- while (start <= end && it.Next ()) {
654- if (!cb (it.Get ()))
655- break ;
656- start++;
655+ if (it.Valid ()) {
656+ do {
657+ if (start > end || !cb (it.Get ()))
658+ break ;
659+ start++;
660+ } while (it.Next ());
657661 }
658662}
659663
@@ -1053,6 +1057,16 @@ bool QList::DelPackedIndex(Node* node, uint8_t* p) {
10531057 return false ;
10541058}
10551059
1060+ void QList::InitIteratorEntry (Iterator* it) const {
1061+ DCHECK (it->current_ );
1062+ const_cast <QList*>(this )->malloc_size_ += DecompressNodeIfNeeded (true , it->current_ );
1063+ if (QL_NODE_IS_PLAIN (it->current_ )) {
1064+ it->zi_ = it->current_ ->entry ;
1065+ } else {
1066+ it->zi_ = lpSeek (it->current_ ->entry , it->offset_ );
1067+ }
1068+ }
1069+
10561070auto QList::GetIterator (Where where) const -> Iterator {
10571071 Iterator it;
10581072 it.owner_ = this ;
@@ -1067,6 +1081,10 @@ auto QList::GetIterator(Where where) const -> Iterator {
10671081 it.direction_ = REV;
10681082 }
10691083
1084+ if (it.current_ ) {
1085+ InitIteratorEntry (&it);
1086+ }
1087+
10701088 return it;
10711089}
10721090
@@ -1119,6 +1137,8 @@ auto QList::GetIterator(long idx) const -> Iterator {
11191137 iter.offset_ = (-index) - 1 + accum;
11201138 }
11211139
1140+ InitIteratorEntry (&iter);
1141+
11221142 return iter;
11231143}
11241144
@@ -1137,10 +1157,9 @@ auto QList::Erase(Iterator it) -> Iterator {
11371157 deleted_node = DelPackedIndex (node, it.zi_ );
11381158 }
11391159
1140- /* after delete, the zi is now invalid for any future usage. */
1141- it.zi_ = NULL ;
1160+ it.zi_ = NULL ; // Reset current entry pointer
11421161
1143- /* If current node is deleted, we must update iterator node and offset. */
1162+ // If current node is deleted, we must update iterator node and offset.
11441163 if (deleted_node) {
11451164 if (it.direction_ == FWD) {
11461165 it.current_ = next;
@@ -1151,6 +1170,10 @@ auto QList::Erase(Iterator it) -> Iterator {
11511170 }
11521171 }
11531172
1173+ if (it.current_ ) {
1174+ InitIteratorEntry (&it);
1175+ }
1176+
11541177 // Sanity, should be noop in release mode.
11551178 if (len_ == 1 ) {
11561179 DCHECK_EQ (count_, head_->count );
@@ -1241,29 +1264,35 @@ bool QList::Erase(const long start, unsigned count) {
12411264 return true ;
12421265}
12431266
1267+ uint8_t * QList::TryExtractListpack () {
1268+ // TODO: enable this once we support listpack encoding for lists.
1269+ return nullptr ;
1270+
1271+ if (len_ != 1 || QL_NODE_IS_PLAIN (head_) || !ShouldStoreAsListPack (head_->sz ) ||
1272+ head_->IsCompressed ()) {
1273+ return nullptr ;
1274+ }
1275+
1276+ uint8_t * res = std::exchange (head_->entry , nullptr );
1277+ DelNode (head_);
1278+
1279+ return res;
1280+ }
1281+
12441282bool QList::Iterator::Next () {
12451283 if (!current_)
12461284 return false ;
12471285
12481286 int plain = QL_NODE_IS_PLAIN (current_);
1249- if (!zi_) {
1250- /* If !zi, use current index. */
1251- const_cast <QList*>(owner_)->malloc_size_ += DecompressNodeIfNeeded (true , current_);
1252- if (ABSL_PREDICT_FALSE (plain))
1253- zi_ = current_->entry ;
1254- else
1255- zi_ = lpSeek (current_->entry , offset_);
1256- } else if (ABSL_PREDICT_FALSE (plain)) {
1287+
1288+ // Advance to the next element in the current node.
1289+ if (ABSL_PREDICT_FALSE (plain)) {
12571290 zi_ = NULL ;
12581291 } else {
1259- unsigned char * (*nextFn)(unsigned char *, unsigned char *) = NULL ;
1260- int offset_update = 0 ;
1292+ unsigned char * (*nextFn)(unsigned char *, unsigned char *) = lpNext ;
1293+ int offset_update = 1 ;
12611294
1262- /* else, use existing iterator offset and get prev/next as necessary. */
1263- if (direction_ == FWD) {
1264- nextFn = lpNext;
1265- offset_update = 1 ;
1266- } else {
1295+ if (direction_ == REV) {
12671296 DCHECK_EQ (REV, direction_);
12681297 nextFn = lpPrev;
12691298 offset_update = -1 ;
@@ -1275,7 +1304,7 @@ bool QList::Iterator::Next() {
12751304 if (zi_)
12761305 return true ;
12771306
1278- // Retry again with the next node.
1307+ // Move to the next node.
12791308 const_cast <QList*>(owner_)->Compress (current_);
12801309
12811310 if (direction_ == FWD) {
@@ -1289,7 +1318,11 @@ bool QList::Iterator::Next() {
12891318 current_ = (current_ == owner_->head_ ) ? nullptr : current_->prev ;
12901319 }
12911320
1292- return current_ ? Next () : false ;
1321+ if (!current_)
1322+ return false ;
1323+
1324+ owner_->InitIteratorEntry (this );
1325+ return zi_ != nullptr ;
12931326}
12941327
12951328auto QList::Iterator::Get () const -> Entry {
0 commit comments