better and more predication, improved documentation

master
leitner 22 years ago
parent b36f12a121
commit 558c6128fe

@ -20,6 +20,7 @@
scan_ushort scan_ushort
extended socket API; you can now pass NULL for results you don't want extended socket API; you can now pass NULL for results you don't want
rename Makefile to GNUmakefile; create Makefile target rename Makefile to GNUmakefile; create Makefile target
add buffer_get_token_pred and buffer_get_token_sa_pred
0.14: 0.14:
avoid bus errors in byte_copy avoid bus errors in byte_copy

@ -46,6 +46,13 @@ extern int buffer_getn(buffer* b,char* x,unsigned int len);
extern int buffer_get_token(buffer* b,char* x,unsigned int len,const char* charset,unsigned int setlen); extern int buffer_get_token(buffer* b,char* x,unsigned int len,const char* charset,unsigned int setlen);
#define buffer_getline(b,x,len) buffer_get_token((b),(x),(len),"\n",1) #define buffer_getline(b,x,len) buffer_get_token((b),(x),(len),"\n",1)
/* this predicate is given the string as currently read from the buffer
* and is supposed to return 1 if the token is complete, 0 if not. */
typedef int (*string_predicate)(const char* x,unsigned int len);
/* like buffer_get_token but the token ends when your predicate says so */
extern int buffer_get_token_pred(buffer* b,char* x,unsigned int len,string_predicate p);
extern char *buffer_peek(buffer* b); extern char *buffer_peek(buffer* b);
extern void buffer_seek(buffer* b,unsigned int len); extern void buffer_seek(buffer* b,unsigned int len);
@ -74,10 +81,27 @@ extern buffer *buffer_2;
#ifdef STRALLOC_H #ifdef STRALLOC_H
/* write stralloc to buffer */ /* write stralloc to buffer */
extern int buffer_putsa(buffer* b,stralloc* sa); extern int buffer_putsa(buffer* b,stralloc* sa);
/* these "read token" functions return 0 if the token was complete or
* EOF was hit or -1 on error. In contrast to the non-stralloc token
* functions, the separator is also put in the stralloc; use
* stralloc_chop or stralloc_chomp to get rid of it. */
/* WARNING! These token reading functions will not clear the stralloc!
* They _append_ the token to the contents of the stralloc. The idea is
* that this way these functions can be used on non-blocking sockets;
* when you get signalled EAGAIN, just call the functions again when new
* data is available. */
/* read token from buffer to stralloc */ /* read token from buffer to stralloc */
extern int buffer_get_token_sa(buffer* b,stralloc* sa,const char* charset,unsigned int setlen); extern int buffer_get_token_sa(buffer* b,stralloc* sa,const char* charset,unsigned int setlen);
/* read line from buffer to stralloc */ /* read line from buffer to stralloc */
extern int buffer_getline_sa(buffer* b,stralloc* sa); extern int buffer_getline_sa(buffer* b,stralloc* sa);
typedef int (*sa_predicate)(stralloc* sa);
/* like buffer_get_token_sa but the token ends when your predicate says so */
extern int buffer_get_token_sa_pred(buffer* b,stralloc* sa,sa_predicate p);
#endif #endif
#endif #endif

@ -7,21 +7,10 @@ buffer_get_token \- read token from buffer
int \fBbuffer_get_token\fP(buffer* \fIb\fR,char* \fIx\fR,unsigned int \fIlen\fR, int \fBbuffer_get_token\fP(buffer* \fIb\fR,char* \fIx\fR,unsigned int \fIlen\fR,
const char* \fIcharset\fR,unsigned int \fIsetlen\fR); const char* \fIcharset\fR,unsigned int \fIsetlen\fR);
.SH DESCRIPTION .SH DESCRIPTION
Normally buffer_get_token copies data to \fIx\fR[0], \fIx\fR[1], ..., buffer_get_token copies data from \fIb\fR to \fIx\fR[0], \fIx\fR[1], ...,
\fIx\fR[\fIlen\fR-1] from the beginning of a string stored in \fIx\fR[\fIlen\fR-1] until \fIlen\fR bytes have been copied or one of
preallocated space; removes these \fIlen\fR bytes from the string; and \fIcharset\fR[0], \fIcharset\fR[1], ..., \fIcharset\fR[\fIsetlen\fR]
returns \fIlen\fR. equals the last byte that was read. buffer_get_token returns the number
of bytes read or -1 on error (setting \fIerrno\fR appropriately).
If, however, the string has fewer than \fIlen\fR (but more than 0)
bytes, buffer_get_token copies only that many bytes, and returns that number.
If the string is empty, buffer_get_token first uses a \fBread operation\fR to
feed data into the string. The \fBread operation\fR may indicate end of
input, in which case buffer_get_token returns 0; or a read error, in which
case buffer_get_token returns -1, setting \fIerrno\fR approporiately.
The preallocated space and the \fBread operation\fR are specified by
\fIb\fR. You must initialize \fBb\fR using buffer_init before calling
buffer_get_token (or use the pre-initialized buffer_0).
.SH "SEE ALSO" .SH "SEE ALSO"
buffer_init(3), buffer_feed(3), buffer_peek(3), buffer_seek(3), buffer(3) buffer_init(3), buffer_feed(3), buffer_peek(3), buffer_seek(3), buffer(3)

