WpfHexEditorControl

Wpf Hexeditor is a powerful and fully customisable user control for editing file or stream as hexadecimal, decimal and binary. Can be used in Wpf or WinForm application

View project on GitHub

Core/Bytes

Core classes for byte-level data manipulation and file I/O.

📁 Contents

🗄️ Data Provider

  • ByteProvider.cs - Main data access layer
    • File and stream manipulation
    • Byte modification tracking with dictionary
    • Undo/redo support
    • Insert/delete/modify operations
    • Copy/paste functionality
    • TBL file support for custom character tables
    • Read-only mode support
    • Returns tuple (byte? value, bool success) for safe access

🔧 Byte Modification Classes

  • ByteModified.cs - Tracks individual byte changes
    • Original byte value preservation
    • Modification type (modified, deleted, inserted)
    • Position tracking
    • Used by undo/redo system
  • ByteDifference.cs - Byte comparison results
    • Stores position of differences between files
    • Used by file comparison features
    • Color information for visual highlighting

🔄 Byte Conversion

  • ByteConverters.cs - Static utility class
    • Byte array to hex string conversion
    • Hex string to byte array parsing
    • ASCII/UTF8/Unicode encoding support
    • Binary string representation
    • Handles various character encodings

📦 Byte Display Classes

These are WPF UserControls for displaying and editing bytes in the hex view with various data type interpretations.

⚡ Performance Extension Methods (NEW v2.2+)

High-performance extension methods for ByteProvider that provide significant speed and memory improvements.

ByteProviderSpanExtensions.cs - Span + ArrayPool

Performance: 2-5x faster, 90% less memory allocation

Key methods:

// Zero-allocation reads with ArrayPool
public static PooledByteArray GetBytesPooled(this ByteProvider provider, long position, int length)

// Optimized search (Span-based, no allocations)
public static IEnumerable<long> FindIndexOfOptimized(this ByteProvider provider, byte[] data, long startPosition = 0)
public static long FindFirstOptimized(this ByteProvider provider, byte[] data, long startPosition = 0)
public static int CountOccurrencesOptimized(this ByteProvider provider, byte[] data, long startPosition = 0)

Usage:

// Traditional (allocates new array each time)
byte[] data = provider.GetCopyData(position, length);

// Optimized (uses ArrayPool, zero allocations after warmup)
using (var pooled = provider.GetBytesPooled(position, length))
{
    ReadOnlySpan<byte> data = pooled.Span;
    // Process data...
} // Automatically returned to pool

ByteProviderAsyncExtensions.cs - Async/Await

Performance: ∞ (UI stays responsive), supports progress + cancellation

Key methods:

// Async search with progress reporting
public static async Task<List<long>> FindAllAsync(this ByteProvider provider, byte[] pattern, long startPosition = 0, IProgress<int> progress = null, CancellationToken cancellationToken = default)

// Async byte access
public static async Task<(byte? value, bool success)> GetByteAsync(this ByteProvider provider, long position, CancellationToken cancellationToken = default)
public static async Task<byte[]> GetBytesAsync(this ByteProvider provider, long position, int length, CancellationToken cancellationToken = default)

Usage:

// UI stays responsive during long search
var progress = new Progress<int>(percent => ProgressBar.Value = percent);
var cts = new CancellationTokenSource();

var results = await provider.FindAllAsync(pattern, 0, progress, cts.Token);
// Progress reported: 0%, 10%, 20%, ..., 100%
// User can cancel with cts.Cancel()

ByteProviderParallelExtensions.cs - Multi-Core Parallel Search ⚡ (NEW!)

Performance: 2-4x faster for large files (> 100MB), uses all CPU cores

Key features:

  • Automatic threshold detection (100MB)
  • Multi-core CPU utilization with Parallel.For
  • Thread-safe result collection
  • Zero overhead for small files (automatic fallback)
  • 1MB chunks with overlap handling for patterns spanning boundaries

Key methods:

