mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 14:22:43 +00:00 
			
		
		
		
	 6fd478b6ce
			
		
	
	
		6fd478b6ce
		
	
	
	
	
		
			
			These instances were detected by searching for files that include AK/Format.h, but don't match the regex: \\b(CheckedFormatString|critical_dmesgln|dbgln|dbgln_if|dmesgln|FormatBu ilder|__FormatIfSupported|FormatIfSupported|FormatParser|FormatString|Fo rmattable|Formatter|__format_value|HasFormatter|max_format_arguments|out |outln|set_debug_enabled|StandardFormatter|TypeErasedFormatParams|TypeEr asedParameter|VariadicFormatParams|v_critical_dmesgln|vdbgln|vdmesgln|vf ormat|vout|warn|warnln|warnln_if)\\b (Without the linebreaks.) This regex is pessimistic, so there might be more files that don't actually use any formatting functions. Observe that this revealed that Userland/Libraries/LibC/signal.cpp is missing an include. In theory, one might use LibCPP to detect things like this automatically, but let's do this one step after another.
		
			
				
	
	
		
			248 lines
		
	
	
	
		
			8.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			248 lines
		
	
	
	
		
			8.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2021, Jan de Visser <jan@de-visser.net>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #include <LibSQL/BTree.h>
 | |
| 
 | |
