mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 14:02:46 +00:00 
			
		
		
		
	AK: Add Bitmap::count_in_range and Bitmap::fill_range
This commit is contained in:
		
							parent
							
								
									cd2815ed87
								
							
						
					
					
						commit
						efac3d27d2
					
				
					 2 changed files with 161 additions and 0 deletions
				
			
		
							
								
								
									
										98
									
								
								AK/Bitmap.h
									
										
									
									
									
								
							
							
						
						
									
										98
									
								
								AK/Bitmap.h
									
										
									
									
									
								
							|  | @ -103,6 +103,57 @@ public: | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     size_t count_slow(bool value) const | ||||
|     { | ||||
|         return count_in_range(0, m_size, value); | ||||
|     } | ||||
| 
 | ||||
|     size_t count_in_range(size_t start, size_t len, bool value) const | ||||
|     { | ||||
|         ASSERT(start < m_size); | ||||
|         ASSERT(start + len <= m_size); | ||||
|         if (len == 0) | ||||
|             return 0; | ||||
| 
 | ||||
|         static const u8 bitmask_first_byte[8] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 }; | ||||
|         static const u8 bitmask_last_byte[8] = { 0x0, 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F }; | ||||
| 
 | ||||
|         size_t count; | ||||
|         const u8* first = &m_data[start / 8]; | ||||
|         const u8* last = &m_data[(start + len) / 8]; | ||||
|         u8 byte = *first; | ||||
|         byte &= bitmask_first_byte[start % 8]; | ||||
|         if (first == last) { | ||||
|             byte &= bitmask_last_byte[(start + len) % 8]; | ||||
|             count = __builtin_popcount(byte); | ||||
|         } else { | ||||
|             count = __builtin_popcount(byte); | ||||
|             byte = *last; | ||||
|             byte &= bitmask_last_byte[(start + len) % 8]; | ||||
|             count += __builtin_popcount(byte); | ||||
|             if (++first < last) { | ||||
|                 const u32* ptr32 = (const u32*)(((FlatPtr)first + sizeof(u32) - 1) & ~(sizeof(u32) - 1)); | ||||
|                 if ((const u8*)ptr32 > last) | ||||
|                     ptr32 = (const u32*)last; | ||||
|                 while (first < (const u8*)ptr32) { | ||||
|                     count += __builtin_popcount(*first); | ||||
|                     first++; | ||||
|                 } | ||||
|                 const u32* last32 = (const u32*)((FlatPtr)last & ~(sizeof(u32) - 1)); | ||||
|                 while (ptr32 < last32) { | ||||
|                     count += __builtin_popcountl(*ptr32); | ||||
|                     ptr32++; | ||||
|                 } | ||||
|                 for (first = (const u8*)ptr32; first < last; first++) | ||||
|                     count += __builtin_popcount(*first); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (!value) | ||||
|             count = len - count; | ||||
|         return count; | ||||
|     } | ||||
| 
 | ||||
|     u8* data() { return m_data; } | ||||
|     const u8* data() const { return m_data; } | ||||
| 
 | ||||
|  | @ -127,6 +178,53 @@ public: | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     template<bool VALUE> | ||||
|     void fill_range(size_t start, size_t len) | ||||
|     { | ||||
|         ASSERT(start < m_size); | ||||
|         ASSERT(start + len <= m_size); | ||||
|         if (len == 0) | ||||
|             return; | ||||
| 
 | ||||
|         static const u8 bitmask_first_byte[8] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 }; | ||||
|         static const u8 bitmask_last_byte[8] = { 0x0, 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F }; | ||||
| 
 | ||||
|         u8* first = &m_data[start / 8]; | ||||
|         u8* last = &m_data[(start + len) / 8]; | ||||
|         u8 byte_mask = bitmask_first_byte[start % 8]; | ||||
|         if (first == last) { | ||||
|             byte_mask &= bitmask_last_byte[(start + len) % 8]; | ||||
|             if constexpr (VALUE) | ||||
|                 *first |= byte_mask; | ||||
|             else | ||||
|                 *first &= ~byte_mask; | ||||
|         } else { | ||||
|             if constexpr (VALUE) | ||||
|                 *first |= byte_mask; | ||||
|             else | ||||
|                 *first &= ~byte_mask; | ||||
|             byte_mask = bitmask_last_byte[(start + len) % 8]; | ||||
|             if constexpr (VALUE) | ||||
|                 *last |= byte_mask; | ||||
|             else | ||||
|                 *last &= ~byte_mask; | ||||
|             if (++first < last) { | ||||
|                 if constexpr (VALUE) | ||||
|                     __builtin_memset(first, 0xFF, last - first); | ||||
|                 else | ||||
|                     __builtin_memset(first, 0x0, last - first); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void fill_range(size_t start, size_t len, bool value) | ||||
|     { | ||||
|         if (value) | ||||
|             fill_range<true>(start, len); | ||||
|         else | ||||
|             fill_range<false>(start, len); | ||||
|     } | ||||
| 
 | ||||
|     void fill(bool value) | ||||
|     { | ||||
|         __builtin_memset(m_data, value ? 0xff : 0x00, size_in_bytes()); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Tom
						Tom