| 510 | } |
| 511 | |
| 512 | std::pair<bdecode_node, bdecode_node> bdecode_node::dict_at_node(int i) const |
| 513 | { |
| 514 | TORRENT_ASSERT(type() == dict_t); |
| 515 | TORRENT_ASSERT(m_token_idx != -1); |
| 516 | |
| 517 | bdecode_token const* tokens = m_root_tokens; |
| 518 | TORRENT_ASSERT(tokens[m_token_idx].type == bdecode_token::dict); |
| 519 | |
| 520 | int token = m_token_idx + 1; |
| 521 | int item = 0; |
| 522 | |
| 523 | // do we have a lookup cached? |
| 524 | if (m_last_index <= i && m_last_index != -1) |
| 525 | { |
| 526 | token = m_last_token; |
| 527 | item = m_last_index; |
| 528 | } |
| 529 | |
| 530 | while (item < i) |
| 531 | { |
| 532 | TORRENT_ASSERT(tokens[token].type == bdecode_token::string |
| 533 | || tokens[token].type == bdecode_token::long_string); |
| 534 | |
| 535 | // skip the key |
| 536 | token += tokens[token].next_item; |
| 537 | TORRENT_ASSERT(tokens[token].type != bdecode_token::end); |
| 538 | |
| 539 | // skip the value |
| 540 | token += tokens[token].next_item; |
| 541 | |
| 542 | ++item; |
| 543 | |
| 544 | // index 'i' out of range |
| 545 | TORRENT_ASSERT(tokens[token].type != bdecode_token::end); |
| 546 | } |
| 547 | |
| 548 | // there's no point in caching the first item |
| 549 | if (i > 0) |
| 550 | { |
| 551 | m_last_token = token; |
| 552 | m_last_index = i; |
| 553 | } |
| 554 | |
| 555 | int value_token = token + tokens[token].next_item; |
| 556 | TORRENT_ASSERT(tokens[token].type != bdecode_token::end); |
| 557 | |
| 558 | return std::make_pair( |
| 559 | bdecode_node(tokens, m_buffer, m_buffer_size, token) |
| 560 | , bdecode_node(tokens, m_buffer, m_buffer_size, value_token)); |
| 561 | } |
| 562 | |
| 563 | std::pair<string_view, bdecode_node> bdecode_node::dict_at(int const i) const |
| 564 | { |