UNPKG

totjs

Version:

Markup-like Database without Indexing

126 lines (116 loc) 3.98 kB
import fs from 'fs'; import { printError } from './printError.js'; import { DefaultStreamCount, DefaultNameMaximum, DefaultStreamMinimum } from './const.js'; export async function getDataByNameAt(filename, name, position = 0, encoding = 'utf8', streamCount = DefaultStreamCount) { try { if (!name) { printError('Name may not be appropriate'); return ''; } if (name.includes('<d:') || name.includes('</d:')) { printError("Name cannot contain '<d:' or '</d:'"); return ''; } if (name.length > DefaultNameMaximum) { printError(`Name cannot be longer than ${ DefaultNameMaximum } characters`); return ''; } if (streamCount < DefaultStreamMinimum) { printError(`Stream count cannot be smaller than ${ DefaultStreamMinimum }`); return ''; } if (position < 0) { printError('Position cannot be smaller than 0'); return ''; } const result = await processGetDataByNameAt(filename, name, position, encoding, streamCount); return result; } catch (error) { printError(error.toString()); return ''; } } async function processGetDataByNameAt(filename, name, position, encoding, streamCount) { return new Promise((resolve, reject) => { const tagStart = `<d:${ name }>`; const tagEnd = `</d:${ name }>`; let inTag = false; let tagEnded = false; let data = ''; let previousChunk = ''; const readStream = fs.createReadStream(filename, { encoding, highWaterMark: streamCount, start: position, }); readStream.on('data', (chunk) => { let processingChunk = previousChunk + chunk; previousChunk = ''; while (processingChunk.length > 0) { if (!inTag) { const indexStart = processingChunk.indexOf(tagStart); if (indexStart > -1) { inTag = true; processingChunk = processingChunk.slice(indexStart + tagStart.length); } else { previousChunk = processingChunk.slice(-tagStart.length); break; } } else { const indexEnd = processingChunk.indexOf(tagEnd); if (indexEnd > -1) { inTag = false; tagEnded = true; data += processingChunk.slice(0, indexEnd); processingChunk = ''; data = data.trim(); resolve(data); readStream.close(); return; } else { data += processingChunk.slice(0, -tagEnd.length); previousChunk = processingChunk.slice(-tagEnd.length); break; } } } }); readStream.on('end', () => { if (!tagEnded) { if (inTag) { printError(`No closing tag '</d:${ name }>' found for '<d:${ name }>'`); } else { printError(`Tag '<d:${ name }>' not found in file`); } } resolve(''); }); readStream.on('error', (error) => { printError(error.toString()); reject(''); }); }); }