Like raxIteratorNextStep() but implements an iteration step moving * to the lexicographically previous element. The 'noup' option has a similar * effect to the one of raxIteratorNextStep(). */
| 1431 | * to the lexicographically previous element. The 'noup' option has a similar |
| 1432 | * effect to the one of raxIteratorNextStep(). */ |
| 1433 | int raxIteratorPrevStep(raxIterator *it, int noup) { |
| 1434 | if (it->flags & RAX_ITER_EOF) { |
| 1435 | return 1; |
| 1436 | } else if (it->flags & RAX_ITER_JUST_SEEKED) { |
| 1437 | it->flags &= ~RAX_ITER_JUST_SEEKED; |
| 1438 | return 1; |
| 1439 | } |
| 1440 | |
| 1441 | /* Save key len, stack items and the node where we are currently |
| 1442 | * so that on iterator EOF we can restore the current key and state. */ |
| 1443 | size_t orig_key_len = it->key_len; |
| 1444 | size_t orig_stack_items = it->stack.items; |
| 1445 | raxNode *orig_node = it->node; |
| 1446 | |
| 1447 | while(1) { |
| 1448 | int old_noup = noup; |
| 1449 | |
| 1450 | /* Already on head? Can't go up, iteration finished. */ |
| 1451 | if (!noup && it->node == it->rt->head) { |
| 1452 | it->flags |= RAX_ITER_EOF; |
| 1453 | it->stack.items = orig_stack_items; |
| 1454 | it->key_len = orig_key_len; |
| 1455 | it->node = orig_node; |
| 1456 | return 1; |
| 1457 | } |
| 1458 | |
| 1459 | unsigned char prevchild = it->key[it->key_len-1]; |
| 1460 | if (!noup) { |
| 1461 | it->node = raxStackPop(&it->stack); |
| 1462 | } else { |
| 1463 | noup = 0; |
| 1464 | } |
| 1465 | |
| 1466 | /* Adjust the current key to represent the node we are |
| 1467 | * at. */ |
| 1468 | int todel = it->node->iscompr ? it->node->size : 1; |
| 1469 | raxIteratorDelChars(it,todel); |
| 1470 | |
| 1471 | /* Try visiting the prev child if there is at least one |
| 1472 | * child. */ |
| 1473 | if (!it->node->iscompr && it->node->size > (old_noup ? 0 : 1)) { |
| 1474 | raxNode **cp = raxNodeLastChildPtr(it->node); |
| 1475 | int i = it->node->size-1; |
| 1476 | while (i >= 0) { |
| 1477 | debugf("SCAN PREV %c\n", it->node->data[i]); |
| 1478 | if (it->node->data[i] < prevchild) break; |
| 1479 | i--; |
| 1480 | cp--; |
| 1481 | } |
| 1482 | /* If we found a new subtree to explore in this node, |
| 1483 | * go deeper following all the last children in order to |
| 1484 | * find the key lexicographically greater. */ |
| 1485 | if (i != -1) { |
| 1486 | debugf("SCAN found a new node\n"); |
| 1487 | /* Enter the node we just found. */ |
| 1488 | if (!raxIteratorAddChars(it,it->node->data+i,1)) return 0; |
| 1489 | if (!raxStackPush(&it->stack,it->node)) return 0; |
| 1490 | memcpy(&it->node,cp,sizeof(it->node)); |
no test coverage detected