38 lines
1.7 KiB
Text
38 lines
1.7 KiB
Text
# write.ludic - a write that is known to be on disk: the old file to the backup first (only when it
|
|
# is whole - a torn file must never replace a good backup), then the new text, read straight back
|
|
# and compared, because a caller about to delete something on the strength of it needs to know
|
|
export function save_write(path: string, backup: string, text: string) -> bool {
|
|
let old = Fs.read_text(path)
|
|
if old != null and len(backup) > 0 and save_text_intact(old) { Fs.write_text(backup, old) }
|
|
Fs.write_text(path, text)
|
|
let back = Fs.read_text(path)
|
|
return back != null and back == text
|
|
}
|
|
|
|
# a SaveRead that must not be written over says so; a write through it refuses
|
|
export function save_write_to(r: SaveRead, path: string, backup: string, text: string) -> bool {
|
|
if r != null and r.readonly { return false }
|
|
return save_write(path, backup, text)
|
|
}
|
|
|
|
# save_write for a tree: the same backup, then Json.write_file (the runtime's kept buffer, .tmp and
|
|
# rename), so a game that saves often holds nothing more for it. Read back whole, as a save is read
|
|
export function save_write_tree(path: string, backup: string, v: Val) -> bool {
|
|
if len(backup) > 0 and save_file_intact(path) { Fs.copy(path, backup) }
|
|
if not Json.write_file(v, path) { return false }
|
|
return save_file_intact(path)
|
|
}
|
|
|
|
export function save_write_tree_to(r: SaveRead, path: string, backup: string, v: Val) -> bool {
|
|
if r != null and r.readonly { return false }
|
|
return save_write_tree(path, backup, v)
|
|
}
|
|
|
|
# whether the file on disk is a whole one; the text read to tell is given back
|
|
export function save_file_intact(path: string) -> bool {
|
|
let s = Fs.read_text(path)
|
|
if s == null { return false }
|
|
let whole = save_text_intact(s)
|
|
unsafe { free(s) }
|
|
return whole
|
|
}
|