mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2026-01-23 04:52:42 -08:00
ecl_open_stream refactor
We rearrange the code and avoid unnecessary file operations with probe. Some nesting is removed.
This commit is contained in:
parent
d9c4b2a88c
commit
c35f98ef58
2 changed files with 67 additions and 87 deletions
125
src/c/file.d
125
src/c/file.d
|
|
@ -5060,115 +5060,98 @@ FEinvalid_option(cl_object option, cl_object value)
|
|||
}
|
||||
|
||||
cl_object
|
||||
ecl_open_stream(cl_object fn, enum ecl_smmode smm, cl_object if_exists,
|
||||
ecl_open_stream(cl_object filename, enum ecl_smmode smm, cl_object if_exists,
|
||||
cl_object if_does_not_exist, cl_fixnum byte_size,
|
||||
int flags, cl_object external_format)
|
||||
{
|
||||
cl_object output;
|
||||
int f;
|
||||
char *fname;
|
||||
bool appending = 0, exists;
|
||||
#if defined(ECL_MS_WINDOWS_HOST)
|
||||
ecl_mode_t mode = _S_IREAD | _S_IWRITE;
|
||||
#else
|
||||
ecl_mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
||||
#endif
|
||||
cl_object filename = si_coerce_to_filename(fn);
|
||||
char *fname = (char*)filename->base_string.self;
|
||||
bool appending = 0;
|
||||
bool exists = si_file_kind(filename, ECL_T) != ECL_NIL;
|
||||
if (smm == ecl_smm_input || smm == ecl_smm_probe) {
|
||||
if (!exists) {
|
||||
if (if_does_not_exist == @':error') {
|
||||
FEcannot_open(fn);
|
||||
} else if (if_does_not_exist == @':create') {
|
||||
f = safe_open(fname, O_WRONLY|O_CREAT, mode);
|
||||
unlikely_if (f < 0) FEcannot_open(fn);
|
||||
safe_close(f);
|
||||
} else if (Null(if_does_not_exist)) {
|
||||
return ECL_NIL;
|
||||
} else {
|
||||
FEinvalid_option(@':if-does-not-exist',
|
||||
if_does_not_exist);
|
||||
}
|
||||
}
|
||||
filename = si_coerce_to_filename(filename);
|
||||
fname = (char*)filename->base_string.self;
|
||||
exists = si_file_kind(filename, ECL_T) != ECL_NIL;
|
||||
if (!exists) {
|
||||
if (if_does_not_exist == ECL_NIL) return ECL_NIL;
|
||||
if (if_does_not_exist == @':error') FEcannot_open(filename);
|
||||
if (if_does_not_exist != @':create')
|
||||
FEinvalid_option(@':if-does-not-exist', if_does_not_exist);
|
||||
f = safe_open(fname, O_WRONLY|O_CREAT, mode);
|
||||
unlikely_if (f < 0) FEcannot_open(filename);
|
||||
safe_close(f);
|
||||
}
|
||||
|
||||
switch (smm) {
|
||||
case ecl_smm_probe:
|
||||
output = ecl_make_file_stream_from_fd(filename, -1, smm, byte_size, flags, external_format);
|
||||
generic_close(output);
|
||||
return output;
|
||||
case ecl_smm_input:
|
||||
f = safe_open(fname, O_RDONLY, mode);
|
||||
unlikely_if (f < 0) FEcannot_open(fn);
|
||||
} else if (smm == ecl_smm_output || smm == ecl_smm_io) {
|
||||
unlikely_if (f < 0) FEcannot_open(filename);
|
||||
break;
|
||||
case ecl_smm_output:
|
||||
case ecl_smm_io: {
|
||||
int base = (smm == ecl_smm_output)? O_WRONLY : O_RDWR;
|
||||
if (if_exists == @':new_version' &&
|
||||
if_does_not_exist == @':create') {
|
||||
exists = 0;
|
||||
if_does_not_exist = @':create';
|
||||
}
|
||||
if (exists) {
|
||||
if (if_exists == @':error') {
|
||||
FEcannot_open(fn);
|
||||
} else if (if_exists == @':rename') {
|
||||
if (if_exists == ECL_NIL) return ECL_NIL;
|
||||
if (if_exists == @':error') FEcannot_open(filename);
|
||||
if (if_exists == @':rename') {
|
||||
f = ecl_backup_open(fname, base|O_CREAT, mode);
|
||||
unlikely_if (f < 0) FEcannot_open(fn);
|
||||
unlikely_if (f < 0) FEcannot_open(filename);
|
||||
} else if (if_exists == @':rename_and_delete' ||
|
||||
if_exists == @':new_version' ||
|
||||
/* :SUPERSEDE could write to a new file and only upon succesful
|
||||
close it could replace the file in question. That way we'd
|
||||
assure a transaction-like behavior. We add :TRUNACTE for
|
||||
explicit truncate action. */
|
||||
if_exists == @':supersede' ||
|
||||
if_exists == @':truncate') {
|
||||
f = safe_open(fname, base|O_TRUNC, mode);
|
||||
unlikely_if (f < 0) FEcannot_open(fn);
|
||||
unlikely_if (f < 0) FEcannot_open(filename);
|
||||
} else if (if_exists == @':overwrite' || if_exists == @':append') {
|
||||
f = safe_open(fname, base, mode);
|
||||
unlikely_if (f < 0) FEcannot_open(fn);
|
||||
unlikely_if (f < 0) FEcannot_open(filename);
|
||||
appending = (if_exists == @':append');
|
||||
} else if (Null(if_exists)) {
|
||||
return ECL_NIL;
|
||||
} else {
|
||||
FEinvalid_option(@':if-exists', if_exists);
|
||||
}
|
||||
} else {
|
||||
if (if_does_not_exist == @':error') {
|
||||
FEcannot_open(fn);
|
||||
} else if (if_does_not_exist == @':create') {
|
||||
f = safe_open(fname, base | O_CREAT | O_TRUNC, mode);
|
||||
unlikely_if (f < 0) FEcannot_open(fn);
|
||||
} else if (Null(if_does_not_exist)) {
|
||||
return ECL_NIL;
|
||||
} else {
|
||||
FEinvalid_option(@':if-does-not-exist',
|
||||
if_does_not_exist);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
FEerror("Illegal stream mode ~S", 1, ecl_make_fixnum(smm));
|
||||
}
|
||||
if (flags & ECL_STREAM_C_STREAM) {
|
||||
FILE *fp = 0;
|
||||
safe_close(f);
|
||||
/* We do not use fdopen() because Windows seems to
|
||||
* have problems with the resulting streams. Furthermore, even for
|
||||
* output we open with w+ because we do not want to
|
||||
* overwrite the file. */
|
||||
/* We do not use fdopen() because Windows seems to have problems with the
|
||||
* resulting streams. Furthermore, even for output we open with w+ because
|
||||
* we do not want to overwrite the file. */
|
||||
switch (smm) {
|
||||
case ecl_smm_probe:
|
||||
case ecl_smm_input: fp = safe_fopen(fname, OPEN_R); break;
|
||||
/* never happens (returns earlier) */
|
||||
case ecl_smm_input:
|
||||
fp = safe_fopen(fname, OPEN_R);
|
||||
break;
|
||||
case ecl_smm_output:
|
||||
case ecl_smm_io: fp = safe_fopen(fname, OPEN_RW); break;
|
||||
default:; /* never reached */
|
||||
case ecl_smm_io:
|
||||
fp = safe_fopen(fname, OPEN_RW);
|
||||
break;
|
||||
default:;
|
||||
/* never reached (errors earlier) */
|
||||
}
|
||||
output = ecl_make_stream_from_FILE(fn, fp, smm, byte_size, flags,
|
||||
external_format);
|
||||
output = ecl_make_stream_from_FILE(filename, fp, smm, byte_size, flags, external_format);
|
||||
si_set_buffering_mode(output, byte_size? @':full' : @':line');
|
||||
} else {
|
||||
output = ecl_make_file_stream_from_fd(fn, f, smm, byte_size, flags,
|
||||
external_format);
|
||||
}
|
||||
if (smm == ecl_smm_probe) {
|
||||
cl_close(1, output);
|
||||
} else {
|
||||
output->stream.flags |= ECL_STREAM_MIGHT_SEEK;
|
||||
si_set_finalizer(output, ECL_T);
|
||||
/* Set file pointer to the correct position */
|
||||
ecl_file_position_set(output, appending? ECL_NIL : ecl_make_fixnum(0));
|
||||
output = ecl_make_file_stream_from_fd(filename, f, smm, byte_size, flags, external_format);
|
||||
}
|
||||
|
||||
output->stream.flags |= ECL_STREAM_MIGHT_SEEK;
|
||||
si_set_finalizer(output, ECL_T);
|
||||
/* Set file pointer to the correct position */
|
||||
ecl_file_position_set(output, appending? ECL_NIL : ecl_make_fixnum(0));
|
||||
return output;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -466,13 +466,12 @@ struct ecl_array { /* array header */
|
|||
struct ecl_vector { /* vector header */
|
||||
/* adjustable flag */
|
||||
/* has-fill-pointer flag */
|
||||
_ECL_HDR2(elttype,flags); /* array element type, has fill ptr, adjustable-p */
|
||||
_ECL_HDR2(elttype,flags); /* array element type, has fill ptr, adjustable-p */
|
||||
cl_object displaced; /* displaced */
|
||||
cl_index dim; /* dimension */
|
||||
cl_index fillp; /* fill pointer */
|
||||
/* For simple vectors, */
|
||||
/* v_fillp is equal to v_dim. */
|
||||
union ecl_array_data self; /* pointer to the vector */
|
||||
/* For simple vectors, fillp is equal to dim. */
|
||||
union ecl_array_data self; /* pointer to the vector */
|
||||
byte offset;
|
||||
};
|
||||
|
||||
|
|
@ -495,11 +494,9 @@ struct ecl_string { /* string header */
|
|||
/* has-fill-pointer flag */
|
||||
_ECL_HDR2(elttype,flags); /* array element type, has fill ptr, adjustable-p */
|
||||
cl_object displaced; /* displaced */
|
||||
cl_index dim; /* dimension */
|
||||
/* string length */
|
||||
cl_index dim; /* dimension, string length */
|
||||
cl_index fillp; /* fill pointer */
|
||||
/* For simple strings, */
|
||||
/* st_fillp is equal to st_dim-1. */
|
||||
/* For simple strings, fillp is equal to dim-1. */
|
||||
ecl_character *self; /* pointer to the string */
|
||||
};
|
||||
#endif
|
||||
|
|
@ -513,15 +510,15 @@ struct ecl_string { /* string header */
|
|||
|
||||
enum ecl_smmode { /* stream mode */
|
||||
ecl_smm_input, /* input */
|
||||
ecl_smm_input_file, /* input */
|
||||
ecl_smm_input_file, /* input */
|
||||
ecl_smm_output, /* output */
|
||||
ecl_smm_output_file, /* output */
|
||||
ecl_smm_io, /* input-output */
|
||||
ecl_smm_io_file, /* input-output */
|
||||
ecl_smm_synonym, /* synonym */
|
||||
ecl_smm_broadcast, /* broadcast */
|
||||
ecl_smm_io, /* input-output */
|
||||
ecl_smm_io_file, /* input-output */
|
||||
ecl_smm_synonym, /* synonym */
|
||||
ecl_smm_broadcast, /* broadcast */
|
||||
ecl_smm_concatenated, /* concatenated */
|
||||
ecl_smm_two_way, /* two way */
|
||||
ecl_smm_two_way, /* two way */
|
||||
ecl_smm_echo, /* echo */
|
||||
ecl_smm_string_input, /* string input */
|
||||
ecl_smm_string_output, /* string output */
|
||||
|
|
@ -529,10 +526,10 @@ enum ecl_smmode { /* stream mode */
|
|||
#if defined(ECL_WSOCK)
|
||||
ecl_smm_input_wsock, /* input socket (Win32) */
|
||||
ecl_smm_output_wsock, /* output socket (Win32) */
|
||||
ecl_smm_io_wsock, /* input/output socket (Win32) */
|
||||
ecl_smm_io_wsock, /* input/output socket (Win32) */
|
||||
#endif
|
||||
#if defined(ECL_MS_WINDOWS_HOST)
|
||||
ecl_smm_io_wcon, /* windows console (Win32) */
|
||||
ecl_smm_io_wcon, /* windows console (Win32) */
|
||||
#endif
|
||||
ecl_smm_sequence_input, /* sequence input */
|
||||
ecl_smm_sequence_output /* sequence output */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue