fileseek.xyw

fileseek.xyw
calendarsave
.include "lib/macros.xyw"

; Report any unexpected error and halt
unexpected_error system._on_error STW

; Write "0123456789" to seek_file.txt
seek_file_s file._path_s STW
digits_s file._buffer STW
$000A file.length_w STW
file.op.write file.operation STB

; Explicit FILE_OP_SEEK, for re-applying an already-set offset
; (e.g. right before a read) without another register write
seek_file_s file._path_s STW
$0008 file.offset STW
file.op.seek file.operation STB
buf0 file._buffer STW
$0002 file.length_w STW
file.op.read file.operation STB
buf0 puts JSRw
NL

; Seek to 5, read 3 bytes -> "567"
seek_file_s file._path_s STW
$0005 file.offset STW
buf1 file._buffer STW
$0003 file.length_w STW
file.op.read file.operation STB
buf1 puts JSRw
NL

; Seek to 2, write "AB" (overwrite in the middle)
seek_file_s file._path_s STW
$0002 file.offset STW
ab_text_s file._buffer STW
$0002 file.length_w STW
file.op.write file.operation STB

; Re-read the whole file to confirm the overwrite
seek_file_s file._path_s STW
$0000 file.offset STW
buf2 file._buffer STW
$000A file.length_w STW
file.op.read file.operation STB
buf2 puts JSRw
NL

; Path write resets FILE_OFFSET back to 0
seek_file_s file._path_s STW
file.offset LDW putd_w JSRw
NL

; Write with no seek still starts at cursor 0
q_text_s file._buffer STW
$0001 file.length_w STW
file.op.write file.operation STB
seek_file_s file._path_s STW
$0000 file.offset STW
buf3 file._buffer STW
$000A file.length_w STW
file.op.read file.operation STB
buf3 puts JSRw
NL

; Append, then seek+write overwrites instead of appending
seek_file_s file._path_s STW
bang_text_s file._buffer STW
$0002 file.length_w STW
file.op.append file.operation STB
; offset should now be at EOF (12)
file.offset LDW putd_w JSRw
NL
seek_file_s file._path_s STW
$0000 file.offset STW
z_text_s file._buffer STW
$0001 file.length_w STW
file.op.write file.operation STB
seek_file_s file._path_s STW
$0000 file.offset STW
buf4 file._buffer STW
$000C file.length_w STW
file.op.read file.operation STB
buf4 puts JSRw
NL

; Seek past EOF raises FILE_ERROR_OFFSET_RANGE
seek_error system._on_error STW
seek_file_s file._path_s STW
$00FF file.offset STW
unexpected_error system._on_error STW

; Splice: insert at offset 0
seek_file_s file._path_s STW
front_text_s file._buffer STW
$0000 file.length_w STW
file.op.splice file.operation STB
seek_file_s file._path_s STW
$0000 file.offset STW
buf5 file._buffer STW
$0012 file.length_w STW
file.op.read file.operation STB
buf5 puts JSRw
NL

; Splice: delete everything, leaving a 0-byte file
seek_file_s file._path_s STW
$0000 file.offset STW
$0000 file._buffer STW
$0012 file.length_w STW
file.op.splice file.operation STB
seek_file_s file._path_s STW
file.size_w LDW putd_w JSRw
NL

; Splice: shrink and grow on a fresh file
grow_file_s file._path_s STW
xxxxx_text_s file._buffer STW
$0005 file.length_w STW
file.op.write file.operation STB

; Shrink: replace 3 bytes (offset 1) with "YY" -> "XYYX"
grow_file_s file._path_s STW
$0001 file.offset STW
yy_text_s file._buffer STW
$0003 file.length_w STW
file.op.splice file.operation STB
grow_file_s file._path_s STW
$0000 file.offset STW
buf6 file._buffer STW
$0004 file.length_w STW
file.op.read file.operation STB
buf6 puts JSRw
NL

; Grow: replace 1 byte (offset 1) with "ZZZZZ" -> "XZZZZZYX"
grow_file_s file._path_s STW
$0001 file.offset STW
zzzzz_text_s file._buffer STW
$0001 file.length_w STW
file.op.splice file.operation STB
grow_file_s file._path_s STW
$0000 file.offset STW
buf7 file._buffer STW
$0008 file.length_w STW
file.op.read file.operation STB
buf7 puts JSRw
NL

; Splice error paths: offset > size, and missing file
splice_error system._on_error STW
grow_file_s file._path_s STW
$00FF file.offset STW
$0000 file.length_w STW
file.op.splice file.operation STB

missing_file_s file._path_s STW
$0000 file.offset STW
$0000 file.length_w STW
file.op.splice file.operation STB
unexpected_error system._on_error STW

HLT

; Error handlers
.label seek_error
  system.error LDB putd JSRw
  SP seek_range_msg_s puts JSRw
  $00 system.error STB
  RTS

.label splice_error
  system.error LDB putd JSRw
  SP splice_error_msg_s puts JSRw
  $00 system.error STB
  RTS

.label unexpected_error
  unexpected_error_msg_s puts JSRw
  $00 system.error STB
  HLT

.include "lib/puts.xyw"
.include "lib/putd.xyw"
.include "lib/putd_w.xyw"

.label seek_file_s
  .string "seek_file.txt"
.label grow_file_s
  .string "grow_file.txt"
.label missing_file_s
  .string "does_not_exist.txt"

.label digits_s
  .string "0123456789"
.label ab_text_s
  .string "AB"
.label q_text_s
  .string "Q"
.label bang_text_s
  .string "!!"
.label z_text_s
  .string "Z"
.label front_text_s
  .string "front-"
.label xxxxx_text_s
  .string "XXXXX"
.label yy_text_s
  .string "YY"
.label zzzzz_text_s
  .string "ZZZZZ"

.label seek_range_msg_s
  .string " seek-range-error\n"
.label splice_error_msg_s
  .string " splice-error\n"
.label unexpected_error_msg_s
  .string "unexpected error!\n"

.label buf0
  .reserve $03
.label buf1
  .reserve $04
.label buf2
  .reserve $0B
.label buf3
  .reserve $0B
.label buf4
  .reserve $0D
.label buf5
  .reserve $13
.label buf6
  .reserve $05
.label buf7
  .reserve $09