@ -0,0 +1,23 @@
.TH buffer_get_token_pred 3
.SH NAME
buffer_get_token_pred \- read token from buffer
.SH SYNTAX
.B #include <buffer.h>
int \fBbuffer_get_token_pred\fP(buffer* \fIb\fR,char* \fIx\fR,unsigned int \fIlen\fR,
int (*\fIpredicate\fR)(const char* \fIs\fR,unsigned int \fIlen\fR));
.SH DESCRIPTION
buffer_get_token_pred copies data from \fIb\fR to \fIx\fR[0],
\fIx\fR[1], ..., \fIx\fR[\fIlen\fR-1] until \fIlen\fR bytes have been
read or \fIpredicate\fR called on the destination string returns
nonzero.
\fIpredicate\fR can also return 0 (indicating further input is required
to complete the token) or -1 (abort and return -1; use this if
\fIpredicate\fR wants to enfore a maximum message size or does timeout
handling or detects a malformed message).
buffer_get_token_pred returns the number of bytes copied or -1 on
\fIerrno\fR (setting errno appropriately).
.SH "SEE ALSO"
buffer_init(3), buffer_feed(3), buffer_peek(3), buffer_seek(3), buffer(3)

@ -0,0 +1,16 @@
#include "byte.h"
#include "buffer.h"
#include "scan.h"
int buffer_get_token_pred(buffer* b,char* x,unsigned int len,string_predicate p) {
int blen;
for (blen=0;blen<len;++blen) {
register int r;
if ((r=buffer_getc(b,x))<0) return r;
if (r==0) break;
if (p(x-blen,blen+1)) break;
++x;
}
return blen;
}

@ -9,15 +9,20 @@ buffer_get_token_sa \- read token from buffer
int \fBbuffer_get_token_sa\fP(buffer* \fIb\fR,stralloc* \fIsa\fR, int \fBbuffer_get_token_sa\fP(buffer* \fIb\fR,stralloc* \fIsa\fR,
const char* \fIcharset\fR,unsigned int \fIsetlen\fR); const char* \fIcharset\fR,unsigned int \fIsetlen\fR);
.SH DESCRIPTION .SH DESCRIPTION
buffer_get_token_sa copies data from the \fIb\fR to \fIsa\fR until one buffer_get_token_sa appends data from the \fIb\fR to \fIsa\fR until one
of the delimiters in \fIcharset\fR is found, overwriting the previous of the delimiters in \fIcharset\fR is found, NOT overwriting the
content of \fIsa\fR. That delimiter is also appended to \fIsa\fR. previous content of \fIsa\fR. That delimiter is also appended to
\fIsa\fR.
If reading from the buffer or allocating memory fails, If reading from the buffer or allocating memory fails,
buffer_get_token_sa returns -1 and sets \fIerrno\fR appropriately. At buffer_get_token_sa returns -1 and sets \fIerrno\fR appropriately. At
that point \fIsa\fR may be empty or it may already contain a partial that point \fIsa\fR may already contain a partial token.
token.
On success, buffer_get_token_sa returns 0. On success, buffer_get_token_sa returns 0.
.SH RATIONALE
buffer_get_token_sa appends instead of overwriting so it can be used on
non-blocking sockets (these signal error and set \fIerrno\fR to EAGAIN;
in this case you can simply call buffer_get_token_sa again when
\fBselect\fR or \fBpoll\fR indicate more data is available).
.SH "SEE ALSO" .SH "SEE ALSO"
buffer_getline_sa(3), buffer_get_token(3), buffer(3) buffer_getline_sa(3), buffer_get_token(3), buffer(3)

