3 * lineread.c - functions to read lines from sockets effectively
5 * Copyright © 1994 AmiTCP/IP Group,
6 * Network Solutions Development Inc.
8 * Copyright © 2005 Pavel Fedin
12 * since charRead is a macro package and having no `.c' -file, it's
13 * documentation is added here
16 /****** net.lib/charRead ****************************************************
19 charRead -- read characters from socket one by one.
24 void initCharRead(struct CharRead *, int);
27 character = charRead(rc)
29 int charRead(struct CharRead *);
33 charRead is a macro package which return characters one by one
34 from given socket input stream. The socket where data is to be read
35 is set by calling initCharRead(): rc is the pointer to charread
36 structure previously allocated. fd is the (socket) descriptor where
37 reading is to be done.
39 charRead() returns the next character from input stream or one of
42 RC_DO_SELECT (-3) - read input buffer is returned. Do select
43 before next call if you don't want charread
46 RC_EOF (-2) - end-of-file condition has occurred.
48 RC_ERROR (-1) - there has been an error while filling new
49 charread buffer. Check the value of Errno()
52 Always use variable of type int to store return value from charRead()
53 since the numeric value of characters returned may vary between
54 0 -255 (or even greater). As you may know, -3 equals 253 if of type
59 * This piece of code shows how to use charread with select()
61 #include <sys/types.h>
62 #include <sys/socket.h>
71 initCharRead(&rc, sock);
76 FD_SET(sock, &readfds);
78 if (select(sock + 1. &readfds, NULL, NULL, NULL)) < 0) {
82 if (FD_ISSET(sock, &readfds)) {
83 while((c = charRead(&rc)) >= 0)
84 handle_next_input_character(c);
96 The source file charread.h should be able to be used in
100 lineRead(), bsdsocket.library/recv()
101 *****************************************************************************
106 /****** net.lib/lineRead *****************************************************
109 lineRead -- read newline terminated strings from socket
112 initLineRead(rl, fd, lftype, bufsize)
114 void initLineRead(struct LineRead *, int, int, int);
117 length = lineRead(rl)
119 int lineread(struct LineRead *);
123 lineRead() reads newline terminated strings from given descriptor
124 very efficiently. All the options needed are set by calling
125 initLineRead(): rl is the pointer to lineread structure previously
126 allocated. fd is the (socket) descriptor where reading is to be
127 done. lftype can have following 3 values:
129 RL_LFNOTREQ - Newline terminated strings are returned unless
130 there is no newlines left in currently buffered
131 input. In this case remaining buffer is returned.
133 RL_LFREQLF - If there is no newlines left in currently buffered
134 input the remaining input data is copied at the
135 start of buffer. Caller is informed that next
136 call will fill the buffer (and it may block).
137 Lines are always returned with newline at the end
138 unless the string is longer than whole buffer.
140 RL_LFREQNUL - Like LF_REQLF, but remaining newline is removed.
141 Note here that lenght is one longer that actual
142 string length since line that has only one
143 newline at the end would return length as 0
144 which indigate string incomplete condition.
146 bufsize is used to tell lineread how big the receive buffer is.
147 always put RL_BUFSIZE here since that value is used to determine
148 the memory allocated for the buffer. This option is given to you
149 so you may decide to use different buffer size than the default
152 lineRead() returns the newline terminated string in rl_line field
153 of lineread structure. Return values of lineRead() are:
155 1 - RL_BUFSIZE - normal length of returned string.
157 0 - If zero is returned just after select(),
158 end-of-file condition has occurred.
159 Otherwise string is not completed yet.
160 Make sure you call select() (or use non-
161 blocking IO) if you don't want next call
164 -1 - if rl_Line field of lineread structure
165 is NULL, it indicates error condition.
166 If rl_Line points to start of string
167 buffer, input string has been longer
168 than buffer. In this case rl_Line points
169 to zero terminated string of length
172 You may modify the zero terminated string returned by lineRead() in
173 any way, but memory around the string is private lineread memory.
177 * The following code shows how to use lineread with select()
179 #ifdef USE_LOW_MEMORY_BUFFER
180 #define RL_BUFSIZE 256
183 #include <sys/types.h>
185 #include <bsdsocket.h>
187 #include <lineread.h>
195 struct LineRead * rl;
199 if (rl = (struct LineRead *)AllocMem(sizeof (*rl), 0)) {
201 initLineRead(rl, sock, LF_REQLF, RL_BUFSIZE);
206 FD_SET(sock, &readfds);
208 if (select(sock + 1, &readfds, NULL, NULL, NULL)) < 0) {
212 if (FD_ISSET(sock, &readfds))
213 if ((length = lineRead(rl)) == 0) \* EOF *\
217 write(1, rl->rl_Line, length); \* stdout. write() for *\
218 \* speed demonstration *\
219 else { \* length == -1 *\
220 if (rl->rl_Line == NULL); {
225 fprintf(stderr, "lineread input buffer overflow!\n");
226 write(1, rl->rl_Line, RL_BUFSIZE);
230 } while ((length = lineRead(rl)) != 0); \* 0 -> do select() *\
232 FreeMem(rl, sizeof (*rl);
235 fprintf("AllocMem: Out Of memory\n");
239 The source modules lineread.c and lineread.h should compile
240 in UNIX machines as is.
243 charRead(), bsdsocket.library/recv()
245 ******************************************************************************
248 #include "lineread.h"
251 extern struct Library
* SocketBase
;
252 #define READ(a, b, c) recv(a, b, c, 0)
253 #include <proto/socket.h>
254 #else /* not AMIGA */
255 #define READ(a, b, c) read(a, b, c)
271 #if defined (__STDC__) || defined (__cplusplus)
272 #define __CONCAT(x,y) x ## y
274 #define __CONCAT(x,y) x/**/y
276 #endif /* __CONCAT not defined */
278 #define RLP(field) __CONCAT(rl->rl_Private.rlp_,field)
281 #if defined (__STDC__) || defined (__cplusplus)
283 int lineRead(struct LineRead
* rl
)
288 struct LineRead
* rl
;
294 if (RLP(Bufpointer
) == RLP(Howlong
))
298 if (RLP(Line_completed
))
299 RLP(Startp
) = RLP(Bufpointer
) = 0;
301 if ((i
= READ(rl
->rl_Fd
,
302 RLP(Buffer
) + RLP(Bufpointer
),
303 RLP(Buffersize
) - RLP(Bufpointer
))) <= 0) {
305 * here if end-of-file or on error. set Howlong == Bufpointer
306 * so if non-blocking I/O is in use next call will go to READ()
308 RLP(Howlong
) = RLP(Bufpointer
);
313 RLP(Howlong
) = RLP(Bufpointer
) + i
;
315 else /* Inform user that next call may block (unless select()ed) */
317 RLP(Selected
) = TRUE
;
320 else /* Bufpointer has not reached Howlong yet. */
322 RLP(Buffer
)[RLP(Bufpointer
)] = RLP(Saved
);
323 RLP(Startp
) = RLP(Bufpointer
);
327 * Scan read string for next newline.
329 while (RLP(Bufpointer
) < RLP(Howlong
))
330 if (RLP(Buffer
)[RLP(Bufpointer
)++] == '\n')
334 * Here if Bufpointer == Howlong.
336 if (rl
->rl_Lftype
!= RL_LFNOTREQ
) {
337 RLP(Selected
) = TRUE
;
339 if (RLP(Bufpointer
) == RLP(Buffersize
)) {
341 * Here if Bufpointer reaches end-of-buffer.
343 if (RLP(Startp
) == 0) { /* (buffer too short for whole string) */
344 RLP(Line_completed
) = TRUE
;
345 rl
->rl_Line
= RLP(Buffer
);
346 RLP(Buffer
)[RLP(Bufpointer
)] = '\0';
350 * Copy partial string to start-of-buffer and make control ready for
351 * filling rest of buffer when next call to lineRead() is made
352 * (perhaps after select()).
354 for (i
= 0; i
< RLP(Buffersize
) - RLP(Startp
); i
++)
355 RLP(Buffer
)[i
] = RLP(Buffer
)[RLP(Startp
) + i
];
356 RLP(Howlong
)-= RLP(Startp
);
357 RLP(Bufpointer
) = RLP(Howlong
);
361 RLP(Line_completed
) = FALSE
;
366 RLP(Line_completed
) = TRUE
;
367 if (rl
->rl_Lftype
== RL_LFREQNUL
)
368 RLP(Buffer
)[RLP(Bufpointer
) - 1] = '\0';
369 RLP(Saved
) = RLP(Buffer
)[RLP(Bufpointer
)];
370 RLP(Buffer
)[RLP(Bufpointer
)] = '\0';
371 RLP(Selected
) = FALSE
;
372 rl
->rl_Line
= RLP(Buffer
) + RLP(Startp
);
374 return (RLP(Bufpointer
) - RLP(Startp
));
379 #if defined (__STDC__) || defined (__cplusplus)
381 void initLineRead(struct LineRead
* rl
, int fd
, int lftype
, int buffersize
)
385 int initLineRead(rl
, fd
, lftype
, buffersize
)
386 struct LineRead
* rl
;
394 rl
->rl_Lftype
= lftype
;
396 RLP(Bufpointer
) = RLP(Howlong
) = 0;
397 RLP(Selected
) = RLP(Line_completed
) = TRUE
;
399 RLP(Buffersize
) = buffersize
;