I finally got some time to look at this again yesterday, here is what I ended up with, for those following along that want this functionality:
/*
(file-position stream) returns current file postition
(file-position stream position) seeks to position given
*/
object *fn_file_position(object *args, object *env) {
(void) env;
#if defined(sdcardsupport)
int stream = isstream(first(args));
if (stream>>8 != SDSTREAM) error2("not an SD file stream");
int address = stream & 0xFF;
File *file = (address >= 1) ? &SDpfile : &SDgfile;
if (cdr(args) != NULL) {
unsigned long pos = (unsigned long)(checkinteger(second(args)));
if (pos <= file->size()) {
file->seek(pos);
return number(pos);
}
} else {
if (*file) {
unsigned long position = file->position();
return number(position);
} else { error2("problem reading file position");}
}
#endif
return nil;
}
This will work for both read and write, although it requires some updates to the with-sd-card C function to pass along the stream’s mode.
In the main ino file (i.e. ulisp-tdeck.ino), function sp_withsdcard change the address of 1 to mode, which has already been set.
object *pair = cons(var, stream(SDSTREAM, mode));
Unfortunately, the write modes supplied don’t allow for seeking to a specific position and editing data. They all append to the files last position, blocking the seek functionality. One leaves the existing data, appending only to the end; and the other mode clears the whole file, appending to the beginning. For the esp32, the modes are posix compliant (https://pubs.opengroup.org/onlinepubs/009695399/functions/fopen.html), a slight deviation from other arduino file operations, I believe.
There is a third option r+, that allows one to read and write to the file where the seek functionality is not blocked.
Going forward, I’m not sure if sticking to the enumerated integer values for file modes makes sense, and add 3, or to just pass the string values themselves, in which the options would be:
"r" Open file for reading.
"w" Truncate to zero length or create file for writing.
"a" Append; open or create file for writing at end-of-file.
"r+" Open file for update (reading and writing).
"w+" Truncate to zero length or create file for update.
"a+" Append; open or create file for update, writing at end-of-file.
Some of these seem redundant. I’m not sure what the use cases for a+ and w+ differ from a and w. I wish they’d used u instead of r+.
In this case the ulisp would look like:
(with-sd-card (str "test.txt" "r+")
(file-position str 35)
(write-string "new text" str))