Commits

Zenchreal committed 80867f6

Removed several functions from BytesMap::Reader. Find previous and find backwards now work. Selection now limited to valid bytes

Comments (0)

Files changed (5)

src/bytes/BytesMap.cpp

 	return (iter == bytesMap.map.begin()) && (offsetInIter == 0);
 }
 
-void BytesMap::Reader::forward(size_t n)
-{
-	using std::min;
-	
-	while (n > 0 && !end())
-	{
-		const size_t itemSize = iter->second->size();
-		
-		assert(itemSize >= offsetInIter);
-
-		const size_t read = min(itemSize - offsetInIter, n);
-		n -= read;
-		offsetInIter += read;
-
-		// Just to be absolutely clear -- this is obvious from above
-		assert(offsetInIter <= itemSize);
-
-		// Increment the iterator if we're at the end of the item
-		if (offsetInIter == itemSize)
-		{
-			iter++;
-			offsetInIter = 0;
-		}
-	}
-}
-
-void BytesMap::Reader::backward(size_t n)
-{
-	/*
-	while (n > 0 && !beginning())
-	{
-		const size_t itemSize = iter->second->size();
-		
-		assert(itemSize >= offsetInIter);
-
-		const size_t read = min(itemSize - offsetInIter, n);
-		byteBuffer += read;
-		n -= read;
-		offsetInIter += read;
-
-		// Just to be absolutely clear -- this is obvious from above
-		assert(offsetInIter <= itemSize);
-
-		// Increment the iterator if we're at the end of the item
-		if (offsetInIter == itemSize)
-		{
-			iter++;
-			offsetInIter = 0;
-		}
-	}
-	*/
-}
-
-uint8_t BytesMap::Reader::current() const
-{
-	if (end())
-	{
-		return 0xFF;
-	}
-	else
-	{
-		const size_t itemSize = iter->second->size();
-		const uint8_t* itemPtr = iter->second->ptr();
-		
-		assert(itemSize > offsetInIter);
-		
-		return itemPtr[offsetInIter];
-	}
-}
-
 size_t BytesMap::Reader::read(void* buffer, size_t size, bool* showAsModified)
 {
 	using std::min;
 	return total;
 }
 
-const void* BytesMap::Reader::read(size_t& size, size_t& offset, bool forward)
+BytesMap::ReversedReader::ReversedReader(const BytesMap& bytesMap):
+		Reader(bytesMap)
 {
-	if (forward)
+}
+
+bool BytesMap::ReversedReader::end() const
+{
+	return Reader::beginning();
+}
+
+bool BytesMap::ReversedReader::beginning() const
+{
+	return Reader::end();
+}
+
+size_t BytesMap::ReversedReader::read(void* buffer, size_t size, bool* showAsModified)
+{
+	using std::min;
+	using std::reverse_copy;
+	using std::fill;
+
+	assert(size >= 0);
+	
+	uint8_t* byteBuffer = (uint8_t*) buffer;
+	size_t total = 0;
+
+	// Loop while there's room left in the buffer and we have data
+	while (size > 0 && !end())
 	{
-		if (!end())
+		// Decrement the iterator before reading
+		if (offsetInIter <= 0)
 		{
-			const uint8_t* ptr = iter->second->ptr();
-			size = iter->second->size();
-			offset = offsetInIter;
-			
-			// Increment the iterator
-			iter++;
-			offsetInIter = 0;
-			return ptr;
+			// We can assume that this produces a valid item because !end() guarantees it
+			iter--;
+			offsetInIter = iter->second->size();
 		}
-		else
+
+		const size_t itemSize = iter->second->size(); // probably don't need
+		const uint8_t* itemPtr = iter->second->ptr();
+		
+		assert(itemSize >= offsetInIter);
+
+		// Copy data from the item to the buffer
+		const size_t read = min(offsetInIter, size);
+		const uint8_t* ptr = itemPtr + offsetInIter - read;
+		reverse_copy(ptr, ptr + read, byteBuffer);
+		
+		if (showAsModified != nullptr)
 		{
-			size = 0;
-			offset = 0;
-			return nullptr;
+			fill(showAsModified, showAsModified + read, iter->second->showAsModified());
 		}
+		
+		byteBuffer += read;
+		size -= read;
+		total += read;
+		offsetInIter -= read;
+
+		// Just to be absolutely clear -- this is obvious from above
+		assert(offsetInIter <= itemSize);
 	}
-	else
-	{
-		return nullptr;
-	}
-	return nullptr;
+	return total;
 }

src/bytes/BytesMap.hpp

 		 */
 		void seek(size_t offset);
 		size_t tell() const;
-		bool end() const;
-		bool beginning() const;
-		void forward(size_t n);
-		void backward(size_t n);
-		uint8_t current() const;
-		size_t read(void* buffer, size_t size, bool* showAsModified = nullptr);
-		const void* read(size_t& size, size_t& offset, bool forward = true);
+		virtual bool end() const;
+		virtual bool beginning() const;
+		virtual size_t read(void* buffer, size_t size, bool* showAsModified = nullptr);
 
 	protected:
 		const BytesMap& bytesMap;
 	
 	class ReversedReader : public Reader
 	{
+	public:
+		/**
+		 * Construct a plain reader with no options.
+		 */
+		ReversedReader(const BytesMap& bytesMap);
+		virtual bool end() const;
+		virtual bool beginning() const;
+		virtual size_t read(void* buffer, size_t size, bool* showAsModified = nullptr);
 	};
 };
 
 		if (offset + n < 0)
 		{
 			std::cout << "OOPS: TRIED TO SEEK PAST BEGINNING OF STREAM" << std::endl;
-			offset = 0;
+			offset = offset + n;
 			return;
 		}
 		
 		return buffer[offset];
 	}
 	