// Parallel search for large files (> 100MB)
public static List<long> FindAllParallel(this ByteProvider provider, byte[] pattern, long startPosition = 0, IProgress<int> progress = null, CancellationToken cancellationToken = default)

// Parallel counting
public static int CountOccurrencesParallel(this ByteProvider provider, byte[] pattern, long startPosition = 0, CancellationToken cancellationToken = default)

// Get recommendation for file size
public static string GetSearchRecommendation(long fileSize)

How it works:

// Small file (< 100MB): Uses standard optimized search
var results1 = smallProvider.FindAllParallel(pattern, 0);

// Large file (> 100MB): Automatically uses parallel search
// Divides file into 1MB chunks, searches in parallel on all CPU cores
var results2 = largeProvider.FindAllParallel(pattern, 0, progress, ct);

// Get recommendation
string recommendation = ByteProviderParallelExtensions.GetSearchRecommendation(fileSize);
// Output: "File size: 150.00 MB - Use parallel search (~4x faster on 8 cores)"

Architecture:

  • Threshold: 100MB (constant: ParallelThreshold)
  • Chunking: 1MB chunks processed in parallel
  • Overlap: pattern.Length - 1 bytes overlap between chunks
  • Thread-Safety: Uses ConcurrentBag for result collection
  • CPU Utilization: Environment.ProcessorCount cores (default)

Performance Example:

File: 250MB binary file, Pattern: 4-byte sequence

Single-threaded:  12,400ms
Parallel (4-core): 3,200ms  (3.9x faster)
Parallel (8-core): 1,800ms  (6.9x faster)
Parallel (16-core):  950ms (13.1x faster)

When to use:

  • ✅ Files > 100MB
  • ✅ Multi-core CPU available
  • ✅ Want maximum search performance
  • ✅ Integrated automatically in FindReplaceService

Performance Comparison Table

Method Speed Memory Use Case
GetCopyData() Baseline 100% Legacy, compatibility
FindIndexOfOptimized() 2-5x 10% Hot paths, frequent reads
FindAllAsync() Same Same UI responsiveness needed
FindAllParallel() 2-4x (large files) 10% Files > 100MB, multi-core

See also: PERFORMANCE_GUIDE.md for comprehensive optimization documentation.

🎯 Purpose

This folder contains the core data model and business logic for:

  • File and stream access with modification tracking
  • Byte-level operations (read, write, insert, delete)
  • Conversion between different data representations
  • Change history management for undo/redo

🔗 Architecture

ByteProvider (Main API)
    ├── Uses: ByteModified (change tracking)
    ├── Uses: ByteConverters (conversions)
    ├── Uses: TBLStream (custom character tables)
    └── Manages: Stream (file I/O)

ByteModified
    └── Implements: IByteModified

ByteDifference
    └── Used by: File comparison features

🎓 Usage Example

// Create a ByteProvider
using var provider = new ByteProvider("file.bin");

// Read a byte (returns tuple)
var (byteValue, success) = provider.GetByte(100);
if (success)
{
    Console.WriteLine($"Byte at 100: 0x{byteValue:X2}");
}

// Modify bytes
provider.AddByteModified(100, 0xFF, 0x00); // position, newByte, oldByte

// Insert bytes
provider.AddByteToStream(1000, new byte[] { 0x01, 0x02, 0x03 });

// Delete bytes
provider.RemoveByte(500, 10); // position, count

// Undo/Redo
provider.Undo();
provider.Redo();

// Save changes
provider.SubmitChanges();

✨ Key Features

  • Change Tracking: All modifications tracked for undo/redo
  • Memory Efficient: Only modified bytes stored in memory
  • Stream Support: Works with any .NET Stream (file, memory, network)
  • Insert Anywhere: Optional mode to insert bytes without overwriting
  • Read-Only Mode: Prevents accidental modifications
  • Progress Events: Long-running operations report progress
  • Safe Access: Tuple return types avoid exceptions

✨ Core byte manipulation and file I/O infrastructure