StoreGlobalVar,
StoreGlobalVarWithOffset,
StreamProperty,
+ SetStreamPosition,
InferenceLevel,
CleanUpBlock,
EraseBall,
&SystemClauseType::SetOutput => clause_name!("$set_output"),
&SystemClauseType::SetSeed => clause_name!("$set_seed"),
&SystemClauseType::StreamProperty => clause_name!("$stream_property"),
+ &SystemClauseType::SetStreamPosition => clause_name!("$set_stream_position"),
&SystemClauseType::StoreGlobalVar => clause_name!("$store_global_var"),
&SystemClauseType::StoreGlobalVarWithOffset => {
clause_name!("$store_global_var_with_offset")
("$set_input", 1) => Some(SystemClauseType::SetInput),
("$set_output", 1) => Some(SystemClauseType::SetOutput),
("$stream_property", 3) => Some(SystemClauseType::StreamProperty),
+ ("$set_stream_position", 2) => Some(SystemClauseType::SetStreamPosition),
("$inference_level", 2) => Some(SystemClauseType::InferenceLevel),
("$clean_up_block", 1) => Some(SystemClauseType::CleanUpBlock),
("$erase_ball", 0) => Some(SystemClauseType::EraseBall),
put_byte/1, put_byte/2, put_code/1, put_code/2,
put_char/1, put_char/2, read_term/2, read_term/3,
repeat/0, retract/1, set_prolog_flag/2,
- set_input/1, set_output/1, setof/3,
- stream_property/2, sub_atom/5, subsumes_term/2,
- term_variables/2, throw/1, true/0,
- unify_with_occurs_check/2, write/1,
+ set_input/1, set_stream_position/2, set_output/1,
+ setof/3, stream_property/2, sub_atom/5,
+ subsumes_term/2, term_variables/2, throw/1,
+ true/0, unify_with_occurs_check/2, write/1,
write_canonical/1, write_term/2, write_term/3,
writeq/1]).
!,
( E = at ; E = past ).
+
+set_stream_position(S_or_a, Position) :-
+ ( var(Position) ->
+ throw(error(instantiation_error, set_stream_position/2))
+ ; integer(Position), Position >= 0 ->
+ true
+ ; throw(error(domain_error(stream_position, Position)))
+ ),
+ '$set_stream_position'(S_or_a, Position).
Modify,
Open,
OutputStream,
+ Reposition,
}
impl Permission {
+ #[inline]
pub fn as_str(self) -> &'static str {
match self {
Permission::Access => "access",
Permission::Modify => "modify",
Permission::Open => "open",
Permission::OutputStream => "output",
+ Permission::Reposition => "reposition",
}
}
}
#[inline]
pub(crate)
fn as_str(&self) -> &'static str {
+ match self {
+ StreamType::Binary => "binary_stream",
+ StreamType::Text => "text_stream",
+ }
+ }
+
+ #[inline]
+ pub(crate)
+ fn as_property_str(&self) -> &'static str {
match self {
StreamType::Binary => "binary",
StreamType::Text => "text",
}
}
+ #[inline]
+ pub(crate)
+ fn set_position(&mut self, position: u64) {
+ match self.stream_inst.0.borrow_mut().deref_mut() {
+ (past_end_of_stream, StreamInstance::InputFile(_, ref mut file)) => {
+ file.seek(SeekFrom::Start(position)).unwrap();
+
+ if let Ok(metadata) = file.metadata() {
+ *past_end_of_stream = position > metadata.len();
+ }
+ }
+ _ => {
+ }
+ }
+ }
+
#[inline]
pub(crate)
fn past_end_of_stream(&self) -> bool {
}
}
}
+ &SystemClauseType::SetStreamPosition => {
+ let mut stream = self.get_stream_or_alias(
+ self[temp_v!(1)],
+ indices,
+ "set_stream_position",
+ 2,
+ )?;
+
+ if !stream.options.reposition {
+ let stub = MachineError::functor_stub(clause_name!("set_stream_position"), 2);
+
+ let err = MachineError::permission_error(
+ self.heap.h(),
+ Permission::Reposition,
+ "stream",
+ vec![HeapCellValue::Stream(stream)],
+ );
+
+ return Err(self.error_form(err, stub));
+ }
+
+ let position = self.store(self.deref(self[temp_v!(2)]));
+
+ let position =
+ match Number::try_from((position, &self.heap)) {
+ Ok(Number::Fixnum(n)) => {
+ n as u64
+ }
+ Ok(Number::Integer(n)) => {
+ if let Some(n) = n.to_u64() {
+ n
+ } else {
+ self.fail = true;
+ return Ok(());
+ }
+ }
+ _ => {
+ unreachable!()
+ }
+ };
+
+ stream.set_position(position);
+ }
&SystemClauseType::StreamProperty => {
let mut stream = self.get_stream_or_alias(
self[temp_v!(1)],
}
"type" => {
HeapCellValue::Atom(
- clause_name!(stream.options.stream_type.as_str()),
+ clause_name!(stream.options.stream_type.as_property_str()),
None,
)
}