]> Repositorios git - scryer-prolog.git/commitdiff
ENHANCED: faster format/3 when writing to binary streams
authorMarkus Triska <[email protected]>
Sun, 14 Jun 2020 08:06:27 +0000 (10:06 +0200)
committerMarkus Triska <[email protected]>
Sun, 14 Jun 2020 08:43:25 +0000 (10:43 +0200)
This is also more secure, since it does not change the atom table
and therefore leaves little trace of what was processed.

src/lib/format.pl
src/machine/system_calls.rs

index 2e496730329867324877e3cd5b51bfc3ecbf76bd..a3a0f5a4ffa485f0ee32d85405a9dba888f770b9 100644 (file)
@@ -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)
         ).
 
index e18da09b322eb7ebb53403ec8ec8895ca7cf7313..025da98b091f8067dbe4bcd8418dfeca901ff514 100644 (file)
@@ -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(_) => {