-	inline size_t absoluteOffset() const
-	{
-		if (!reader)
-			return 0;
-			
-		return reader->tell() - (bufferUsed - offset);
-	}
-	
 private:
 	BytesMap::Reader* reader;
 	

src/bytes/Document.cpp

 		
 	if (start >= size())
 		start = size();
+
+	// Reverse the pattern if needed
+	const uint8_t* pattern = b;
+	uint8_t* reversedPattern = nullptr;
+	if (!forward)
+	{
+		reversedPattern = new uint8_t[length];
+		std::reverse_copy(b, b + length, reversedPattern);
+		pattern = reversedPattern;
+	}
 	
-	BytesMap::Reader reader(bytesMap);
+	// Just create both readers and select the correct one
+	BytesMap::Reader forwardReader(bytesMap);
+	BytesMap::ReversedReader reversedReader(bytesMap);
+	BytesMap::Reader& reader = forward ? forwardReader : reversedReader;
+
+	// Seek to correct location
 	reader.seek(start);
-	
 	SequentialReader seq(&reader);
 	
-	std::cout << "-----" << std::endl;
-	std::cout << "running find..." << std::endl;
-	
-	size_t found = boyer_moore(seq, b, length);
+	size_t found = boyer_moore(seq, pattern, length);
 	
 	if (found == size_t(-1))
 	{
 	}
 	else
 	{
-		found += start;
+		if (forward)
+			found = start + found;
+		else
+			found = start - found - length;
+
 		std::cout << "found at: " << found << std::endl;
 	}
+
+	// Clean up the reversed pattern
+	delete[] reversedPattern;
+	reversedPattern = nullptr;
 		
 	return found;
 }

src/ui/HexEditorWidget.cpp

 		return;
 
 	if (totalBytes < 1)
+	{
 		clearSelection();
+		return;
+	}
 
-	selCaretPos = CaretPosition(max(sel.first, size_t(0)), LD);
-	caretPos = CaretPosition(min(sel.second, totalBytes - 1), RD);
+	selCaretPos = CaretPosition(min<size_t>(max<size_t>(sel.first, 0), totalBytes - 1), LD);
+	caretPos = CaretPosition(min<size_t>(max<size_t>(sel.second, 0), totalBytes - 1), RD);
 }
 
 void HexEditorWidget::clearSelection()
 	if (start > end)
 		return Selection(-1, -1);
 
-	// Sanity check -- shouldn't be needed but to be on the safe side
-	end = max<size_t>(end, 0);
-	start = min<size_t>(start, totalBytes);
+	// Sanity check -- don't allow the selection to go outside the hex
+	end = min<size_t>(max<size_t>(end, 0), totalBytes - 1);
+	start = min<size_t>(max<size_t>(start, 0), totalBytes - 1);
 
 	return Selection(start, end);
 }

src/ui/MainWindow.cpp

 			return;
 		}
 
-		size_t found = doc->find(editor->caretOffset(), (const uint8_t*) findPattern.constData(), findPattern.size());
+		size_t found = doc->find(editor->caretOffset(), (const uint8_t*) findPattern.constData(), findPattern.size(), !findBackwards);
 	
 		if (found != size_t(-1))
 		{
 		}
 		else
 		{
-			QMessageBox::information(this, tr("Find Downwards"), tr("No further instances of the string in this file."));
-			//QMessageBox::information(this, tr("Find Upwards"), tr("No preceding instances of the string in this file."));
+			if (findBackwards)
+				QMessageBox::information(this, tr("Find Upwards"), tr("No preceding instances of the string in this file."));
+			else
+				QMessageBox::information(this, tr("Find Downwards"), tr("No further instances of the string in this file."));
 		}
 	}
 }
 		nextOffset = editor->caretOffset();
 	}
 
-	size_t found = doc->find(nextOffset, (const uint8_t*) findPattern.constData(), findPattern.size());
+	size_t found = doc->find(nextOffset, (const uint8_t*) findPattern.constData(), findPattern.size(), true);
 	
 	if (found != size_t(-1))
 	{
 
 void MainWindow::findPrev()
 {
+	if (findPattern.size() < 1)
+	{
+		//statusMessage(tr("empty string"));
+		return;
+	}
+
+	size_t nextOffset;
+	if (editor->hasSelection())
+	{
+		nextOffset = editor->selectionOffset();
+	}
+	else
+	{
+		nextOffset = editor->caretOffset();
+	}
+
+	size_t found = doc->find(nextOffset, (const uint8_t*) findPattern.constData(), findPattern.size(), false);
+	
+	if (found != size_t(-1))
+	{
+		// This is somewhat a hack: if we don't set the caret position, the screen
+		// won't scroll down/up. A more elegent way to do this might be to add
+		// a new function to set the caret/selection and scroll the window. Then
+		// we could center the selection on the screen or do something else.
+		editor->setCaretOffset(found + findPattern.size());
+		editor->setCaretOffset(found);
+
+		editor->setSelection(HexEditorWidget::Selection(found + findPattern.size() - 1, found));
+		
+		updatePosAndSel();
+		editor->viewport()->update();
+	}
+	else
+	{
+		QMessageBox::information(this, tr("Find Upwards"), tr("No preceding instances of the string in this file."));
+	}
 }
 
 void MainWindow::goto_()