From: Markus Triska Date: Sun, 14 Jun 2020 08:06:27 +0000 (+0200) Subject: ENHANCED: faster format/3 when writing to binary streams X-Git-Tag: v0.8.127~31^2~1^2~1 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=409d3c168dc43f2489502d0599fe7c9e5c4839bb;p=scryer-prolog.git 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. --- diff --git a/src/lib/format.pl b/src/lib/format.pl index 2e496730..a3a0f5a4 100644 --- a/src/lib/format.pl +++ b/src/lib/format.pl @@ -375,20 +375,9 @@ format(Fs, Args) :- format(Stream, Fs, Args) :- phrase(format_(Fs, Args), Cs), ( 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 % that uses only a single "write" operation for efficiency. - '$put_bytes'(Stream, Bytes) + '$put_bytes'(Stream, Cs) ; maplist(put_char(Stream), Cs) ). diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index e18da09b..025da98b 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -2022,8 +2022,24 @@ impl MachineState { let mut stream = self.get_stream_or_alias(self[temp_v!(1)], indices, "$put_bytes", 2)?; - let stub = MachineError::functor_stub(clause_name!("$put_bytes"), 2); - let bytes = self.integers_to_bytevec(temp_v!(2), stub); + 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 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) { Ok(_) => {