@ -4,7 +4,6 @@
#include <errno.h> #include <errno.h>
int buffer_get_token_sa(buffer* b,stralloc* sa,const char* charset,unsigned int setlen) { int buffer_get_token_sa(buffer* b,stralloc* sa,const char* charset,unsigned int setlen) {
sa->len=0;
for (;;) { for (;;) {
char x; char x;
if (!stralloc_readyplus(sa,1)) goto nomem; if (!stralloc_readyplus(sa,1)) goto nomem;

@ -0,0 +1,34 @@
.TH buffer_get_token_sa_pred 3
.SH NAME
buffer_get_token_sa_pred \- read token from buffer
.SH SYNTAX
.nf
.B #include <stralloc.h>
.B #include <buffer.h>
int \fBbuffer_get_token_sa_pred\fP(buffer* \fIb\fR,stralloc* \fIsa\fR,
int (*\fIpredicate\fR)(stralloc* * \fIsa\fR));
.SH DESCRIPTION
buffer_get_token_sa_pred appends data from the \fIb\fR to \fIsa\fR until
\fIpredicate\fR(\fIsa\fR) returns 1 or -1.
If \fIpredicate\fR returns 1 once a '\\n' was read, that new-line
character is still appended to \fIsa\fR -- use stralloc_chop or
stralloc_chomp to get rid of it. \fIpredicate\fR can also return 0
(indicating further input is required to complete the token) or -1
(abort and return -1; use this if \fIpredicate\fR wants to enfore a
maximum message size or does timeout handling or detects a malformed
message).
If reading from the buffer or allocating memory fails,
buffer_get_token_sa_pred returns -1 and sets \fIerrno\fR appropriately. At
that point \fIsa\fR may already contain a partial token.
On success, buffer_get_token_sa_pred returns 0.
.SH RATIONALE
buffer_get_token_sa_pred appends instead of overwriting so it can be
used on non-blocking sockets (these signal error and set \fIerrno\fR to
EAGAIN; in this case you can simply call buffer_get_token_sa again when
\fBselect\fR or \fBpoll\fR indicate more data is available).
.SH "SEE ALSO"
buffer_getline_sa(3), buffer_get_token(3), buffer(3)

@ -0,0 +1,21 @@
#include "byte.h"
#include "stralloc.h"
#include "buffer.h"
#include <errno.h>
int buffer_get_token_sa_pred(buffer* b,stralloc* sa,sa_predicate p) {
for (;;) {
char x;
if (!stralloc_readyplus(sa,1)) return -1;
switch (buffer_getc(b,&x)) {
case -1: return -1;
case 0: return 0;
}
stralloc_append(sa,&x);
switch (p(sa)) {
case -1: return -1;
case 0: break;
case 1: return 0;
}
}
}

@ -8,8 +8,8 @@ buffer_getline_sa \- read line from buffer
int \fBbuffer_getline_sa\fP(buffer* \fIb\fR,stralloc* \fIsa\fR); int \fBbuffer_getline_sa\fP(buffer* \fIb\fR,stralloc* \fIsa\fR);
.SH DESCRIPTION .SH DESCRIPTION
buffer_getline_sa copies data from the \fIb\fR to \fIsa\fR until a '\\n' buffer_getline_sa appends data from the \fIb\fR to \fIsa\fR until a '\\n'
is found, overwriting the previous content of \fIsa\fR. The new-line is found, NOT overwriting the previous content of \fIsa\fR. The new-line
is also appended to \fIsa\fR. is also appended to \fIsa\fR.
If reading from the buffer or allocating memory fails, If reading from the buffer or allocating memory fails,
@ -18,5 +18,10 @@ that point \fIsa\fR may be empty or it may already contain a partial
token. token.
On success, buffer_getline_sa returns 0. On success, buffer_getline_sa returns 0.
.SH RATIONALE
buffer_getline_sa appends instead of overwriting so it can be used on
non-blocking sockets (these signal error and set \fIerrno\fR to EAGAIN;
in this case you can simply call buffer_getline_sa again when
\fBselect\fR or \fBpoll\fR indicate more data is available).
.SH "SEE ALSO" .SH "SEE ALSO"
buffer_get_token_sa(3), buffer(3) buffer_get_token_sa(3), buffer(3)

@ -114,10 +114,26 @@ extern int stralloc_chomp(stralloc* sa);
#ifdef BUFFER_H #ifdef BUFFER_H
/* write stralloc to buffer */ /* write stralloc to buffer */
extern int buffer_putsa(buffer* b,stralloc* sa); extern int buffer_putsa(buffer* b,stralloc* sa);
/* these "read token" functions return 0 if the token was complete or
* EOF was hit or -1 on error. In contrast to the non-stralloc token
* functions, the separator is also put in the stralloc; use
* stralloc_chop or stralloc_chomp to get rid of it. */
/* WARNING! These token reading functions will not clear the stralloc!
* They _append_ the token to the contents of the stralloc. The idea is
* that this way these functions can be used on non-blocking sockets;
* when you get signalled EAGAIN, just call the functions again when new
* data is available. */
/* read token from buffer to stralloc */ /* read token from buffer to stralloc */
extern int buffer_get_token_sa(buffer* b,stralloc* sa,const char* charset,unsigned int setlen); extern int buffer_get_token_sa(buffer* b,stralloc* sa,const char* charset,unsigned int setlen);
/* read line from buffer to stralloc */ /* read line from buffer to stralloc */
extern int buffer_getline_sa(buffer* b,stralloc* sa); extern int buffer_getline_sa(buffer* b,stralloc* sa);
typedef int (*sa_predicate)(stralloc* sa);
/* like buffer_get_token_sa but the token ends when your predicate says so */
extern int buffer_get_token_sa_pred(buffer* b,stralloc* sa,sa_predicate p);
#endif #endif
#endif #endif

@ -3,6 +3,8 @@
main() { main() {
static stralloc sa; static stralloc sa;
/* static makes sure sa is initialized and empty;
* use stralloc_init to initialize and stralloc_copys(&sa,"") to empty */
if (buffer_get_token_sa(buffer_0,&sa," \t\n",3)==0) { if (buffer_get_token_sa(buffer_0,&sa," \t\n",3)==0) {
buffer_putsa(buffer_1,&sa); buffer_putsa(buffer_1,&sa);
buffer_putnlflush(buffer_1); buffer_putnlflush(buffer_1);

Loading…
Cancel
Save