From 5c91e694008d48170790adae91deb689f149c2bd Mon Sep 17 00:00:00 2001 From: Nick Downing Date: Tue, 4 Jan 2022 19:28:58 +1100 Subject: [PATCH] Put methods into a class called logjson.File --- a.mjs | 7 +- b.mjs | 6 +- logjson.mjs | 246 ++++++++++++++++++++++++++++++---------------------- 3 files changed, 152 insertions(+), 107 deletions(-) diff --git a/a.mjs b/a.mjs index 8cc3797..d84e952 100755 --- a/a.mjs +++ b/a.mjs @@ -3,7 +3,10 @@ import logjson from './logjson.mjs' import fsPromises from 'fs/promises' -let {log, eof, value} = await logjson.open_log( - 'a.logjson', +let file = new logjson.File() +await file.open( + 'a.logjson', JSON.parse(await fsPromises.readFile('random.json', 'utf-8')) ) +console.log('file.value', file.value) +await file.close() diff --git a/b.mjs b/b.mjs index ef146d2..7e89a37 100755 --- a/b.mjs +++ b/b.mjs @@ -3,5 +3,7 @@ import logjson from './logjson.mjs' import fsPromises from 'fs/promises' -let {log, eof, value} = await logjson.open_log('a.logjson', {}) -console.log('value', value) +let file = new logjson.File() +await file.open('a.logjson', {}) +console.log('file.value', file.value) +await file.close() diff --git a/logjson.mjs b/logjson.mjs index a2c3934..9c8c296 100644 --- a/logjson.mjs +++ b/logjson.mjs @@ -3,131 +3,171 @@ import fsPromises from 'fs/promises' let open_angle = Buffer.from('\n<', 'utf-8') let close_angle = Buffer.from('>\n', 'utf-8') -let find_root = async (log, eof) => { - let ptr = eof & ~0xfff - let count = eof & 0xfff - let buffer = Buffer.alloc(0x1001) - assert((await log.read(buffer, 0, count, ptr)).bytesRead === count) - while (true) { - let i = count - if (i && (i = buffer.lastIndexOf(close_angle, i - 2)) != -1) { - let end = i + ptr - while (true) { - if (i && (i = buffer.lastIndexOf(open_angle, i - 2)) != -1) { - let start = i + ptr + 2 - return {ptr: start, len: end - start} - } +class File { + constructor() { + this.log = null + this.eof = 0 + this.value = null + } - if (ptr == 0) - break - ptr -= 0x1000 - buffer[0x1000] = buffer[0] - assert((await log.read(buffer, 0, 0x1000, ptr)).bytesRead === 0x1000) - count = 0x1001 - } + async open(path, default_value) { + assert(this.log === null) - // special case for < at start of file - if (count && buffer[0] === 0x3c) { - let start = 1 - return {ptr: start, len: end - start} - } + try { + this.log = await fsPromises.open(path, 'r+') + } + catch (error) { + if (error.code !== 'ENOENT') + throw error - throw new Error('can\'t find logjson start marker') + this.log = await fsPromises.open(path, 'w+') + this.eof = 0 + + await this.write(default_value, true) + this.value = default_value + return } - if (ptr == 0) - break - ptr -= 0x1000 - buffer[0x1000] = buffer[0] - assert((await log.read(buffer, 0, 0x1000, ptr)).bytesRead === 0x1000) - count = 0x1001 - } while (ptr >= 0) - throw new Error('can\'t find logjson end marker') -} + this.eof = (await this.log.stat()).size + let {ptr, len} = await this.find_root() + this.value = await this.read(ptr, len) -let open_log = async (path, default_value) => { - let log - try { - log = await fsPromises.open(path, 'r+') + this.eof = ptr + len + 2 + await this.log.truncate(this.eof) } - catch (error) { - if (error.code !== 'ENOENT') - throw error - log = await fsPromises.open(path, 'w+') - let {eof} = await write_log(log, 0, default_value, true) - return {log, eof, value: default_value} + + async close() { + assert(this.log !== null) + + await this.log.close() + this.log = null } - let eof = (await log.stat()).size - let {ptr, len} = await find_root(log, eof) - let value = await read_log(log, ptr, len) + async find_root() { + let ptr = this.eof & ~0xfff + let count = this.eof & 0xfff + let buffer = Buffer.alloc(0x1001) + assert( + (await this.log.read(buffer, 0, count, ptr)).bytesRead === count + ) + while (true) { + let i = count + if (i && (i = buffer.lastIndexOf(close_angle, i - 2)) != -1) { + let end = i + ptr + while (true) { + if (i && (i = buffer.lastIndexOf(open_angle, i - 2)) != -1) { + let start = i + ptr + 2 + return {ptr: start, len: end - start} + } - eof = ptr + len + 2 - await log.truncate(eof) + if (ptr == 0) + break + ptr -= 0x1000 + if (count) { + buffer[0x1000] = buffer[0] + count = 0x1001 + } + else + count = 0x1000 + assert( + (await this.log.read(buffer, 0, 0x1000, ptr)).bytesRead === 0x1000 + ) + } - return {log, eof, value} -} + // special case for < at start of file + if (count && buffer[0] === 0x3c) { + let start = 1 + return {ptr: start, len: end - start} + } -let read_log = async (log, ptr, len) => { - let buffer = Buffer.alloc(len) - assert((await log.read(buffer, 0, len, ptr)).bytesRead === len) - let value = JSON.parse(buffer.toString('utf-8')) - if (typeof value === 'object' && value !== null) - if (value instanceof Array) { - for (let i = 0; i < value.length; ++i) { - let item = value[i] - if (item instanceof Array) - value[i] = await read_log(log, item[0], item[1]) + throw new Error('can\'t find logjson start marker') } + + if (ptr == 0) + break + ptr -= 0x1000 + if (count) { + buffer[0x1000] = buffer[0] + count = 0x1001 + } + else + count = 0x1000 + assert( + (await this.log.read(buffer, 0, 0x1000, ptr)).bytesRead === 0x1000 + ) } - else - for (let i in value) { - let item = value[i] - if (item instanceof Array) - value[i] = await read_log(log, item[0], item[1]) + + throw new Error('can\'t find logjson end marker') + } + + async read(ptr, len) { + let buffer = Buffer.alloc(len) + assert((await this.log.read(buffer, 0, len, ptr)).bytesRead === len) + let value = JSON.parse(buffer.toString('utf-8')) + if (typeof value === 'object' && value !== null) + if (value instanceof Array) { + for (let i = 0; i < value.length; ++i) { + let item = value[i] + if (item instanceof Array) + value[i] = await this.read(item[0], item[1]) + } } - return value -} + else + for (let i in value) { + let item = value[i] + if (item instanceof Array) + value[i] = await this.read(item[0], item[1]) + } + return value + } -let write_log = async (log, eof, value, is_root) => { - if (typeof value === 'object' && value !== null) - if (value instanceof Array) { - let value1 = [] - for (let i = 0; i < value.length; ++i) { - let item = value[i] - if (typeof item === 'object' && item !== null) { - let {ptr, len, eof: eof1} = await write_log(log, eof, item, false) - item = [ptr, len] - eof = eof1 + async write(value, is_root) { + if (typeof value === 'object' && value !== null) + if (value instanceof Array) { + let value1 = [] + for (let i = 0; i < value.length; ++i) { + let item = value[i] + if (typeof item === 'object' && item !== null) { + let {ptr, len} = await this.write(item, false) + item = [ptr, len] + } + value1.push(item) } - value1.push(item) + value = value1 } - value = value1 - } - else { - let value1 = {} - for (let i in value) { - let item = value[i] - if (typeof item === 'object' && item !== null) { - let {ptr, len, eof: eof1} = await write_log(log, eof, item, false) - item = [ptr, len] - eof = eof1 + else { + let value1 = {} + for (let i in value) { + let item = value[i] + if (typeof item === 'object' && item !== null) { + let {ptr, len} = await this.write(item, false) + item = [ptr, len] + } + value1[i] = item } - value1[i] = item + value = value1 } - value = value1 + + let data = JSON.stringify(value, null, 2) + if (is_root) { + let buffer = Buffer.from(`<${data}>\n`) + let len = buffer.length + assert( + (await this.log.write(buffer, 0, len, this.eof)).bytesWritten === len + ) + let ptr = this.eof + 1 + this.eof += len + return {ptr, len: len - 2} } - let data = JSON.stringify(value, null, 2) - if (is_root) { - let buffer = Buffer.from(`<${data}>\n`) + let buffer = Buffer.from(`${data}\n`) let len = buffer.length - assert((await log.write(buffer, 0, len, eof)).bytesWritten === len) - return {ptr: eof + 1, len: len - 2, eof: eof + len} + assert( + (await this.log.write(buffer, 0, len, this.eof)).bytesWritten === len + ) + let ptr = this.eof + this.eof += len + return {ptr, len: len - 1} } - let buffer = Buffer.from(`${data}\n`) - let len = buffer.length - assert((await log.write(buffer, 0, len, eof)).bytesWritten === len) - return {ptr: eof, len: len - 1, eof: eof + len} } -export default {open_log, read_log, write_log} +export default {File} -- 2.34.1