@phroun/paged-buffer
Version:
High-performance buffer system for editing massive files with intelligent memory management and undo/redo capabilities
177 lines • 6.29 kB
JavaScript
"use strict";
/**
* Enhanced Page metadata with simplified line tracking (marks moved to global system)
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MarkInfo = exports.LineInfo = exports.PageInfo = void 0;
const crypto = __importStar(require("crypto"));
/**
* Enhanced Page metadata with simplified line tracking and no marks management
* (Marks are now handled globally by the page coordinate system)
*/
class PageInfo {
constructor(pageKey, fileOffset, originalSize, checksum = null) {
// Runtime state
this.isDirty = false; // Has been modified
this.isLoaded = false; // Currently in memory
this.isDetached = false; // Conflicts with source file
this.data = null; // In-memory data buffer
// Simplified line tracking - just store newline positions
this.newlinePositions = []; // Array of relative positions of \n characters
this.linesCacheValid = false; // Whether newline positions are up to date
this.pageKey = pageKey;
this.fileOffset = fileOffset;
this.originalSize = originalSize;
this.checksum = checksum;
this.currentSize = originalSize;
this.lastAccess = Date.now();
}
/**
* Calculate fast checksum for change detection
*/
static calculateChecksum(data) {
return crypto.createHash('md5').update(data).digest('hex');
}
/**
* Update page with new data and invalidate caches as needed
*/
updateData(data) {
this.data = data;
this.currentSize = data.length;
this.isDirty = true;
this.isLoaded = true;
this.lastAccess = Date.now();
// Invalidate caches when data changes
this.linesCacheValid = false;
// Rebuild line information immediately for loaded pages
this._rebuildLineCache(data);
}
/**
* Rebuild the newline positions cache
*/
_rebuildLineCache(data) {
this.newlinePositions = [];
// Single pass through data to find all newlines
for (let i = 0; i < data.length; i++) {
if (data[i] === 0x0A) { // \n
this.newlinePositions.push(i);
}
}
this.linesCacheValid = true;
}
/**
* Ensure line cache is valid and up to date
*/
ensureLineCacheValid() {
if (!this.linesCacheValid && this.isLoaded && this.data) {
this._rebuildLineCache(this.data);
}
}
/**
* Get the number of newlines in this page
*/
getNewlineCount() {
this.ensureLineCacheValid();
return this.newlinePositions.length;
}
/**
* Get global line starts contributed by this page
*/
getGlobalLineStarts(pageVirtualStart) {
this.ensureLineCacheValid();
const starts = [];
// Each newline creates a line start at position + 1
for (const nlPos of this.newlinePositions) {
const globalLineStart = pageVirtualStart + nlPos + 1;
starts.push(globalLineStart);
}
return starts;
}
/**
* Update line cache after a modification within this page
*/
updateAfterModification(_offset, _deletedBytes, _insertedData) {
// Invalidate cache - we'll rebuild on next access
this.linesCacheValid = false;
}
/**
* Verify page integrity against original file
*/
verifyIntegrity(originalData) {
if (!this.checksum)
return false;
const currentChecksum = PageInfo.calculateChecksum(originalData);
return currentChecksum === this.checksum;
}
/**
* Get memory usage statistics for this page
*/
getMemoryStats() {
let memoryUsed = 0;
if (this.data) {
memoryUsed += this.data.length;
}
// Newline positions memory (much smaller than before)
memoryUsed += this.newlinePositions.length * 4; // 4 bytes per position
return {
dataSize: this.data ? this.data.length : 0,
newlineCount: this.newlinePositions.length,
newlinePositionsSize: this.newlinePositions.length,
marksCount: 0, // No marks stored here anymore
estimatedMemoryUsed: memoryUsed,
isLoaded: this.isLoaded,
isDirty: this.isDirty,
linesCacheValid: this.linesCacheValid,
marksValid: true // Always valid since no marks
};
}
}
exports.PageInfo = PageInfo;
// Backwards compatibility exports
class LineInfo {
constructor(startOffset, length, endsWithNewline = false) {
this.startOffset = startOffset;
this.length = length;
this.endsWithNewline = endsWithNewline;
}
get endOffset() {
return this.startOffset + this.length;
}
get contentLength() {
return this.endsWithNewline ? this.length - 1 : this.length;
}
}
exports.LineInfo = LineInfo;
// Legacy class kept for compatibility but no longer used
class MarkInfo {
constructor(name, pageOffset, virtualAddress) {
this.name = name;
this.pageOffset = pageOffset;
this.virtualAddress = virtualAddress;
}
}
exports.MarkInfo = MarkInfo;
//# sourceMappingURL=page-info.js.map