add set_stream_position/2
This commit is contained in:
@@ -248,6 +248,7 @@ pub enum SystemClauseType {
|
||||
StoreGlobalVar,
|
||||
StoreGlobalVarWithOffset,
|
||||
StreamProperty,
|
||||
SetStreamPosition,
|
||||
InferenceLevel,
|
||||
CleanUpBlock,
|
||||
EraseBall,
|
||||
@@ -422,6 +423,7 @@ impl SystemClauseType {
|
||||
&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")
|
||||
@@ -575,6 +577,7 @@ impl SystemClauseType {
|
||||
("$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),
|
||||
|
||||
@@ -59,10 +59,10 @@ user:term_expansion((:- op(Pred, Spec, [Op | OtherOps])), OpResults) :-
|
||||
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]).
|
||||
|
||||
@@ -1320,3 +1320,12 @@ at_end_of_stream :-
|
||||
!,
|
||||
( 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).
|
||||
|
||||
@@ -468,9 +468,11 @@ pub enum Permission {
|
||||
Modify,
|
||||
Open,
|
||||
OutputStream,
|
||||
Reposition,
|
||||
}
|
||||
|
||||
impl Permission {
|
||||
#[inline]
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
Permission::Access => "access",
|
||||
@@ -479,6 +481,7 @@ impl Permission {
|
||||
Permission::Modify => "modify",
|
||||
Permission::Open => "open",
|
||||
Permission::OutputStream => "output",
|
||||
Permission::Reposition => "reposition",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,15 @@ impl StreamType {
|
||||
#[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",
|
||||
@@ -296,6 +305,22 @@ impl Stream {
|
||||
}
|
||||
}
|
||||
|
||||
#[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 {
|
||||
|
||||
@@ -4556,6 +4556,49 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
}
|
||||
&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)],
|
||||
@@ -4648,7 +4691,7 @@ impl MachineState {
|
||||
}
|
||||
"type" => {
|
||||
HeapCellValue::Atom(
|
||||
clause_name!(stream.options.stream_type.as_str()),
|
||||
clause_name!(stream.options.stream_type.as_property_str()),
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user