[m-rev.] diff 1/2: [net] Networking library improvments
Paul Bone
paul at bone.id.au
Sat Jan 10 15:20:32 AEDT 2015
Branches: master
---
[net] Networking library improvments
extras/net/streams.m:
Add a socket/1 function to get the socket of a stream.
Add a reader instance for lines and a writer instance for strings.
These don't do any character encoding or buffering. They're pretty
terrible but better than nothing.
extras/net/sockets.m:
Use shutdown() rather than close() for sockets.
---
extras/net/sockets.m | 2 +-
extras/net/streams.m | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+), 1 deletion(-)
diff --git a/extras/net/sockets.m b/extras/net/sockets.m
index c7a654c..7d0dfdb 100644
--- a/extras/net/sockets.m
+++ b/extras/net/sockets.m
@@ -399,7 +399,7 @@ close(Socket, Result, !IO) :-
struct linger sockets_linger = { MR_TRUE, 2 };
setsockopt(Socket, SOL_SOCKET, SO_LINGER,
&sockets_linger, sizeof(sockets_linger));
- if (-1 == close(Socket)) {
+ if (-1 == shutdown(Socket, SHUT_RDWR)) {
Errno = error();
Success = MR_NO;
} else {
diff --git a/extras/net/streams.m b/extras/net/streams.m
index 164d31d..12172cb 100644
--- a/extras/net/streams.m
+++ b/extras/net/streams.m
@@ -19,6 +19,7 @@
:- import_module int.
:- import_module io.
:- import_module stream.
+:- import_module string.
:- import_module net.sockets.
@@ -28,6 +29,8 @@
:- func stream(socket) = socket_stream.
+:- func socket(socket_stream) = socket.
+
:- type byte
---> byte(int).
@@ -45,6 +48,8 @@
%
:- instance reader(socket_stream, streams.byte, io, streams.error).
+:- instance reader(socket_stream, line, io, streams.error).
+
%-----------------------------------------------------------------------------%
:- instance output(socket_stream, io).
@@ -53,12 +58,16 @@
%
:- 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.
@@ -70,6 +79,8 @@
stream(Socket) = socket_stream(Socket).
+socket(socket_stream(Socket)) = Socket.
+
%-----------------------------------------------------------------------------%
:- instance error(streams.error) where [
@@ -117,6 +128,57 @@ get_byte(socket_stream(Socket), Result, !IO) :-
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) ->
+ (
+ ( Char = '\n'
+ ; Char = '\r'
+ )
+ ->
+ Result = ok(Chars0)
+ ;
+ 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 [
@@ -146,5 +208,21 @@ put_byte(socket_stream(Socket), byte(Byte), !IO) :-
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).
+
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
--
2.1.3
More information about the reviews
mailing list