Overview
TheGapBuffer is a specialized data structure optimized for efficient text editing operations. It maintains an internal “gap” that can be moved around, making insertions and deletions in localized regions very efficient. This data structure is famously used by editors like Emacs.
Source: include/zep/gap_buffer.h:52
How Gap Buffers Work
A gap buffer appears as contiguous memory to the client, but internally contains a “gap” - an empty space that can be moved around the buffer. When you insert or delete text:- The gap is moved to the insertion/deletion point
- Insertions consume gap space (shrinking the gap)
- Deletions expand the gap
- When the gap becomes too small, the buffer is reallocated with a larger gap
Template Declaration
T- The value type stored in the buffer (typicallycharoruint8_tfor text)A- The allocator type (defaults tostd::allocator<T>)
Key Members
Internal Pointers
include/zep/gap_buffer.h:64-67
Constants
include/zep/gap_buffer.h:55
Core Methods
Size and Capacity
size()
include/zep/gap_buffer.h:178
empty()
true if the buffer contains no elements.
Source: include/zep/gap_buffer.h:184
Insertion Operations
insert()
pt- The position to insert atsrcStart- Beginning of the source rangesrcEnd- End of the source range
include/zep/gap_buffer.h:395
push_back()
include/zep/gap_buffer.h:483-494
push_front()
include/zep/gap_buffer.h:467-481
Deletion Operations
erase()
include/zep/gap_buffer.h:417-441
pop_back() / pop_front()
include/zep/gap_buffer.h:497-509
Access Operations
operator[]
include/zep/gap_buffer.h:511-521
at()
include/zep/gap_buffer.h:523-532
front() / back()
include/zep/gap_buffer.h:443-465
Buffer Management
clear()
include/zep/gap_buffer.h:211
resize()
include/zep/gap_buffer.h:224
assign()
include/zep/gap_buffer.h:343
Iterators
TheGapBuffer provides STL-compatible iterators that automatically skip over the gap:
include/zep/gap_buffer.h:167-172
Iterator Features
- Random access: Full support for
operator+,operator-, comparisons - Gap-aware: Automatically skips the gap when traversing
- Position-based: Iterator position is measured in logical characters, not buffer offsets
include/zep/gap_buffer.h:72-117
Performance Characteristics
Time Complexity
| Operation | Complexity | Notes |
|---|---|---|
| Insert at gap | O(1) | Amortized, may trigger gap resize |
| Insert elsewhere | O(n) | Requires moving the gap |
| Delete at gap | O(1) | |
| Delete elsewhere | O(n) | Requires moving the gap |
| Random access | O(1) | With simple gap check |
| Sequential access | O(1) per element | Via iterators |
Space Complexity
- Memory overhead: Default gap of 1000 elements
- Growth strategy: Gap grows by
m_defaultGapwhen space is needed - Shrinking: Buffer never shrinks automatically; gap expands instead
Optimal Use Cases
Best for:- Text editors where edits are localized (typing at cursor)
- Sequential insert/delete operations in the same region
- Scenarios where insertion/deletion is more common than random access
- Random insertions/deletions across the entire buffer
- Very small buffers where gap overhead is significant
- Applications requiring frequent full-buffer copies
Search Operations
The gap buffer provides optimized search operations that handle the gap efficiently:find_first_of()
include/zep/gap_buffer.h:629
find_first_not_of()
include/zep/gap_buffer.h:643
Example Usage
Design Notes
- The gap buffer implementation is copy-disabled (
deletecopy constructor/assignment) - Debug builds fill the gap with
@characters to aid debugging - The buffer uses
memmovefor efficient memory operations - Iterators remain valid after operations unless they point to erased elements
