mirror of /home/gitosis/repositories/libowfat.git
parent
58bf3e91a3
commit
bb3243fbe2
20 changed files with 376 additions and 6 deletions
@ -0,0 +1,92 @@ |
||||
.TH array 3 |
||||
.SH NAME |
||||
array \- The array library interface |
||||
.SH SYNTAX |
||||
.B #include <array.h> |
||||
|
||||
.SH DESCRIPTION |
||||
An \fBallocated\fR array variable keeps track of |
||||
|
||||
.sp 1 |
||||
.IP \(bu |
||||
a (nonzero) pointer to a dynamically allocated region of memory; |
||||
.IP \(bu |
||||
the number of bytes allocated (always positive); and |
||||
.IP \(bu |
||||
the number of bytes initialized (between 0 and the number of bytes |
||||
allocated). |
||||
.PP |
||||
|
||||
There are two other possibilities for the state of an array variable: |
||||
\fBunallocated\fR and \fIfailed\fR. In both cases, there is no |
||||
dynamically allocated region of memory. |
||||
|
||||
A new array variable is normally created as a static variable: |
||||
|
||||
#include "array.h" |
||||
|
||||
static array x; |
||||
|
||||
At this point it is unallocated. The array library provides various |
||||
allocation and inspection functions. |
||||
|
||||
A new array variable can also be created dynamically. It must be |
||||
initialized to all-0, meaning unallocated, before it is given to any of |
||||
the array functions. It must be returned to the unallocated (or failed) |
||||
state, for example with array_reset, before it is destroyed. These rules |
||||
prevent all memory leaks. |
||||
.SH "Expansion and inspection" |
||||
|
||||
array x; |
||||
|
||||
t* p1 = array_allocate(&x,sizeof(t),pos); |
||||
|
||||
t* p2 = array_get(&x,sizeof(t),pos); |
||||
|
||||
t* p3 = array_start(&x); |
||||
|
||||
int64 len = array_length(&x,sizeof(t)); |
||||
|
||||
int64 bytes = array_bytes(&x); |
||||
|
||||
.SH "Truncation and deallocation" |
||||
|
||||
array x; |
||||
|
||||
array_truncate(&x,sizeof(t),len); |
||||
|
||||
array_trunc(&x); |
||||
|
||||
array_reset(&x); |
||||
|
||||
array_fail(&x); |
||||
|
||||
.SH "Comparison" |
||||
|
||||
array x; |
||||
array y; |
||||
|
||||
if (array_equal(&x,&y)) |
||||
/* arrays are equal... */ |
||||
|
||||
.SH "Concatenation" |
||||
|
||||
array x; |
||||
array y; |
||||
|
||||
array_cat(&x,&y); |
||||
|
||||
array_catb(&x,"fnord",5); |
||||
|
||||
array_cats(&x,"fnord"); |
||||
|
||||
array_cats0(&x,"fnord"); /* also append the \\0 */ |
||||
|
||||
array_cat0(&x); /* append \\0 */ |
||||
|
||||
array_cate(&x,"fnord",1,4); /* append "nor" */ |
||||
|
||||
.SH "ORIGINAL API DEFINITION" |
||||
http://cr.yp.to/lib/array.html |
||||
.SH "SEE ALSO" |
||||
array_get(3), array_start(3), array_fail(3) |
@ -0,0 +1,8 @@ |
||||
#include <unistd.h> |
||||
#include "io_internal.h" |
||||
|
||||
void io_close(int64 d) { |
||||
close(d); |
||||
io_entry* e=array_get(&io_fds,sizeof(io_entry),d); |
||||
if (e) e->inuse=0; |
||||
} |
@ -0,0 +1,8 @@ |
||||
#include <unistd.h> |
||||
#include <fcntl.h> |
||||
#include <errno.h> |
||||
#include "io_internal.h" |
||||
|
||||
void io_closeonexec(int64 d) { |
||||
fcntl(d,F_SETFL,fcntl(d,F_GETFL,0) | FD_CLOEXEC); |
||||
} |
@ -0,0 +1,15 @@ |
||||
#include <unistd.h> |
||||
#include <fcntl.h> |
||||
#include "io_internal.h" |
||||
|
||||
int io_createfile(int64* d,const char* s) { |
||||
long fd=open(s,O_WRONLY|O_CREAT|O_TRUNC,0600); |
||||
if (fd != -1) { |
||||
if (io_fd(fd)) { |
||||
*d=fd; |
||||
return 1; |
||||
} |
||||
close(fd); |
||||
} |
||||
return 0; |
||||
} |
@ -0,0 +1,11 @@ |
||||
#include <unistd.h> |
||||
#include <fcntl.h> |
||||
#include <errno.h> |
||||
#include "io_internal.h" |
||||
|
||||
void io_dontwantread(int64 d) { |
||||
io_entry* e=array_get(&io_fds,sizeof(io_entry),d); |
||||
if (!e) return; |
||||
if (e->wantread && !e->wantwrite) --io_wanted_fds; |
||||
e->wantread=0; |
||||
} |
@ -0,0 +1,11 @@ |
||||
#include <unistd.h> |
||||
#include <fcntl.h> |
||||
#include <errno.h> |
||||
#include "io_internal.h" |
||||
|
||||
void io_dontwantwrite(int64 d) { |
||||
io_entry* e=array_get(&io_fds,sizeof(io_entry),d); |
||||
if (!e) return; |
||||
if (!e->wantread && e->wantwrite) --io_wanted_fds; |
||||
e->wantwrite=0; |
||||
} |
@ -0,0 +1,16 @@ |
||||
#include <sys/types.h> |
||||
#include <fcntl.h> |
||||
|
||||
#include "io_internal.h" |
||||
|
||||
/* put d on internal data structure, return 1 on success, 0 on error */ |
||||
int io_fd(int64 d) { |
||||
long r; |
||||
io_entry* e; |
||||
if ((r=fcntl(d,F_GETFL,0) & O_NDELAY) == -1) |
||||
return 0; /* file descriptor not open */ |
||||
if (!(e=array_allocate(&io_fds,sizeof(io_entry),d))) return 0; |
||||
e->inuse=1; |
||||
if (r&O_NDELAY) e->nonblock=1; |
||||
return 1; |
||||
} |
@ -0,0 +1,11 @@ |
||||
#include <unistd.h> |
||||
#include <fcntl.h> |
||||
#include <errno.h> |
||||
#include "io_internal.h" |
||||
|
||||
void io_nonblock(int64 d) { |
||||
io_entry* e=array_get(&io_fds,sizeof(io_entry),d); |
||||
if (e && e->nonblock) return; |
||||
fcntl(d,F_SETFL,fcntl(d,F_GETFL,0) | O_NDELAY); |
||||
if (e) e->nonblock=1; |
||||
} |
@ -0,0 +1,18 @@ |
||||
#include <unistd.h> |
||||
#include "io_internal.h" |
||||
|
||||
int io_pipe(int64* d) { |
||||
int fds[2]; |
||||
if (pipe(fds)==-1) |
||||
return 0; |
||||
if (io_fd(fds[1])) { |
||||
if (io_fd(fds[0])) { |
||||
d[0]=fds[0]; |
||||
d[1]=fds[1]; |
||||
return 1; |
||||
} |
||||
io_close(fds[1]); |
||||
} |
||||
close(fds[0]); |
||||
return 0; |
||||
} |
@ -0,0 +1,15 @@ |
||||
#include <unistd.h> |
||||
#include <fcntl.h> |
||||
#include "io_internal.h" |
||||
|
||||
int io_readfile(int64* d,const char* s) { |
||||
long fd=open(s,O_RDONLY); |
||||
if (fd != -1) { |
||||
if (io_fd(fd)) { |
||||
*d=fd; |
||||
return 1; |
||||
} |
||||
close(fd); |
||||
} |
||||
return 0; |
||||
} |
@ -0,0 +1,41 @@ |
||||
#include <unistd.h> |
||||
#include <sys/time.h> |
||||
#include <poll.h> |
||||
#include <errno.h> |
||||
#include "io_internal.h" |
||||
|
||||
int64 io_tryread(int64 d,char* buf,int64 len) { |
||||
long r; |
||||
struct itimerval old,new; |
||||
struct pollfd p; |
||||
io_entry* e=array_get(&io_fds,sizeof(io_entry),d); |
||||
if (!e) { errno=EBADF; return -3; } |
||||
if (!e->nonblock) { |
||||
p.fd=d; |
||||
if (p.fd != d) { errno=EBADF; return -3; } /* catch overflow */ |
||||
p.events=POLLIN; |
||||
switch (poll(&p,1,0)) { |
||||
case -1: return -3; |
||||
case 0: errno=EAGAIN; return -1; |
||||
} |
||||
new.it_interval.tv_usec=0; |
||||
new.it_interval.tv_sec=0; |
||||
new.it_value.tv_usec=10000; |
||||
new.it_value.tv_sec=0; |
||||
setitimer(ITIMER_REAL,&new,&old); |
||||
} |
||||
r=read(d,buf,len); |
||||
if (!e->nonblock) { |
||||
new.it_interval.tv_usec=0; |
||||
new.it_interval.tv_sec=0; |
||||
new.it_value.tv_usec=0; |
||||
new.it_value.tv_sec=0; |
||||
setitimer(ITIMER_REAL,&new,&old); |
||||
} |
||||
if (r==-1) { |
||||
if (errno==EINTR) errno=EAGAIN; |
||||
if (errno!=EAGAIN) |
||||
r=-3; |
||||
} |
||||
return r; |
||||
} |
@ -0,0 +1,39 @@ |
||||
#include <unistd.h> |
||||
#include <sys/time.h> |
||||
#include <poll.h> |
||||
#include <errno.h> |
||||
#include "io_internal.h" |
||||
|
||||
int64 io_trywrite(int64 d,const char* buf,int64 len) { |
||||
long r; |
||||
struct itimerval old,new; |
||||
struct pollfd p; |
||||
io_entry* e=array_get(&io_fds,sizeof(io_entry),d); |
||||
if (!e) { errno=EBADF; return -3; } |
||||
if (!e->nonblock) { |
||||
p.fd=d; |
||||
if (p.fd != d) { errno=EBADF; return -3; } /* catch overflow */ |
||||
p.events=POLLOUT; |
||||
switch (poll(&p,1,0)) { |
||||
case -1: return -3; |
||||
case 0: errno=EAGAIN; return -1; |
||||
} |
||||
new.it_interval.tv_usec=0; |
||||
new.it_interval.tv_sec=0; |
||||
new.it_value.tv_usec=10000; |
||||
new.it_value.tv_sec=0; |
||||
setitimer(ITIMER_REAL,&new,&old); |
||||
} |
||||
r=write(d,buf,len); |
||||
if (!e->nonblock) { |
||||
new.it_interval.tv_usec=0; |
||||
new.it_interval.tv_sec=0; |
||||
new.it_value.tv_usec=0; |
||||
new.it_value.tv_sec=0; |
||||
setitimer(ITIMER_REAL,&new,&old); |
||||
} |
||||
if (r==-1) |
||||
if (errno!=EAGAIN) |
||||
r=-3; |
||||
return r; |
||||
} |
@ -0,0 +1,34 @@ |
||||
#include <unistd.h> |
||||
#include <sys/time.h> |
||||
#include <poll.h> |
||||
#include <errno.h> |
||||
#include "io_internal.h" |
||||
|
||||
void io_wait() { |
||||
struct pollfd* p; |
||||
long i,r; |
||||
if (!io_wanted_fds) return; |
||||
for (i=r=0; i<array_length(&io_fds,sizeof(io_entry)); ++i) { |
||||
io_entry* e=array_get(&io_fds,sizeof(io_entry),i); |
||||
if (!e) return; |
||||
e->canread=e->canwrite=0; |
||||
if (e->wantread || e->wantwrite) { |
||||
struct pollfd* p; |
||||
if ((p=array_allocate(&io_pollfds,sizeof(struct pollfd),r))) { |
||||
p->fd=i; |
||||
p->events=(e->wantread?POLLIN:0) + (e->wantwrite?POLLOUT:0); |
||||
++r; |
||||
} else |
||||
return; |
||||
} |
||||
} |
||||
p=array_start(&io_pollfds); |
||||
while ((i=poll(array_start(&io_pollfds),r,99999999))==0); |
||||
if (i==-1) return; |
||||
for (i=0; i<r; ++i) { |
||||
io_entry* e=array_get(&io_fds,sizeof(io_entry),p->fd); |
||||
if (p->revents&POLLIN) e->canread=1; |
||||
if (p->revents&POLLOUT) e->canwrite=1; |
||||
p++; |
||||
} |
||||
} |
@ -0,0 +1,11 @@ |
||||
#include <unistd.h> |
||||
#include <fcntl.h> |
||||
#include <errno.h> |
||||
#include "io_internal.h" |
||||
|
||||
void io_wantread(int64 d) { |
||||
io_entry* e=array_get(&io_fds,sizeof(io_entry),d); |
||||
if (!e) return; |
||||
if (!e->wantread && !e->wantwrite) ++io_wanted_fds; |
||||
e->wantread=1; |
||||
} |
@ -0,0 +1,11 @@ |
||||
#include <unistd.h> |
||||
#include <fcntl.h> |
||||
#include <errno.h> |
||||
#include "io_internal.h" |
||||
|
||||
void io_wantwrite(int64 d) { |
||||
io_entry* e=array_get(&io_fds,sizeof(io_entry),d); |
||||
if (!e) return; |
||||
if (!e->wantread && !e->wantwrite) ++io_wanted_fds; |
||||
e->wantwrite=1; |
||||
} |
@ -0,0 +1,15 @@ |
||||
#include "io.h" |
||||
#include "array.h" |
||||
|
||||
typedef struct { |
||||
unsigned int wantread:1; |
||||
unsigned int wantwrite:1; |
||||
unsigned int canread:1; |
||||
unsigned int canwrite:1; |
||||
unsigned int nonblock:1; |
||||
unsigned int inuse:1; |
||||
} io_entry; |
||||
|
||||
array io_fds; |
||||
uint64 io_wanted_fds; |
||||
array io_pollfds; |
Loading…
Reference in new issue