Beispiel #1
0
/**
 * Apply all edits onto the current leaf by doing a merge of the current pairs and the edits
 *
 * This is necessary for getting good performance (so we don't have to shift too many array items
 * on every insert).
 */
void LeafNode::applyAll(const editlist_t::iterator &editBegin, const editlist_t::iterator &editEnd)
{
    pairlist_t::iterator copy = pairs.begin();
    editlist_t::iterator edit = editBegin;

    // Reserve enough memory for worst-case scenario so we never reallocate
    pairlist_t updated;
    updated.reserve(pairs.size() + editEnd - editBegin);
    size_t newSize = 0;

    while (copy != pairs.end() || edit != editEnd)
    {
        // Deletes come from the end of the 'updated' array, but they can
        // only apply when the remove key is < the copy key (the next insert key).
        if (edit != editEnd && edit->edit != INSERT && (copy == pairs.end() || m_before(edit->key, *copy)))
        {
            bool didUpsert = false;

            // Normally I'd write a reverse_iterator loop, but for some reason they're giving me
            // memory trouble on clang (yet not on gcc, and valgrind is also clean).
            for (int i = updated.size(); i > 0 && updated[i - 1].first == edit->key; i--)
            {
                pairlist_t::iterator it = updated.begin() + i - 1;

                if (edit->edit == UPSERT)
                {
                    newSize -= it->second.size();
                    newSize += edit->value.size();
                    it->second = edit->value;
                    didUpsert = true;
                    break;
                }

                // Deletes
                if (edit->edit == REMOVE_KEY || (edit->edit == REMOVE_KV && edit->value == it->second))
                {
                    newSize -= it->first.size() + it->second.size();
                    updated.erase(it);
                    break;
                }
            }

            if (edit->edit == UPSERT && !didUpsert)
            {
                // Turn upsert into an insert
                updated.push_back(kv_pair(edit->key, edit->value));
                newSize += edit->key.size() + edit->value.size();
            }

            ++edit;
            continue;
        }

        // Inserts are taken from the front of the edit queue or the copy queue
        if (edit != editEnd && edit->edit == INSERT)
        {
            int keyComp = -1; // If there are no more items to compare to, be sure to insert
            if (copy != pairs.end())
                keyComp = m_before.fns.keyCompare(edit->key, copy->first);

            if (keyComp <= 0)
            {
                // Insert
                updated.push_back(kv_pair(edit->key, edit->value));
                newSize += edit->key.size() + edit->value.size();
                ++edit;
                continue;
            }
        }

        // No update applies -- regular copy
        if (copy != pairs.end())
        {
            updated.push_back(*copy);
            newSize += copy->first.size() + copy->second.size();
            ++copy;
        }
    }

    pairs.swap(updated);
    m_elementsSize = newSize;
}
Beispiel #2
0
		void node_data::insert_map_pair(node& key, node& value)
		{
			m_map[&key] = &value;
			if(!key.is_defined() || !value.is_defined())
				m_undefinedPairs.push_back(kv_pair(&key, &value));
		}