ENHANCED: faster format/3 when writing to binary streams
This is also more secure, since it does not change the atom table and therefore leaves little trace of what was processed.
This commit is contained in:
@@ -375,20 +375,9 @@ format(Fs, Args) :-
|
|||||||
format(Stream, Fs, Args) :-
|
format(Stream, Fs, Args) :-
|
||||||
phrase(format_(Fs, Args), Cs),
|
phrase(format_(Fs, Args), Cs),
|
||||||
( stream_property(Stream, type(binary)) ->
|
( stream_property(Stream, type(binary)) ->
|
||||||
% maplist(char_code, Cs, Bytes) is currently a lot slower
|
|
||||||
% than first converting Cs to an atom, and then to codes.
|
|
||||||
% In the future, we can ideally avoid creating an atom here,
|
|
||||||
% since an atom leaves traces in the system.
|
|
||||||
atom_chars(A, Cs),
|
|
||||||
atom_codes(A, Bytes),
|
|
||||||
( member(NonByte, Bytes), NonByte > 255 ->
|
|
||||||
char_code(Char, NonByte),
|
|
||||||
throw(error(representation_error(Char), format/3))
|
|
||||||
; true
|
|
||||||
),
|
|
||||||
% For binary streams, we use a specialised internal predicate
|
% For binary streams, we use a specialised internal predicate
|
||||||
% that uses only a single "write" operation for efficiency.
|
% that uses only a single "write" operation for efficiency.
|
||||||
'$put_bytes'(Stream, Bytes)
|
'$put_bytes'(Stream, Cs)
|
||||||
; maplist(put_char(Stream), Cs)
|
; maplist(put_char(Stream), Cs)
|
||||||
).
|
).
|
||||||
|
|
||||||
|
|||||||
@@ -2022,8 +2022,24 @@ impl MachineState {
|
|||||||
let mut stream =
|
let mut stream =
|
||||||
self.get_stream_or_alias(self[temp_v!(1)], indices, "$put_bytes", 2)?;
|
self.get_stream_or_alias(self[temp_v!(1)], indices, "$put_bytes", 2)?;
|
||||||
|
|
||||||
|
let mut iter = self.heap_pstr_iter(self[temp_v!(2)]);
|
||||||
|
let mut bytes = Vec::new();
|
||||||
|
for c in iter.to_string().chars() {
|
||||||
|
if c as u32 > 255 {
|
||||||
|
|
||||||
let stub = MachineError::functor_stub(clause_name!("$put_bytes"), 2);
|
let stub = MachineError::functor_stub(clause_name!("$put_bytes"), 2);
|
||||||
let bytes = self.integers_to_bytevec(temp_v!(2), stub);
|
|
||||||
|
let err = MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::Byte,
|
||||||
|
Addr::Char(c),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Err(self.error_form(err, stub));
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes.push(c as u8);
|
||||||
|
}
|
||||||
|
|
||||||
match stream.write(&bytes) {
|
match stream.write(&bytes) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user