| namespace SQL {
 | |
| 
 | |
| BTreeIterator::BTreeIterator(TreeNode* node, int index)
 | |
|     : m_current(node)
 | |
|     , m_index(index)
 | |
| {
 | |
|     if (!node) {
 | |
|         m_where = Where::End;
 | |
|     } else {
 | |
|         if (index < 0) {
 | |
|             while (!node->is_leaf() && (node->size() != 0)) {
 | |
|                 node = node->down_node(0);
 | |
|             }
 | |
|             if (node->size() == 0) {
 | |
|                 m_where = Where::End;
 | |
|                 m_current = nullptr;
 | |
|                 m_index = -1;
 | |
|             } else {
 | |
|                 m_where = Where::Valid;
 | |
|                 m_current = node;
 | |
|                 m_index = 0;
 | |
|             }
 | |
|         } else {
 | |
|             VERIFY(m_index < (int)m_current->size());
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| int BTreeIterator::cmp(BTreeIterator const& other) const
 | |
| {
 | |
|     if (is_end())
 | |
|         return (other.is_end()) ? 0 : 1;
 | |
|     if (other.is_end())
 | |
|         return -1;
 | |
|     VERIFY(&other.m_current->tree() == &m_current->tree());
 | |
|     VERIFY((m_current->size() > 0) && (other.m_current->size() > 0));
 | |
|     if (&m_current != &other.m_current)
 | |
|         return (*m_current)[m_current->size() - 1].compare((*(other.m_current))[0]);
 | |
|     return (*m_current)[m_index].compare((*(other.m_current))[other.m_index]);
 | |
| }
 | |
| 
 | |
| int BTreeIterator::cmp(Key const& other) const
 | |
| {
 | |
|     if (is_end())
 | |
|         return 1;
 | |
|     if (other.is_null())
 | |
|         return -1;
 | |
|     return key().compare(other);
 | |
| }
 | |
| 
 | |
| BTreeIterator BTreeIterator::next() const
 | |
| {
 | |
|     if (is_end())
 | |
|         return end();
 | |
| 
 | |
|     auto ix = m_index;
 | |
|     auto node = m_current;
 | |
|     if (ix < (int)(node->size() - 1)) {
 | |
|         if (node->is_leaf()) {
 | |
|             // We're in the middle of a leaf node. Next entry is
 | |
|             // is the next entry of the node:
 | |
|             return BTreeIterator(node, ix + 1);
 | |
|         } else {
 | |
|             /*
 | |
|              * We're in the middle of a non-leaf node. The iterator's
 | |
|              * next value is all the way down to the right, first entry.
 | |
|              *
 | |
|              *                  |
 | |
|              *                  +--+--+--+--+
 | |
|              *                  |  |##|  |  |
 | |
|              *                  +--+--+--+--+
 | |
|              *                 /   |  |  |   \
 | |
|              *                        |
 | |
|              *               +--+--+--+--+
 | |
|              *               |  |  |  |  |
 | |
|              *               +--+--+--+--+
 | |
|              *              /
 | |
|              * +--+--+--+--+
 | |
|              * |++|  |  |  |
 | |
|              * +--+--+--+--+
 | |
|              */
 | |
|             ix++;
 | |
|             while (!node->is_leaf()) {
 | |
|                 node = node->down_node(ix);
 | |
|                 ix = 0;
 | |
|             }
 | |
|         }
 | |
|         VERIFY(node->is_leaf() && (ix < (int)node->size()));
 | |
|         return BTreeIterator(node, ix);
 | |
|     }
 | |
| 
 | |
|     if (node->is_leaf()) {
 | |
|         // We currently at the last entry of a leaf node. We need to check
 | |
|         // one or more levels up until we end up in the "middle" of a node.
 | |
|         // If one level up we're still at the end of the node, we need
 | |
|         // to keep going up until we hit the root node. If we're at the
 | |
|         // end of the root node, we reached the end of the btree.
 | |
|         for (auto up = node->up(); up; up = node->up()) {
 | |
|             for (size_t i = 0; i < up->size(); i++) {
 | |
|                 // One level up, try to find the entry with the current
 | |
|                 // node's pointer as the left pointer:
 | |
|                 if (up->down_pointer(i) == node->pointer())
 | |
|                     // Found it. This is the iterator's next value:
 | |
|                     return BTreeIterator(up, (int)i);
 | |
|             }
 | |
|             // We didn't find the m_current's pointer as a left node. So
 | |
|             // it must be the right node all the way at the end and we need
 | |
|             // to go one more level up:
 | |
|             node = up;
 | |
|         }
 | |
|         // We reached the root node and we're still at the end of the node.
 | |
|         // That means we're at the end of the btree.
 | |
|         return end();
 | |
|     }
 | |
| 
 | |
|     // If we're at the end of a non-leaf node, we need to follow the
 | |
|     // right pointer down until we find a leaf:
 | |
|     TreeNode* down;
 | |
|     for (down = node->down_node(node->size()); !down->is_leaf(); down = down->down_node(0))
 | |
|         ;
 | |
|     return BTreeIterator(down, 0);
 | |
| }
 | |
| 
 | |
| // FIXME Reverse iterating doesn't quite work; we don't recognize the
 | |
| // end (which is really the beginning) of the tree.
 | |
| BTreeIterator BTreeIterator::previous() const
 | |
| {
 | |
|     if (is_end()) {
 | |
|         return end();
 | |
|     }
 | |
| 
 | |
|     auto node = m_current;
 | |
|     auto ix = m_index;
 | |
|     if (ix > 0) {
 | |
|         if (node->is_leaf()) {
 | |
|             // We're in the middle of a leaf node. Previous entry is
 | |
|             // is the previous entry of the node:
 | |
|             return BTreeIterator(node, ix - 1);
 | |
|         } else {
 | |
|             /*
 | |
|              * We're in the middle of a non-leaf node. The iterator's
 | |
|              * previous value is all the way down to the left, last entry.
 | |
|              *
 | |
|              *                  |
 | |
|              *                  +--+--+--+--+
 | |
|              *                  |  |  |##|  |
 | |
|              *                  +--+--+--+--+
 | |
|              *                 /   |  |  |   \
 | |
|              *                        |
 | |
|              *               +--+--+--+--+
 | |
|              *               |  |  |  |  |
 | |
|              *               +--+--+--+--+
 | |
|              *                            \
 | |
|              *                 +--+--+--+--+
 | |
|              *                 |  |  |  |++|
 | |
|              *                 +--+--+--+--+
 | |
|              */
 | |
|             while (!node->is_leaf()) {
 | |
|                 node = node->down_node(ix);
 | |
|                 ix = (int)node->size();
 | |
|             }
 | |
|         }
 | |
|         VERIFY(node->is_leaf() && (ix <= (int)node->size()));
 | |
|         return BTreeIterator(node, ix);
 | |
|     }
 | |
| 
 | |
|     if (node->is_leaf()) {
 | |
|         // We currently at the first entry of a leaf node. We need to check one
 | |
|         // or more levels up until we end up in the "middle" of a node.
 | |
|         // If one level up we're still at the start of the node, we need
 | |
|         // to keep going up until we hit the root node. If we're at the
 | |
|         // start of the root node, we reached the start of the btree.
 | |
|         auto stash_current = node;
 | |
|         for (auto up = node->up(); up; up = node->up()) {
 | |
|             for (size_t i = up->size(); i > 0; i--) {
 | |
|                 // One level up, try to find the entry with the current
 | |
|                 // node's pointer as the right pointer:
 | |
|                 if (up->down_pointer(i) == node->pointer()) {
 | |
|                     // Found it. This is the iterator's next value:
 | |
|                     node = up;
 | |
|                     ix = (int)i - 1;
 | |
|                     return BTreeIterator(node, ix);
 | |
|                 }
 | |
|             }
 | |
|             // We didn't find the m_current's pointer as a right node. So
 | |
|             // it must be the left node all the way at the start and we need
 | |
|             // to go one more level up:
 | |
|             node = up;
 | |
|         }
 | |
|         // We reached the root node and we're still at the start of the node.
 | |
|         // That means we're at the start of the btree.
 | |
|         return BTreeIterator(stash_current, 0);
 | |
|     }
 | |
| 
 | |
|     // If we're at the start of a non-leaf node, we need to follow the
 | |
|     // left pointer down until we find a leaf:
 | |
|     TreeNode* down = node->down_node(0);
 | |
|     while (!down->is_leaf())
 | |
|         down = down->down_node(down->size());
 | |
|     return BTreeIterator(down, down->size() - 1);
 | |
| }
 | |
| 
 | |
| Key BTreeIterator::key() const
 | |
| {
 | |
|     if (is_end())
 | |
|         return {};
 | |
|     return (*m_current)[m_index];
 | |
| }
 | |
| 
 | |
| bool BTreeIterator::update(Key const& new_value)
 | |
| {
 | |
|     if (is_end())
 | |
|         return false;
 | |
|     if ((cmp(new_value) == 0) && (key().pointer() == new_value.pointer()))
 | |
|         return true;
 | |
|     auto previous_iter = previous();
 | |
|     auto next_iter = next();
 | |
|     if (!m_current->tree().duplicates_allowed() && ((previous_iter == new_value) || (next_iter == new_value))) {
 | |
|         return false;
 | |
|     }
 | |
|     if ((previous_iter > new_value) || (next_iter < new_value))
 | |
|         return false;
 | |
| 
 | |
|     // We are friend of BTree and TreeNode. Don't know how I feel about that.
 | |
|     m_current->m_entries[m_index] = new_value;
 | |
|     m_current->tree().serializer().serialize_and_write(*m_current);
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| BTreeIterator& BTreeIterator::operator=(BTreeIterator const& other)
 | |
| {
 | |
|     if (&other != this) {
 | |
|         m_current = other.m_current;
 | |
|         m_index = other.m_index;
 | |
|         m_where = other.m_where;
 | |
|     }
 | |
|     return *this;
 | |
| }
 | |
| 
 | |
| }
 |