mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-19 11:23:46 +00:00
extras/curs/curs.m:
extras/curs/curs.panel.m:
Make panel a separate submodule of curs, not a nested submodule.
extras/base64/base64.m:
extras/curses/mcurses.basics.m:
extras/curses/mcurses.m:
extras/curses/mcurses.misc.m:
extras/curses/mcurses.user.m:
extras/gator/evolve.m:
extras/gator/genotype.m:
extras/gator/phenotype.m:
extras/gator/tausworthe3.m:
extras/monte/dots.m:
extras/monte/geom.m:
extras/monte/hg.m:
extras/monte/monte.m:
extras/monte/rnd.m:
extras/moose/grammar.m:
extras/moose/moose.m:
extras/mopenssl/mopenssl.m:
extras/net/echo.m:
extras/net/errno.m:
extras/net/getaddrinfo.m:
extras/net/net.m:
extras/net/netdb.m:
extras/net/sockets.m:
extras/net/streams.m:
extras/net/tcp.m:
extras/net/test_lookups.m:
extras/net/types.m:
extras/odbc/odbc.m:
extras/odbc/odbc_test.m:
extras/references/README:
extras/references/reference.m:
extras/references/scoped_update.m:
extras/solver_types/library/any.m:
extras/solver_types/library/any_array.m:
extras/solver_types/library/any_assoc_list.m:
extras/solver_types/library/any_list.m:
extras/solver_types/library/any_map.m:
extras/solver_types/library/any_tree234.m:
extras/solver_types/library/any_util.m:
extras/trail/trail.m:
extras/trailed_update/samples/interpreter.m:
extras/trailed_update/samples/vqueens.m:
extras/trailed_update/tests/var_test.m:
extras/trailed_update/tr_array.m:
extras/trailed_update/tr_store.m:
extras/trailed_update/trailed_update.m:
extras/trailed_update/unsafe.m:
extras/trailed_update/var.m:
Bring programming style up to date.
229 lines
6.0 KiB
Mathematica
229 lines
6.0 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2014-2016, 2018 The Mercury Team.
|
|
% This file is distributed under the terms specified in COPYING.LIB.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Module: net.streams.
|
|
% Main Author: Paul Bone
|
|
% Stability: low
|
|
%
|
|
% Provide a streams interface for sockets.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module net.streams.
|
|
:- interface.
|
|
|
|
:- import_module int.
|
|
:- import_module io.
|
|
:- import_module stream.
|
|
:- import_module string.
|
|
|
|
:- import_module net.sockets.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- type socket_stream.
|
|
|
|
:- func stream(socket) = socket_stream.
|
|
|
|
:- func socket(socket_stream) = socket.
|
|
|
|
:- type byte
|
|
---> byte(int).
|
|
|
|
:- type error.
|
|
|
|
:- instance error(streams.error).
|
|
|
|
:- instance stream(socket_stream, io).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- instance input(socket_stream, io).
|
|
|
|
% XXX: This does not buffer reads, it is slow.
|
|
%
|
|
:- instance reader(socket_stream, streams.byte, io, streams.error).
|
|
|
|
:- instance reader(socket_stream, line, io, streams.error).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- instance output(socket_stream, io).
|
|
|
|
% XXX: This does not buffer writes, it is slow.
|
|
%
|
|
:- instance writer(socket_stream, streams.byte, io).
|
|
|
|
:- instance writer(socket_stream, string, io).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
:- implementation.
|
|
|
|
:- import_module char.
|
|
:- import_module exception.
|
|
:- import_module bitmap.
|
|
:- import_module list.
|
|
:- import_module maybe.
|
|
:- import_module require.
|
|
|
|
:- type socket_stream
|
|
---> socket_stream(socket).
|
|
|
|
:- type error
|
|
---> error(string).
|
|
|
|
stream(Socket) = socket_stream(Socket).
|
|
|
|
socket(socket_stream(Socket)) = Socket.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- instance error(streams.error) where [
|
|
error_message(error(Str)) = Str
|
|
].
|
|
|
|
:- instance stream(socket_stream, io) where [
|
|
pred(name/4) is stream_name
|
|
].
|
|
|
|
:- pred stream_name(socket_stream::in, name::out, io::di, io::uo) is det.
|
|
|
|
stream_name(socket_stream(_Socket), Name, !IO) :-
|
|
Name = "a socket".
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- instance input(socket_stream, io) where [].
|
|
|
|
:- instance reader(socket_stream, streams.byte, io, streams.error) where [
|
|
pred(get/4) is get_byte
|
|
].
|
|
|
|
:- pred get_byte(socket_stream::in, result(streams.byte, streams.error)::out,
|
|
io::di, io::uo) is det.
|
|
|
|
get_byte(socket_stream(Socket), Result, !IO) :-
|
|
read(Socket, 1, ReadResult, !IO),
|
|
(
|
|
ReadResult = ok(Bitmap),
|
|
( if num_bytes(Bitmap) = 1 then
|
|
Byte = Bitmap ^ byte(0),
|
|
Result = ok(byte(Byte))
|
|
else if num_bytes(Bitmap) = 0 then
|
|
Result = eof
|
|
else
|
|
unexpected($file, $pred,
|
|
"Read returned unexpected number of bytes")
|
|
)
|
|
;
|
|
ReadResult = eof,
|
|
Result = eof
|
|
;
|
|
ReadResult = error(String),
|
|
Result = error(error(String))
|
|
).
|
|
|
|
:- instance reader(socket_stream, line, io, streams.error) where [
|
|
pred(get/4) is get_line
|
|
].
|
|
|
|
:- pred get_line(socket_stream::in, result(line, streams.error)::out,
|
|
io::di, io::uo) is det.
|
|
|
|
get_line(Stream, Result, !IO) :-
|
|
get_chars_until_nl(Stream, [], Result0, !IO),
|
|
(
|
|
Result0 = ok(RevChars),
|
|
Result = ok(line(from_rev_char_list(RevChars)))
|
|
;
|
|
Result0 = eof,
|
|
Result = eof
|
|
;
|
|
Result0 = error(Error),
|
|
Result = error(Error)
|
|
).
|
|
|
|
:- pred get_chars_until_nl(Stream::in, list(char)::in,
|
|
result(list(char), Error)::out, State::di, State::uo) is det
|
|
<= reader(Stream, streams.byte, State, Error).
|
|
|
|
get_chars_until_nl(Stream, Chars0, Result, !IO) :-
|
|
get(Stream, ResByte, !IO),
|
|
(
|
|
ResByte = ok(byte(Byte)),
|
|
( char.from_int(Byte, Char) ->
|
|
( if
|
|
( Char = '\n'
|
|
; Char = '\r'
|
|
)
|
|
then
|
|
Result = ok(Chars0)
|
|
else
|
|
Chars1 = [Char | Chars0],
|
|
get_chars_until_nl(Stream, Chars1, Result, !IO)
|
|
)
|
|
;
|
|
unexpected($file, $pred, "Encoding error")
|
|
)
|
|
;
|
|
ResByte = eof,
|
|
Result = eof
|
|
;
|
|
ResByte = error(Error),
|
|
Result = error(Error)
|
|
).
|
|
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- instance output(socket_stream, io) where [
|
|
pred(flush/3) is flush_noop
|
|
].
|
|
|
|
:- pred flush_noop(socket_stream::in, io::di, io::uo) is det.
|
|
|
|
flush_noop(_, !IO).
|
|
|
|
% XXX: This does not buffer writes, it is slow.
|
|
%
|
|
:- instance writer(socket_stream, streams.byte, io) where [
|
|
pred(put/4) is put_byte
|
|
].
|
|
|
|
:- pred put_byte(socket_stream::in, streams.byte::in, io::di, io::uo)
|
|
is det.
|
|
|
|
put_byte(socket_stream(Socket), byte(Byte), !IO) :-
|
|
Bitmap = init(bits_per_byte) ^ byte(0) := Byte,
|
|
write(Socket, Bitmap, Result, !IO),
|
|
(
|
|
Result = ok
|
|
;
|
|
Result = error(Error),
|
|
throw(streams.error(Error))
|
|
).
|
|
|
|
:- instance writer(socket_stream, string, io) where [
|
|
pred(put/4) is put_string
|
|
].
|
|
|
|
:- pred put_string(Stream::in, string::in, State::di, State::uo) is det
|
|
<= writer(Stream, streams.byte, State).
|
|
|
|
put_string(Stream, String, !State) :-
|
|
foldl(put_char(Stream), String, !State).
|
|
|
|
:- pred put_char(Stream::in, char::in, State::di, State::uo) is det
|
|
<= writer(Stream, streams.byte, State).
|
|
|
|
put_char(Stream, Char, !State) :-
|
|
put(Stream, byte(to_int(Char)), !State).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|