mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
This commit fixes various minor typos, punctuation errors and corrects the capitalization of many names.
2373 lines
96 KiB
Groff
2373 lines
96 KiB
Groff
.fp 5 CW
|
|
.TH SFIO 3 "01 June 2008"
|
|
.SH NAME
|
|
\fBsfio\fR \- safe/fast string/file input/output
|
|
.SH SYNOPSIS
|
|
.de Tp
|
|
.fl
|
|
.ne 3
|
|
.TP
|
|
..
|
|
.de Ss
|
|
.fl
|
|
.ne 3
|
|
.SS "\\$1"
|
|
..
|
|
.ta 1.0i 2.0i 3.0i 4.0i 5.0i
|
|
.Ss "LIBRARIES"
|
|
.nf
|
|
.ft 5
|
|
#include <sfio.h>
|
|
|
|
libsfio.a -lsfio
|
|
libstdio.a -lstdio
|
|
libsfio-mt.a -lsfio-mt
|
|
libstdio-mt.a -lstdio-mt
|
|
.ft 1
|
|
.fi
|
|
.Ss "DATA TYPES"
|
|
.nf
|
|
.ft 5
|
|
Void_t;
|
|
Sfoff_t;
|
|
Sflong_t;
|
|
Sfulong_t;
|
|
Sfdouble_t;
|
|
|
|
Sfio_t;
|
|
|
|
Sfdisc_t;
|
|
ssize_t (*Sfread_f)(Sfio_t*, Void_t*, size_t, Sfdisc_t*);
|
|
ssize_t (*Sfwrite_f)(Sfio_t*, const Void_t*, size_t, Sfdisc_t*);
|
|
Sfoff_t (*Sfseek_f)(Sfio_t*, Sfoff_t, int, Sfdisc_t*);
|
|
int (*Sfexcept_f)(Sfio_t*, int, Void_t*, Sfdisc_t*);
|
|
|
|
Sffmt_t;
|
|
int (*Sffmtext_f)(Sfio_t*, Void_t*, Sffmt_t*);
|
|
int (*Sffmtevent_f)(Sfio_t*, int, Void_t*, Sffmt_t*);
|
|
|
|
SFIO_VERSION
|
|
.ft 1
|
|
.fi
|
|
.Ss "BIT FLAGS"
|
|
.nf
|
|
.ft 5
|
|
SF_STRING
|
|
SF_READ
|
|
SF_WRITE
|
|
SF_APPENDWR (SF_APPEND)
|
|
SF_LINE
|
|
SF_SHARE
|
|
SF_PUBLIC
|
|
SF_MALLOC
|
|
SF_STATIC
|
|
SF_IOCHECK
|
|
SF_WHOLE
|
|
SF_MTSAFE
|
|
SF_IOINTR
|
|
.ft 1
|
|
.fi
|
|
.Ss "OPENING/CLOSING STREAMS"
|
|
.nf
|
|
.ft 5
|
|
Sfio_t* sfnew(Sfio_t* f, Void_t* buf, size_t size, int fd, int flags);
|
|
Sfio_t* sfopen(Sfio_t* f, const char* string, const char* mode);
|
|
Sfio_t* sfpopen(Sfio_t* f, const char* cmd, const char* mode);
|
|
Sfio_t* sftmp(size_t size);
|
|
int sfclose(Sfio_t* f);
|
|
|
|
|
|
.ft 1
|
|
.fi
|
|
.Ss "THREAD SAFETY"
|
|
.nf
|
|
.ft 5
|
|
int sfmutex(Sfio_t* f, int type);
|
|
|
|
SFMTX_LOCK
|
|
SFMTX_TRYLOCK
|
|
SFMTX_UNLOCK
|
|
SFMTX_CLRLOCK
|
|
.ft 1
|
|
.fi
|
|
.Ss "INPUT/OUTPUT OPERATIONS"
|
|
.nf
|
|
.ft 5
|
|
int sfgetc(Sfio_t* f);
|
|
int sfputc(Sfio_t* f, int c);
|
|
int sfnputc(Sfio_t* f, int c, int n);
|
|
int sfungetc(Sfio_t* f, int c);
|
|
|
|
Sfulong_t sfgetm(Sfio_t* f, Sfulong_t max);
|
|
int sfputm(Sfio_t* f, Sfulong_t v, Sfulong_t max);
|
|
Sfulong_t sfgetu(Sfio_t* f);
|
|
int sfputu(Sfio_t* f, Sfulong_t v);
|
|
Sflong_t sfgetl(Sfio_t* f);
|
|
int sfputl(Sfio_t* f, Sflong_t v);
|
|
Sfdouble_t sfgetd(Sfio_t* f);
|
|
int sfputd(Sfio_t* f, Sfdouble_t v);
|
|
|
|
char* sfgetr(Sfio_t* f, int rsc, int type);
|
|
ssize_t sfputr(Sfio_t* f, const char* s, int rsc);
|
|
Sfoff_t sfmove(Sfio_t* fr, Sfio_t* fw, Sfoff_t n, int rsc);
|
|
|
|
ssize_t sfread(Sfio_t* f, Void_t* buf, size_t n);
|
|
ssize_t sfwrite(Sfio_t* f, const Void_t* buf, size_t n);
|
|
Sfoff_t sfseek(Sfio_t* f, Sfoff_t offset, int type);
|
|
Void_t* sfreserve(Sfio_t* f, ssize_t n, int type);
|
|
.ft 1
|
|
.fi
|
|
.Ss "DATA FORMATTING"
|
|
.nf
|
|
.ft 5
|
|
int sfscanf(Sfio_t* f, const char* format, ...);
|
|
int sfsscanf(const char* s, const char* format, ...);
|
|
int sfvsscanf(const char* s, const char* format, va_list args);
|
|
int sfvscanf(Sfio_t* f, const char* format, va_list args);
|
|
|
|
int sfprintf(Sfio_t* f, const char* format, ...);
|
|
char* sfprints(const char* format, ...);
|
|
char* sfvprints(const char* format, va_list args);
|
|
ssize_t sfaprints(char** sp, const char* format, ...);
|
|
ssize_t sfvaprints(char** sp, const char* format, va_list args);
|
|
int sfsprintf(char* s, int n, const char* format, ...);
|
|
int sfvsprintf(char* s, int n, const char* format, va_list args);
|
|
int sfvprintf(Sfio_t* f, const char* format, va_list args);
|
|
|
|
Sffmt_t;
|
|
|
|
SFFMT_LEFT
|
|
SFFMT_SIGN
|
|
SFFMT_BLANK
|
|
SFFMT_ZERO
|
|
SFFMT_THOUSAND
|
|
SFFMT_LONG
|
|
SFFMT_LLONG
|
|
SFFMT_SHORT
|
|
SFFMT_LDOUBLE
|
|
SFFMT_IFLAG
|
|
SFFMT_JFLAG
|
|
SFFMT_CENTER
|
|
SFFMT_CHOP
|
|
SFFMT_ALTER
|
|
SFFMT_SKIP
|
|
SFFMT_ARGPOS
|
|
SFFMT_VALUE
|
|
|
|
int (*Sffmtext_f)(Sfio_t* f, Void_t* v, Sffmt_t* fe);
|
|
int (*Sffmtevent_f)(Sfio_t* f, int type, Void_t* v, Sffmt_t* fe);
|
|
void va_copy(va_list to, va_list fr);
|
|
long sffmtversion(Sffmt_t* fe, type);
|
|
.ft 1
|
|
.fi
|
|
.Ss "BUFFERING, SYNCHRONIZATION"
|
|
.nf
|
|
.ft 5
|
|
Void_t* sfsetbuf(Sfio_t* f, Void_t* buf, size_t size);
|
|
int sfsync(Sfio_t* f);
|
|
int sfpoll(Sfio_t** flist, int n, int timeout);
|
|
Sfio_t* sfpool(Sfio_t* f, Sfio_t* poolf, int mode);
|
|
int sfpurge(Sfio_t* f);
|
|
.ft 1
|
|
.fi
|
|
.Ss "DISCIPLINE, EVENT HANDLING"
|
|
.nf
|
|
.ft 5
|
|
Sfdisc_t* sfdisc(Sfio_t* f, Sfdisc_t* disc);
|
|
int sfraise(Sfio_t* f, int type, Void_t* data);
|
|
ssize_t sfrd(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc);
|
|
ssize_t sfwr(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc);
|
|
Sfoff_t sfsk(Sfio_t* f, Sfoff_t offset, int type, Sfdisc_t* disc);
|
|
|
|
SF_NEW
|
|
SF_READ
|
|
SF_WRITE
|
|
SF_SEEK
|
|
SF_CLOSING (SF_CLOSE)
|
|
SF_DPUSH
|
|
SF_DPOP
|
|
SF_DPOLL
|
|
SF_DBUFFER
|
|
SF_SYNC
|
|
SF_PURGE
|
|
SF_FINAL
|
|
SF_READY
|
|
SF_LOCKED
|
|
SF_ATEXIT
|
|
SF_EVENT
|
|
.ft 1
|
|
.fi
|
|
.Ss "STREAM CONTROL"
|
|
.nf
|
|
.ft 5
|
|
int sfresize(Sfio_t* f, Sfoff_t size);
|
|
int sfset(Sfio_t* f, int flags, int i);
|
|
int sfsetfd(Sfio_t* f, int fd);
|
|
Sfio_t* sfstack(Sfio_t* base, Sfio_t* top);
|
|
Sfio_t* sfswap(Sfio_t* f1, Sfio_t* f2);
|
|
.ft 1
|
|
.fi
|
|
.Ss "STREAM INFORMATION"
|
|
.nf
|
|
.ft 5
|
|
Sfoff_t sfsize(Sfio_t* f);
|
|
Sfoff_t sftell(Sfio_t* f);
|
|
ssize_t sfvalue(Sfio_t* f);
|
|
int sffileno(Sfio_t* f);
|
|
|
|
int sfstacked(Sfio_t* f);
|
|
int sfeof(Sfio_t* f);
|
|
int sferror(Sfio_t* f);
|
|
int sfclrerr(Sfio_t* f);
|
|
int sfclrlock(Sfio_t* f);
|
|
|
|
int sfnotify(void (*notify)(Sfio_t* f, int type, Void_t* data));
|
|
|
|
int sfwalk(Sfwalk_f walkf, Void_t* data, int type);
|
|
.ft 1
|
|
.fi
|
|
.Ss "MISCELLANEOUS FUNCTIONS"
|
|
.nf
|
|
.ft 5
|
|
ssize_t sfmaxr(ssize_t maxr, int s);
|
|
ssize_t sfslen();
|
|
int sfulen(Sfulong_t v);
|
|
int sfllen(Sflong_t v);
|
|
int sfdlen(Sfdouble_t v);
|
|
ssize_t sfpkrd(int fd, Void_t* buf, size_t n,
|
|
int rsc, long tm, int action);
|
|
.ft 1
|
|
.fi
|
|
.Ss "FULL STRUCTURE SFIO_T"
|
|
.nf
|
|
.ft 5
|
|
#include <sfio_t.h>
|
|
#define SFNEW(buf,size,file,flags,disc)
|
|
.ft 1
|
|
.fi
|
|
.Ss "EXAMPLE DISCIPLINES"
|
|
.nf
|
|
.ft 5
|
|
#include <sfdisc.h>
|
|
|
|
int sfdcdio(Sfio_t* f, size_t bufsize);
|
|
int sfdcdos(Sfio_t* f);
|
|
int sfdcfilter(Sfio_t* f, const char* cmd);
|
|
int sfdcseekable(Sfio_t* f);
|
|
int sfdcslow(Sfio_t* f);
|
|
int sfdcsubstream(Sfio_t* f, Sfio_t* parent,
|
|
Sfoff_t offset, Sfoff_t extent);
|
|
int sfdctee(Sfio_t* f, Sfio_t* tee);
|
|
int sfdcunion(Sfio_t* f, Sfio_t** array, int n);
|
|
int sfdclzw(Sfio_t* f);
|
|
int sfdcgzip(Sfio_t* f, int flags);
|
|
.ft 1
|
|
.fi
|
|
.Ss "STDIO-COMPATIBILITY"
|
|
.nf
|
|
.ft 5
|
|
#include <stdio.h>
|
|
cc ... -lstdio -lsfio
|
|
cc ... -lstdio-mt -lsfio-mt
|
|
.ft 1
|
|
.fi
|
|
.SH DESCRIPTION
|
|
.PP
|
|
Sfio provides I/O functions to manage buffered streams.
|
|
Each Sfio stream is a \fIfile stream\fP, representing a file (see \f3open(2)\fP),
|
|
or a \fIstring stream\fP, representing a memory segment.
|
|
Beyond the usual I/O operations on streams,
|
|
Sfio provides I/O disciplines for extended data processing,
|
|
stream stacks for recursive stream processing, and
|
|
stream pools for automatic data synchronization.
|
|
Applications can extend the \f3sfprintf()/sfscanf()\fP functions
|
|
to define their own conversion patterns as well as redefine existing ones.
|
|
.PP
|
|
A discipline defines analogues of
|
|
the system calls \f3read(2), write(2)\fP and \f3lseek(2)\fP.
|
|
Such system calls or their discipline replacements are used to process stream data.
|
|
Henceforth, ``\fIsystem call\fP'' will refer to either a system call
|
|
or its discipline replacement.
|
|
.PP
|
|
A system call is said to cause an exception if its return value is non-positive.
|
|
Unless overridden by exception handlers (see \f3sfdisc()\fP),
|
|
an interrupted system call (\f3errno == EINTR\fP on UNIX systems)
|
|
will be automatically reinvoked to continue the ongoing operation.
|
|
.PP
|
|
The buffer of a stream is typically a memory segment allocated via \f3malloc(3)\fP
|
|
or supplied by the application.
|
|
File streams may also use memory mapping (\f3mmap(2)\fP) if that is more efficient.
|
|
When memory mapping is used,
|
|
the underlying file should not be truncated while the stream is active.
|
|
Memory mapping can be turned off using \f3sfsetbuf()\fP.
|
|
.PP
|
|
There are three \fIstandard streams\fP:
|
|
\f3sfstdin\fP for input (file descriptor \f30\fP on UNIX systems),
|
|
\f3sfstdout\fP for normal output (file descriptor \f31\fP), and
|
|
\f3sfstderr\fP for error output (file descriptor \f32\fP).
|
|
|
|
.PP
|
|
.Ss "LIBRARIES"
|
|
.PP
|
|
This version of Sfio can be built and used for both single-threaded and multi-threaded
|
|
environments. In the former case, streams are not protected from
|
|
simultaneous accesses by different threads. In the latter case, a stream
|
|
is typically locked with a mutex during access so that another thread
|
|
trying to access the same stream will block until the mutex is released.
|
|
|
|
A program that does not use multiple threads can link with \fBlibsfio.a\fP
|
|
while a program that uses multiple threads should link with \fBlibsfio-mt.a\fP.
|
|
The libraries \fBlibstdio.a\fP and \fBlibstdio-mt.a\fP provide
|
|
corresponding Stdio functions to link with code already compiled using the
|
|
native header \fBstdio.h\fP instead of the one provided by Sfio.
|
|
|
|
.PP
|
|
.Ss "DATA TYPES"
|
|
.PP
|
|
.Ss " Void_t*"
|
|
This defines a type suitable to exchange
|
|
data of unknown types between application and Sfio.
|
|
\f3Void_t\fP is a macro defined as \f3void\fP for ANSI C and C++ and
|
|
\f3char\fP for other compilation environments.
|
|
.PP
|
|
.Ss " Sfoff_t"
|
|
This defines an integral type suitable to address
|
|
the largest possible file extent.
|
|
.PP
|
|
.Ss " Sfulong_t, Sflong_t, Sfdouble_t"
|
|
These are respectively the largest
|
|
unsigned integer, signed integer, and floating point value types on the local platform.
|
|
.PP
|
|
.Ss " Sfio_t"
|
|
This defines the type of a stream handle.
|
|
.PP
|
|
.Ss " Sfdisc_t"
|
|
.Ss " ssize_t (*Sfread_f)(Sfio_t*, Void_t*, size_t, Sfdisc_t*)"
|
|
.Ss " ssize_t (*Sfwrite_f)(Sfio_t*, const Void_t*, size_t, Sfdisc_t*)"
|
|
.Ss " Sfoff_t (*Sfseek_f)(Sfio_t*, Sfoff_t, int, Sfdisc_t*)"
|
|
.Ss " int (*Sfexcept_f)(Sfio_t*, int, Void_t*, Sfdisc_t*)"
|
|
\f3Sfdisc_t\fP defines a stream discipline structure.
|
|
\f3Sfread_f\fP, \f3Sfwrite_f\fP and \f3Sfseek_f\fP are the types
|
|
of discipline functions to replace the system calls:
|
|
\f3read(2)\fP, \f3write(2)\fP and \f3lseek(2)\fP.
|
|
\f3Sfexcept_f\fP is the type of an event-handling function.
|
|
See \f3sfdisc()\fP for more details.
|
|
.PP
|
|
.Ss " Sffmt_t"
|
|
.Ss " int (*Sffmtext_f)(Sfio_t*, Void_t*, Sffmt_t*)"
|
|
.Ss " int (*Sffmtevent_f)(Sfio_t*, int, Void_t*, Sffmt_t*)"
|
|
\f3Sffmt_t\fP defines a formatting environment that can be used
|
|
to extend scanning and printing in the \f3sfprint()/sfscanf()\fP
|
|
functions. \f3Sffmtext_f\fP and \f3Sffmtevent_f\fP define the types
|
|
of extension functions definable in \f3Sffmt_t\fP.
|
|
See \f3Sffmt_t\fP below for more details.
|
|
.PP
|
|
.Ss " SFIO_VERSION"
|
|
This is a macro value of type \f3long int\fP that defines
|
|
the current version number of Sfio. For example, the Sfio2000's
|
|
version number is \f320000515L\fP
|
|
(which also indicates its latest version date: 05/15/2000).
|
|
|
|
.Ss "BIT FLAGS"
|
|
A number of bit flags control stream operations.
|
|
They are set either at stream initialization or by calling \f3sfset()\fP.
|
|
Following are the flags:
|
|
.Tp
|
|
\f3SF_STRING\fP:
|
|
The stream is memory-based.
|
|
.Tp
|
|
\f3SF_READ\fP, \f3SF_WRITE\fP, \f3SF_APPENDWR\fP (\f3SF_APPEND\fP):
|
|
Flags \f3SF_READ\fP and \f3SF_WRITE\fP indicate readability and writability.
|
|
Flag \f3SF_APPENDWR\fP asserts that the stream is a file opened in append mode
|
|
(see \f3open(2)\fP and \f3fcntl(2)\fP)
|
|
so that data is always output at the end of file.
|
|
On systems without direct support for append mode,
|
|
Sfio uses \f3lseek(2)\fP or its discipline replacement
|
|
to approximate this behavior.
|
|
.Tp
|
|
\f3SF_LINE\fP:
|
|
The stream is line-oriented.
|
|
For a \f3SF_WRITE\fP stream,
|
|
this means that buffered data is flushed
|
|
whenever a new-line character, \f3\en\fP, is output.
|
|
For a \f3SF_READ\fP stream, \f3SF_LINE\fP is only
|
|
significant during calls to functions in the \f3sfscanf()\fP family.
|
|
\f3SF_LINE\fP is set on initialization of
|
|
any stream representing a terminal device.
|
|
.Tp
|
|
\f3SF_SHARE\fP, \f3SF_PUBLIC\fP:
|
|
Flag \f3SF_SHARE\fP means that the underlying file descriptor
|
|
is shared by independent entities (for example, multiple processes).
|
|
|
|
For a seekable file stream, \f3SF_SHARE\fP means that
|
|
the logical stream and the physical file positions will be made the same
|
|
before a system call to perform physical I/O.
|
|
There are different possibilities.
|
|
If \f3SF_PUBLIC\fP is not set,
|
|
the physical file position is made equal to the logical stream position.
|
|
If \f3SF_PUBLIC\fP is set, there are two cases.
|
|
If the physical file position has changed from its last known position,
|
|
the logical stream position is made equal to the new physical file position.
|
|
Finally, if the physical file location remains the same as its last known position,
|
|
the physical file position is made the same as the logical stream position.
|
|
|
|
For an unseekable stream (e.g., pipes or terminal devices), if possible,
|
|
\f3SF_SHARE\fP means that
|
|
the block and record I/O operations (\f3sfread()\fP, \f3sfwrite()\fP, \f3sfmove()\fP,
|
|
\f3sfgetr()\fP, \f3sfputr()\fP, \f3sfreserve()\fP, \f3sfscanf()\fP
|
|
and \f3sfvprintf()\fP) will ensure:
|
|
(1) after each writing operation, the stream is synchronized and
|
|
(2) each reading operation only reads the requested amount.
|
|
Note, however, that (2) is not always possible
|
|
without proper OS facilities such as \f3recv(2)\fP or \f3streamio(4)\fP.
|
|
|
|
A standard stream that is seekable will be initialized with \f3SF_SHARE|SF_PUBLIC\fP.
|
|
.Tp
|
|
\f3SF_MALLOC\fP:
|
|
The stream buffer was obtained via \f3malloc(3)\fP
|
|
and can be reallocated or freed.
|
|
.Tp
|
|
\f3SF_STATIC\fP:
|
|
The stream structure should not be freed when closed (\f3sfclose()\fP).
|
|
This flag is used by an applications that allocate their own
|
|
stream structures. Such applications must use the header file \f3sfio_t.h\fP
|
|
instead of \f3sfio.h\fP.
|
|
.Tp
|
|
\f3SF_IOCHECK\fP:
|
|
If the stream has a discipline exception handler,
|
|
exceptions will be raised in \f3sfsync()\fP, \f3sfpurge()\fP
|
|
or before a system call \f3read(2)\fP or \f3write(2)\fP (see \f3sfdisc()\fP).
|
|
.Tp
|
|
\f3SF_WHOLE\fP:
|
|
This flag guarantees that data written in any single \f3sfwrite()\fP or
|
|
\f3sfputr()\fP call will always be output as a whole to the output device.
|
|
This is useful in certain applications (e.g., networking) where a complex object
|
|
must be output without being split in different system calls.
|
|
Note that the respective stream still buffers data as much as the buffer can accommodate.
|
|
.Tp
|
|
\f3SF_MTSAFE\fP:
|
|
This flag indicates that the respective stream may be accessed by more than one threads.
|
|
A mutex lock will be used to ensure that only one thread at a time can access
|
|
the stream. Note that this flag can only be set at stream opening time
|
|
(see \f3sfopen()\fP, \f3sfpopen()\fP and \f3sfnew()\fP).
|
|
Certain fast macro functions such as \f3sfgetc()\fP and \f3sfputc()\fP will
|
|
no longer behave as macros. Thus, an application that requires such fast macro functions
|
|
should leave \f3SF_MTSAFE\fP off and performs explicit locking with \f3sfmutex()\fP.
|
|
.Tp
|
|
\f3SF_IOINTR\fP:
|
|
This flag indicates that I/O system calls should not be resumed
|
|
after being interrupted by signals. It is useful for
|
|
aborting I/O operations on such interruptions. Note, however,
|
|
that certain operating systems (e.g., BSD Unix systems) may automatically
|
|
resume interrupted system calls outside the scope of the library. On such systems,
|
|
\f3SF_IOINTR\fP will be ineffective.
|
|
|
|
.PP
|
|
.Ss "OPENING/CLOSING STREAMS"
|
|
.PP
|
|
.Ss " Sfio_t* sfnew(Sfio_t* f, Void_t* buf, size_t size, int fd, int flags)"
|
|
This function creates or renews a stream.
|
|
It returns the new stream on success and \f3NULL\fP on error.
|
|
.Tp
|
|
\f3f\fP:
|
|
If \f3f\fP is \f3NULL\fP, a new stream is created.
|
|
Otherwise, \f3f\fP is reused.
|
|
In this case, if \f3flags\fP does not have \f3SF_EOF\fP,
|
|
\f3f\fP shall be closed via \f3sfclose()\fP before being reused.
|
|
During a stream renewal, buffer, pool and discipline stack are preserved.
|
|
Note that, except for \f3SF_STATIC\fP streams,
|
|
renewing a stream already closed will result in undefined behavior.
|
|
.Tp
|
|
\f3buf\fP, \f3size\fP:
|
|
These determine a buffering scheme.
|
|
See \f3sfsetbuf()\fP for more details.
|
|
.Tp
|
|
\f3fd\fP:
|
|
If \f3SF_STRING\fP is specified in \f3flags\fP, this is ignored.
|
|
Otherwise, \f3fd\fP is a file descriptor (e.g., from \f3open(2)\fP)
|
|
to use for raw data I/O.
|
|
Note that Sfio supports unseekable file descriptors
|
|
opened for both read and write, e.g., sockets.
|
|
.Tp
|
|
\f3flags\fP:
|
|
This is composed from \f3SF_EOF\fP and
|
|
bit values defined in the \fBBIT FLAGS\fP section.
|
|
Note, in particular, that a multi-threaded application should
|
|
set the bit \f3SF_MTSAFE\fP to protect the new stream from
|
|
being simultaneously accessed by multiple threads.
|
|
|
|
.Ss " Sfio_t* sfopen(Sfio_t* f, const char* string, const char* mode)"
|
|
|
|
If \f3string\fP is \f3NULL\fP,
|
|
\f3f\fP is a file stream and
|
|
\f3mode\fP does not imply a string stream,
|
|
\f3sfopen()\fP changes the modes of \f3f\fP according to \f3mode\fP.
|
|
In this case, \f3sfopen()\fP returns \f3f\fP on success and \f3NULL\fP on error.
|
|
This somewhat unusual usage of \f3sfopen()\fP is good for
|
|
resetting certain predefined modes in standard streams including
|
|
\fItext/binary\fP and \fIappend\fP that are inherited from some parent process.
|
|
Note also that \f3SF_READ\fP and \f3SF_WRITE\fP can only be reset if the stream
|
|
is not yet initialized.
|
|
|
|
\f3sfopen()\fP is normally used to create a new stream or renew a stream.
|
|
In this case, it returns the new stream on success and \f3NULL\fP on error.
|
|
Below are the meanings of the arguments:
|
|
.Tp
|
|
\f3f\fP:
|
|
This is treated as in \f3sfnew()\fP.
|
|
.Tp
|
|
\f3string\fP:
|
|
This is a file name or a string to perform I/O on.
|
|
See above for when this is \f3NULL\fP.
|
|
.Tp
|
|
\f3mode\fP:
|
|
This is composed from the set of letters \f3{s, r, w, +, a, b, t, x, m, u}\fP.
|
|
When conflicting options are present in the same \f3mode\fP string,
|
|
the last one will take effect.
|
|
|
|
\f3s\fP specifies opening a string stream.
|
|
\f3string\fP can be a null-terminated string or \f3NULL\fP.
|
|
Specifying \f3s\fP alone is equivalent to specifying \f3sr\fP.
|
|
If \f3s\fP is not specified, \f3string\fP defines a file name.
|
|
|
|
\f3r\fP and \f3w\fP specify read and write modes.
|
|
Write mode creates and/or truncates the given file to make an empty file.
|
|
The \f3+\fP modifier indicates that the stream is opened for both read and write.
|
|
|
|
\f3a\fP specifies append mode, i.e., data is always output at end of file.
|
|
|
|
\f3b\fP and \f3t\fP specify binary and text modes.
|
|
|
|
\f3x\fP specifies exclusive mode, i.e.,
|
|
a file opened for writing should not already exist.
|
|
|
|
\f3m\fP specifies that the stream needs to be protected from
|
|
simultaneous accesses by multiple threads.
|
|
This turns on the bit flag \f3SF_MTSAFE\fP.
|
|
|
|
\f3u\fP specifies that the stream is guaranteed to be accessed
|
|
by only one thread at a time. The bit flag \f3SF_MTSAFE\fP is left off.
|
|
The absence of option \f3m\fP is the same as the presence of option \f3u\fP.
|
|
|
|
.Ss " Sfio_t* sfpopen(Sfio_t* f, const char* cmd, const char* mode)"
|
|
This function opens a stream that corresponds to the coprocess \f3cmd\fP.
|
|
The argument \f3mode\fP should be composed from \f3r\fP, \f3w\fP, and \f3+\fP.
|
|
The argument \f3f\fP, if not \f3NULL\fP, is a stream to be renewed (see \f3sfnew()\fP).
|
|
\f3sfpopen()\fP returns the new stream or \f3NULL\fP on error.
|
|
|
|
The standard input/output of \f3cmd\fP
|
|
is connected to the application via a pipe if the stream is opened for writing/reading.
|
|
If the stream is opened for both reading and writing,
|
|
there will be two different associated file descriptors, one for each type of I/O
|
|
(note the effect on \f3sffileno()\fP).
|
|
|
|
On opening a coprocess for writing (i.e., \f3mode\fP contains \f3w\fP or \f3+\fP),
|
|
the signal handler for \f3SIGPIPE\fP in the parent application
|
|
will be set to \f3SIG_IGN\fP if it is \f3SIG_DFL\fP at that time.
|
|
This protects the parent application from being accidentally killed
|
|
on writing to a coprocess that closes its reading end.
|
|
Applications that need to detect such write errors should use
|
|
disciplines and exception handlers (see \f3sfdisc()\fP).
|
|
|
|
The command \f3cmd\fP
|
|
is executed by an \fIinterpreter\fP which is either \f3/bin/sh\fP
|
|
or an executable command defined by the environment variable \f3SHELL\fP.
|
|
In either case, the interpreter is invoked with 2 arguments, respectively \f3-c\fP
|
|
and the given command \f3cmd\fP. When the interpreter is \f3/bin/sh\fP or
|
|
\f3/bin/ksh\fP, \f3sfpopen()\fP may execute the command \f3cmd\fP itself
|
|
if there are no shell meta-characters in \f3cmd\fP.
|
|
|
|
.Ss " Sfio_t* sftmp(size_t size)"
|
|
This function creates a stream for temporary data.
|
|
It returns the new stream or \f3NULL\fP on error.
|
|
|
|
A stream created by \f3sftmp()\fP can be completely or partially memory-resident.
|
|
If \f3size\fP is \f3SF_UNBOUND\fP, the stream is a pure string stream.
|
|
If \f3size\fP is zero, the stream is a pure file stream.
|
|
Otherwise, the stream is first created as a string stream but when
|
|
its buffer grows larger than \f3size\fP or on any attempt to change disciplines,
|
|
a temporary file is created.
|
|
Two environment variables, \f3TMPPATH\fP and \f3TMPDIR\fP,
|
|
direct where temporary files are created.
|
|
\f3TMPPATH\fP, if defined,
|
|
specifies a colon-separated set of directories to be
|
|
used in a round-robin fashion to create files.
|
|
If \f3TMPPATH\fP is undefined,
|
|
\f3TMPDIR\fP can be used to specify a single directory to create files.
|
|
If neither of \f3TMPPATH\fP and \f3TMPDIR\fP are defined, \f3/tmp\fP is used.
|
|
|
|
.Ss " int sfclose(Sfio_t* f)"
|
|
This function closes the stream \f3f\fP and frees its resources.
|
|
\f3SF_STATIC\fP should be used if the stream space is to be preserved.
|
|
If \f3f\fP is the base of a stream stack (see \f3sfstack()\fP),
|
|
all streams on the stack are closed.
|
|
If \f3f\fP is a \f3sfpopen\fP-stream,
|
|
\f3sfclose()\fP waits until the associated command terminates
|
|
and returns its exit status.
|
|
\f3sfclose()\fP returns \f3-1\fP for failure and \f30\fP for success.
|
|
|
|
\f3SF_READ|SF_SHARE\fP and \f3SF_WRITE\fP streams
|
|
are synchronized before closing (see \f3sfsync()\fP).
|
|
If \f3f\fP has disciplines,
|
|
their exception handlers will be called twice.
|
|
The first exception handler call has the \f3type\fP argument as one of
|
|
\f3SF_CLOSING\fP or \f3SF_NEW\fP (see \f3sfdisc()\fP).
|
|
The latter, \f3SF_NEW\fP is used when a stream is being closed via \f3sfnew()\fP
|
|
so that it can be renewed.
|
|
The second call uses \f3type\fP as \f3SF_FINAL\fP
|
|
and is done after all closing operations have succeeded but before
|
|
the stream itself is deallocated.
|
|
In either case, if the exception handler returns a negative value,
|
|
\f3sfclose()\fP will immediately return this value.
|
|
If the exception handler returns a positive value,
|
|
\f3sfclose()\fP will immediately return a zero value.
|
|
|
|
.PP
|
|
.Ss "THREAD SAFETY"
|
|
.PP
|
|
The libraries \f3libsfio.a\fP and \f3libstdio.a\fP (providing binary
|
|
compatibility to Stdio-based code) only support single-threaded code.
|
|
Multi-threaded applications should link with
|
|
\f3libsfio-mt.a\fP and \f3libstdio-mt.a\fP.
|
|
When this is done, certain platforms may require additional
|
|
thread libraries for linkage. For example, Linux, IRIX and Solaris
|
|
require \f3-lpthread\fP while HPUX requires \f3-lcma\fP.
|
|
Aside from linkage differences, the Sfio API remains identical in all cases.
|
|
|
|
Note that unlike Stdio streams which are in thread-safe mode by default.
|
|
Sfio streams can be opened in either single-threaded or multi-threaded mode.
|
|
A single-threaded stream is more efficient than a multi-threaded one.
|
|
For example, functions such as \f3sfgetc()\fP and \f3sfputc()\fP
|
|
remain as macro or inline functions for a single-threaded stream while
|
|
they will act as full function calls in a multi-threaded case.
|
|
The three standard streams \f3sfstdin/sfstdout/sfstderr\fP
|
|
are in multi-threaded mode by default
|
|
(however, see \f3sfopen()\fP for how this may be changed).
|
|
Other Sfio streams are normally opened single-threaded unless
|
|
the flag \f3SF_MTSAFE\fP or the option \f3m\fP were specified.
|
|
Stdio-based code can also make a Stdio stream single-threaded by
|
|
using the option \f3u\fP when opening a file.
|
|
|
|
.PP
|
|
.Ss "int sfmutex(Sfio_t* f, int type)"
|
|
This function acquires or releases a mutex
|
|
(mutually exclusive) lock on the stream \f3f\fP.
|
|
It can be used by a thread to serialize a sequence of I/O operations
|
|
executed together in some critical section.
|
|
\f3sfmutex()\fP is implicitly used by
|
|
all Sfio operations on a stream with the flag \f3SF_MTSAFE\fP to
|
|
protect it from concurrent accesses via multiple threads.
|
|
\f3sfmutex()\fP returns \f30\fP on success and some non-zero value on failure.
|
|
|
|
Each stream has a lock count which starts at \f30\fP.
|
|
When the count is positive, a single thread holds the stream.
|
|
Only this thread can further lock or unlock the stream.
|
|
A different thread attempting to acquire such a locked stream will suspend
|
|
until the lock count returns to \f30\fP.
|
|
Each successful locking operation increases the lock count
|
|
while each successful unlocking operation decreases it,
|
|
thus, allowing nesting of matching lock/unlock operations.
|
|
|
|
The \f3type\fP argument of \f3sfmutex()\fP takes on the below values:
|
|
.Tp
|
|
\f3SFMTX_LOCK\fP:
|
|
Locking a stream if it is unlocked or increasing the lock count of the stream
|
|
if it is already locked by the same thread. This call will block until it is
|
|
possible to lock the stream.
|
|
.Tp
|
|
\f3SFMTX_TRYLOCK\fP:
|
|
This is the non-blocking version of \f3SFMTX_LOCK\fP.
|
|
If the stream is already locked by a different thread, \f3sfmutex()\fP will
|
|
immediately return with an error status.
|
|
.Tp
|
|
\f3SFMTX_UNLOCK\fP:
|
|
Decreasing the lock count and releasing the stream when the lock count reaches 0.
|
|
An attempt to unlock a stream without a previously successful lock may
|
|
result in undefined behavior in certain implementations.
|
|
The current Sfio implementation returns an error status.
|
|
.Tp
|
|
\f3SFMTX_CLRLOCK\fP:
|
|
Resetting the lock count to \f30\fP and releasing the stream.
|
|
As with \f3SFMTX_LOCK\fP,
|
|
an attempt to clear the lock count without a previously successful lock
|
|
may result in undefined behavior.
|
|
.PP
|
|
.Ss "INPUT/OUTPUT OPERATIONS"
|
|
.PP
|
|
.Ss " int sfgetc(Sfio_t* f)"
|
|
.Ss " int sfputc(Sfio_t* f, int c)"
|
|
These functions read/write a byte from/to stream \f3f\fP.
|
|
\f3sfgetc()\fP returns the byte read or \f3-1\fP on error.
|
|
\f3sfputc()\fP returns \f3c\fP on success and \f3-1\fP on error.
|
|
|
|
.Ss " ssize_t sfnputc(Sfio_t* f, int c, size_t n)"
|
|
This function attempts to write the byte \f3c\fP to \f3f\fP \f3n\fP times.
|
|
It returns the number of bytes actually written or \f3-1\fP on failure.
|
|
|
|
.Ss " int sfungetc(Sfio_t* f, int c)"
|
|
This function pushes the byte \f3c\fP back into \f3f\fP.
|
|
If \f3c\fP matches the byte immediately before the current position in buffered data,
|
|
the current position is simply backed up (note the effect on \f3sftell()\fP and
|
|
\f3sfseek()\fP). There is no theoretical limit on the number of bytes that
|
|
can be pushed back into a stream. Pushed back bytes not part of
|
|
buffered data will be discarded on any operation that implies
|
|
buffer synchronization.
|
|
\f3sfungetc()\fP returns \f3c\fP on success and \f3-1\fP on failure.
|
|
|
|
.Ss " Sfulong_t sfgetm(Sfio_t* f, Sfulong_t max)"
|
|
.Ss " int sfputm(Sfio_t* f, Sfulong_t v, Sfulong_t max)"
|
|
These functions read and write \f3Sfulong_t\fP values
|
|
encoded in a portable format given that the values are at most \f3max\fP.
|
|
Portability across a write architecture and a read architecture
|
|
requires that the bit order in a byte is the same on both architectures and
|
|
the written value is storable in an \f3Sfulong_t\fP on the read architecture.
|
|
\f3sfgetm()\fP returns the value read or \f3-1\fP on error.
|
|
\f3sfputm()\fP returns the number of bytes written or \f3-1\fP on error.
|
|
|
|
.Ss " Sfulong_t sfgetu(Sfio_t* f)"
|
|
.Ss " int sfputu(Sfio_t* f, Sfulong_t v)"
|
|
These functions read and write \f3Sfulong_t\fP values
|
|
in a compact variable-length portable format.
|
|
Portability across a write architecture and a read architecture
|
|
requires that the bit order in a byte is the same on both architectures and
|
|
the written value is storable in an \f3Sfulong_t\fP on the read architecture.
|
|
\f3sfgetu()\fP returns the value read or \f3-1\fP on error.
|
|
\f3sfputu()\fP returns the number of bytes written or \f3-1\fP on error.
|
|
See also \f3sfulen()\fP.
|
|
|
|
.Ss " Sflong_t sfgetl(Sfio_t* f)"
|
|
.Ss " int sfputl(Sfio_t* f, Sflong_t v)"
|
|
These functions are similar to \f3sfgetu()\fP and \f3sfputu()\fP
|
|
but for reading and writing (signed) \f3Sflong_t\fP values.
|
|
See also \f3sfllen()\fP.
|
|
|
|
.Ss " Sfdouble_t sfgetd(Sfio_t* f)"
|
|
.Ss " int sfputd(Sfio_t* f, Sfdouble_t v)"
|
|
These functions read and write \f3Sfdouble_t\fP values.
|
|
In this case, portability depends on the input and output architectures
|
|
having the same floating point value representation.
|
|
Values are coded and decoded using \f3ldexp(3)\fP and \f3frexp(3)\fP
|
|
so they are constrained to the sizes supported by these functions.
|
|
See also \f3sfdlen()\fP.
|
|
|
|
.Ss " char* sfgetr(Sfio_t* f, int rsc, int type)"
|
|
This function reads a record of data ending in the record separator \f3rsc\fP.
|
|
After \f3sfgetr()\fP returns, the length of the record even if it is incomplete
|
|
can be retrieved with \f3sfvalue()\fP.
|
|
\f3sfgetr()\fP returns the record on success and \f3NULL\fP on error.
|
|
See also \f3sfmaxr()\fP for limiting the amount of data read to construct a record.
|
|
|
|
The \f3type\fP argument is composed of some subset of the below bit flags:
|
|
.Tp
|
|
\f3SF_STRING\fP:
|
|
A null byte will replace the record separator to make the record into a C string.
|
|
Otherwise, the record separator is left alone.
|
|
.Tp
|
|
\f3SF_LOCKR\fP:
|
|
Upon successfully obtaining a record \f3r\fP,
|
|
the stream will be locked from further access until it is released with
|
|
a call \f3sfread(f,r,0)\fP.
|
|
.Tp
|
|
\f3SF_LASTR\fP:
|
|
This should be used only after a failed \f3sfgetr()\fP to retrieve
|
|
the last incomplete record. In this case, \f3rsc\fP is ignored.
|
|
|
|
.Ss " ssize_t sfputr(Sfio_t* f, const char* s, int rsc)"
|
|
This function writes the null-terminated string \f3s\fP to \f3f\fP.
|
|
If \f3rsc\fP is non-negative, \f3(unsigned char)rsc\fP is output after the string.
|
|
\f3sfputr()\fP returns the number of bytes written or \f3-1\fP on failure.
|
|
|
|
.Ss " Sfoff_t sfmove(Sfio_t* fr, Sfio_t* fw, Sfoff_t n, int rsc)"
|
|
This function moves objects
|
|
from input stream \f3fr\fP to output stream \f3fw\fP.
|
|
\f3sfmove()\fP returns the number of objects moved or \f3-1\fP on failure.
|
|
|
|
An object can be either a byte if the record separator argument
|
|
\f3rsc\fP is negative or a record of \f3rsc\fP is non-negative.
|
|
In the latter case, a record is incomplete if it does not end in \f3rsc\fP.
|
|
Generally speaking, a stream can have at most one incomplete record.
|
|
If \f3n\fP is negative, all complete objects of \f3fr\fP will be moved.
|
|
Otherwise, \f3n\fP indicates the number of objects to move.
|
|
If either \f3fr\fP or \f3fw\fP is \f3NULL\fP, it acts
|
|
as if it is a stream corresponding to \f3/dev/null\fP,
|
|
the UNIX device that has no read data and throws away any write data.
|
|
For example, the call \f3sfmove(f,(Sfio_t*)0,(Sfoff_t)(-1),'\en')\fP
|
|
counts the number of complete lines in stream \f3f\fP.
|
|
|
|
.Ss " ssize_t sfread(Sfio_t* f, Void_t* buf, size_t n)"
|
|
This function reads up to \f3n\fP bytes from \f3f\fP into buffer \f3buf\fP.
|
|
It returns the number of bytes actually read or \f3-1\fP on error.
|
|
|
|
.Ss " ssize_t sfwrite(Sfio_t* f, const Void_t* buf, size_t n)"
|
|
This function writes \f3n\fP bytes from \f3buf\fP to \f3f\fP.
|
|
If \f3f\fP is \f3SF_STRING\fP, and the buffer is not large enough,
|
|
an \f3SF_WRITE\fP exception shall be raised.
|
|
\f3sfwrite()\fP returns the number of bytes written or \f3-1\fP on failure.
|
|
|
|
.Ss " Sfoff_t sfseek(Sfio_t* f, Sfoff_t offset, int type)"
|
|
This function sets a new I/O position for \f3f\fP.
|
|
It returns the new position or \f3-1\fP on failure.
|
|
|
|
If the stream is a \f3SF_STRING\fP stream and the new
|
|
address is beyond the current buffer extent,
|
|
an \f3SF_SEEK\fP exception will be raised (see \f3sfdisc()\fP).
|
|
|
|
The new position is determined based on \f3offset\fP and
|
|
\f3type\fP which is composed from the bit flags:
|
|
.Tp
|
|
\f30\fP or \f3SEEK_SET\fP:
|
|
\f3offset\fP is the desired position.
|
|
.Tp
|
|
\f31\fP or \f3SEEK_CUR\fP:
|
|
\f3offset\fP is relative to the current position (see \f3SF_PUBLIC\fP below).
|
|
.Tp
|
|
\f32\fP or \f3SEEK_END\fP:
|
|
\f3offset\fP is relative to the physical end of file.
|
|
.Tp
|
|
\f3SF_SHARE\fP:
|
|
The stream is treated as if it has the control bit \f3SF_SHARE\fP on.
|
|
This implies that a system call seek will be done to ensure that the
|
|
location seeking to is valid.
|
|
.Tp
|
|
\f3SF_PUBLIC\fP:
|
|
The stream is treated as if it has the control bit \f3SF_PUBLIC\fP on.
|
|
If the physical file position has changed from its last known location,
|
|
the current position is taken as the new physical position.
|
|
Otherwise, the current position is the logical stream position.
|
|
|
|
.Ss " Void_t* sfreserve(Sfio_t* f, ssize_t n, int type)"
|
|
This function reserves a data block from the stream \f3f\fP.
|
|
It returns the reserved data block on success and \f3NULL\fP on failure.
|
|
|
|
If \f3f\fP is a \f3SF_READ\fP stream, the data block is a segment of input data.
|
|
If \f3f\fP is a \f3SF_WRITE\fP stream, the data block is a buffer
|
|
suitable for writing output data.
|
|
For consistency, if \f3f\fP is opened with \f3SF_READ|SF_WRITE\fP,
|
|
it will normally be treated as if it is a \f3SF_READ\fP stream
|
|
(see \f3sfset()\fP for forcing a particular mode) but the returned
|
|
buffer can also be written into (more below).
|
|
However, it is possible to bias to \f3SF_WRITE\fP when the \f3type\fP
|
|
argument is non-negative by adding the \f3SF_WRITE\fP bit \f3type\fP.
|
|
In any case, a reserved data block is guaranteed to be valid only until
|
|
a future access to the stream \f3f\fP.
|
|
|
|
When \f3f\fP is \f3SF_READ\fP, \f3SF_SHARE\fP and unseekable,
|
|
\f3sfreserve()\fP will attempt to peek at input data without
|
|
consuming it. This enables separate processes to share in reading
|
|
input from unseekable file descriptors (e.g., pipes or devices).
|
|
However, this use of \f3sfreserve()\fP may fail
|
|
on certain platforms that do not properly support
|
|
peeking on unseekable file descriptors.
|
|
|
|
After a \f3sfreserve()\fP call, whether or not it succeeds,
|
|
\f3sfvalue(f)\fP gives the size of the available data block.
|
|
Any partially reserved data block after a failed \f3sfreserve()\fP
|
|
call can be obtained in another \f3sfreserve()\fP call with the argument
|
|
\f3type\fP being \f3SF_LASTR\fP. The second argument \f3n\fP
|
|
to \f3sfreserve()\fP will be ignored in this case.
|
|
|
|
A \f3sfreserve()\fP call is successful if it can obtain a data block
|
|
of size at least the absolute value of \f3n\fP.
|
|
For a \f3SF_READ\fP atream, the argument \f3n\fP is treated as follows:
|
|
.Tp
|
|
\f3n < 0\fP:
|
|
\f3sfreserve()\fP attempts to get \fIat least\fP \f3|n|\fP bytes
|
|
into the buffer.
|
|
.Tp
|
|
\f3n == 0\fP:
|
|
If the argument \f3type\fP is \f30\fP,
|
|
\f3sfreserve()\fP attempts to get \fIat least\fP \f31\fP byte into the buffer
|
|
but does not consume it (as consistent with \f3n == 0\fP).
|
|
If \f3type != 0\fP, no attempt will be made to read data into the buffer.
|
|
For example, the call \f3sfreserve(f, 0, -1)\fP only returns the buffer status,
|
|
i.e., size of existing buffered data and pointer to such data, if any.
|
|
The call \f3sfreserve(f, 0, SF_LOCKR)\fP is similar but also locks the stream.
|
|
.Tp
|
|
\f3n > 0\fP:
|
|
\f3sfreserve()\fP will use attempt to get \fIat most\fP \f3n\fP bytes into
|
|
the buffer. Further, if \f3type == 3SF_LOCKR\fP (see below), read attempts
|
|
end on a positive amount.
|
|
|
|
For a successful reservation, the argument \f3type\fP dictates treatment
|
|
as follows:
|
|
.Tp
|
|
\f3type == SF_LASTR\fP:
|
|
After a \f3sfreserve()\fP call with \f3type != SF_LOCKR\fP fails,
|
|
there may be some left over data not accessible via conventional Sfio calls.
|
|
Immediately after such a failed call,
|
|
another call to \f3sfreserve\fP with \f3type == SF_LASTR\fP will return any left over
|
|
data and also advance the stream I/O position by the amount of returned data.
|
|
.Tp
|
|
\f3type < 0\fP:
|
|
If \f3n > 0\fP, the stream I/O position is advanced by \f3n\fP.
|
|
If \f3n < 0\fP, the stream I/O position is advanced by the amount
|
|
of available data.
|
|
For example, a successful \f3sfreserve(f, -1, -1)\fP call will return a
|
|
buffer of data and simultaneously advance the stream I/O position by the amount
|
|
indicated by \f3sfvalue(f)\fP.
|
|
.Tp
|
|
\f3type == SF_LOCKR\fP:
|
|
The stream I/O position remains unchanged.
|
|
In addition, \f3f\fP will be locked from further access.
|
|
As appropriate to the stream type (\f3SF_READ\fP, \f3SF_WRITE\fP or both),
|
|
\f3f\fP can be unlocked later
|
|
with one of \f3sfread(f,rsrv,size)\fP or \f3sfwrite(f,rsrv,size)\fP
|
|
where \f3rsrv\fP is the reserved data block and \f3size\fP is the amount of
|
|
data to be consumed. For example, if \f3f\fP is a locked \f3SF_READ\fP stream,
|
|
the call \f3sfread(f,rsrv,1)\fP will reopen the stream and simultaneously
|
|
advance the stream I/O position by \f31\fP.
|
|
Finally, a stream opened for both reading and writing
|
|
can release the lock with either call (with associated operational semantics!)
|
|
For example, the below code reads 10 bytes of data from a stream
|
|
opened with both \f3SF_READ\fP and \f3SF_WRITE\fP, modifies the data in place,
|
|
then rewrites the new data back to the stream:
|
|
|
|
.nf
|
|
.ft 5
|
|
rsrv = sfreserve(f, 10, 1);
|
|
for(i = 0; i < 10; ++i)
|
|
rsrv[i] = toupper(rsrv[i]);
|
|
sfwrite(f, rsrv, 10);
|
|
.ft 1
|
|
.fi
|
|
|
|
.ne 6
|
|
.PP
|
|
.Ss "DATA FORMATTING"
|
|
.PP
|
|
Data printing and scanning are done via the
|
|
\f3sfprintf()\fP and \f3sfscanf()\fP family of functions.
|
|
These functions are similar to their
|
|
ANSI C \f3fprintf()\fP and \f3fscanf()\fP counterparts.
|
|
However, the Sfio versions have been extended for both portability and generality.
|
|
In particular, a notion of a formatting environment stack is introduced.
|
|
Each formatting element on the stack
|
|
defines a separate \fIformatting pair\fP of a format specification string,
|
|
\f3char* format\fP (the usual second argument in the formatting
|
|
functions), and an argument list, \f3va_list args\fP (the third argument
|
|
in functions \f3sfvprintf()\fP and \f3sfvscanf()\fP).
|
|
A formatting environment element may also specify extension functions
|
|
to obtain or assign arguments and to provide new semantics for pattern processing.
|
|
To simplify the description below, whenever we talk
|
|
about an argument list, unless noted otherwise,
|
|
it is understood that this means either the true
|
|
argument list when there is no extension function or the action to be taken
|
|
by such a function in processing arguments.
|
|
The manipulation of the formatting environment stack is done
|
|
via the pattern \f3!\fP discussed below.
|
|
|
|
.Ss "%! and Sffmt_t"
|
|
The pattern \f3%!\fP manipulates the formatting environment stack to
|
|
(1) change the top environment to a new environment,
|
|
(2) stack a new environment on top of the current top,
|
|
or (3) pop the top environment.
|
|
The bottom of the environment stack always contains a virtual environment with the
|
|
original formatting pair and without any extension functions.
|
|
|
|
The top environment of a stack, say \f3fe\fP, is automatically popped whenever
|
|
its format string is completely processed.
|
|
In this case, its event-handling function (if any) is called
|
|
as \f3(*eventf)(f,SF_FINAL,NIL(Void_t*),fe)\fP.
|
|
The top environment
|
|
can also be popped by giving an argument \f3NULL\fP to \f3%!\fP
|
|
or by returning a negative value in an extension function.
|
|
In these cases, the event-handling function is called
|
|
as \f3(*eventf)(f,SF_DPOP,form,fe)\fP where \f3form\fP is the remainder
|
|
of the format string. A negative return value from the event handling function
|
|
will prevent the environment from being popped.
|
|
|
|
A formatting environment is a structure of type \f3Sffmt_t\fP
|
|
which contains the following elements:
|
|
|
|
.nf
|
|
.ft 5
|
|
Sffmtext_f extf; /* extension processor */
|
|
Sffmtevent_f eventf; /* event handler */
|
|
|
|
char* form; /* format string to stack */
|
|
va_list args; /* corresponding arg list */
|
|
|
|
int fmt; /* pattern being processed */
|
|
ssize_t size; /* object size */
|
|
int flags; /* formatting control flags */
|
|
int width; /* width of field */
|
|
int precis; /* precision required */
|
|
int base; /* conversion base */
|
|
|
|
char* t_str; /* extfdata string */
|
|
int n_str; /* length of t_str */
|
|
.ft 1
|
|
.fi
|
|
|
|
The first four elements of \f3Sffmt_t\fP must be defined by the application
|
|
before the structure is passed to a formatting function.
|
|
The two function fields should not be changed during processing.
|
|
Other elements of \f3Sffmt_t\fP are set by the respective formatting function
|
|
before it calls the extension function \f3Sffmt_t.extf\fP and, subsequently,
|
|
can be modified by this function to redirect formatting or scanning.
|
|
For example, consider a call from a \f3sfprintf()\fP function to process an
|
|
unknown pattern \f3%t\fP (which we may take to mean ``time'') based on a
|
|
formatting environment \f3fe\fP.
|
|
\f3fe->extf\fP may reset \f3fe->fmt\fP to `\f3d\fP' upon returning
|
|
to cause \f3sfprintf()\fP to process the value being formatted as an integer.
|
|
|
|
Below are the fields of \f3Sffmt_t\fP:
|
|
.Tp
|
|
\f3extf\fP:
|
|
\f3extf\fP is a function to extend scanning and formatting patterns.
|
|
Its usage is discussed below.
|
|
.Tp
|
|
\f3eventf\fP:
|
|
This is a function to process events as discussed earlier.
|
|
.Tp
|
|
\f3form\fP and \f3args\fP:
|
|
This is the formatting pair of a specification string and corresponding argument list.
|
|
When an environment \f3fe\fP is being inserted into the stack,
|
|
if \f3fe->form\fP is \f3NULL\fP, the top environment is changed to \f3fe\fP
|
|
and its associated extension functions
|
|
but processing of the current formatting pair continues.
|
|
On the other hand, if \f3fe->form\fP is not \f3NULL\fP,
|
|
the new environment is pushed onto the stack
|
|
so that pattern processing will start with the new formatting pair as well as
|
|
any associated extension functions.
|
|
During processing, whenever \f3extf\fP is called,
|
|
\f3form\fP and \f3args\fP will be set to the current values of
|
|
the formatting pair in use.
|
|
.Tp
|
|
\f3fmt\fP:
|
|
This is set to the pattern being processed or one of '.', 'I', '('.
|
|
.Tp
|
|
\f3size\fP:
|
|
This is the size of the object being processed.
|
|
.Tp
|
|
\f3flags\fP:
|
|
This is a collection of bits defining the formatting flags specified for the pattern.
|
|
The bits are:
|
|
|
|
\f3SFFMT_LEFT\fP: Flag \f3-\fP in \f3sfprintf()\fP.
|
|
|
|
\f3SFFMT_SIGN\fP: Flag \f3+\fP in \f3sfprintf()\fP.
|
|
|
|
\f3SFFMT_BLANK\fP: Flag \fIspace\fP in \f3sfprintf()\fP.
|
|
|
|
\f3SFFMT_ZERO\fP: Flag \f30\fP in \f3sfprintf()\fP.
|
|
|
|
\f3SFFMT_THOUSAND\fP: Flag \f3'\fP in \f3sfprintf()\fP.
|
|
|
|
\f3SFFMT_LONG\fP: Flag \f3l\fP in \f3sfprintf()\fP and \f3sfscanf()\fP.
|
|
|
|
\f3SFFMT_LLONG\fP: Flag \f3ll\fP in \f3sfprintf()\fP and \f3sfscanf()\fP.
|
|
|
|
\f3SFFMT_SHORT\fP: Flag \f3h\fP in \f3sfprintf()\fP and \f3sfscanf()\fP.
|
|
|
|
\f3SFFMT_LDOUBLE\fP: Flag \f3L\fP in \f3sfprintf()\fP and \f3sfscanf()\fP.
|
|
|
|
\f3SFFMT_IFLAG\fP: flag \f3I\fP in \f3sfprintf()\fP and \f3sfscanf()\fP.
|
|
|
|
\f3SFFMT_JFLAG\fP: flag \f3j\fP in \f3sfprintf()\fP and \f3sfscanf()\fP.
|
|
|
|
\f3SFFMT_CENTER\fP: flag \f3=\fP in \f3sfprintf()\fP and \f3sfscanf()\fP.
|
|
|
|
\f3SFFMT_CHOP\fP: flag \f3-\fP in \fIprecis\fP in \f3sfprintf()\fP and \f3sfscanf()\fP.
|
|
|
|
\f3SFFMT_ALTER\fP: Flag \f3#\fP in \f3sfprintf()\fP and \f3sfscanf()\fP.
|
|
|
|
\f3SFFMT_SKIP\fP: Flag \f3*\fP in \f3sfscanf()\fP.
|
|
|
|
\f3SFFMT_ARGPOS\fP: This indicates argument processing for \f3pos$\fP.
|
|
|
|
\f3SFFMT_VALUE\fP: This is set by \f3fe->extf\fP
|
|
to indicate that it is returning a value to be formatted or
|
|
the address of an object to be assigned.
|
|
|
|
.Tp
|
|
\f3width\fP:
|
|
This is the field width.
|
|
.Tp
|
|
\f3precis\fP:
|
|
This is the precision.
|
|
.Tp
|
|
\f3base\fP:
|
|
This is the conversion base.
|
|
.Tp
|
|
\f3t_str\fP and \f3n_str\fP:
|
|
This is the type string and its size.
|
|
|
|
.Ss " int (*Sffmtext_f)(Sfio_t* f, Void_t* v, Sffmt_t* fe)"
|
|
This is the type of the extension function \f3fe->extf\fP to process
|
|
patterns and arguments.
|
|
Arguments are always processed in order and
|
|
\f3fe->extf\fP is called exactly once per argument.
|
|
Note that, when \f3pos$\fP (below) is not used anywhere in a format string,
|
|
each argument is used exactly once per a corresponding pattern.
|
|
In that case, \f3fe->extf\fP is called
|
|
as soon as the pattern is recognized and before any scanning or formatting.
|
|
On the other hand, when \f3pos$\fP is used in a format string,
|
|
an argument may be used multiple times.
|
|
In this case, all arguments shall be processed in order
|
|
by calling \f3fe->extf\fP exactly once per argument before any pattern processing.
|
|
This case is signified by the flag \f3SFFMT_ARGPOS\fP in \f3fe->flags\fP.
|
|
|
|
In addition to the predefined formatting patterns and other application-defined
|
|
patterns, \f3fe->extf\fP may be called with \f3fe->fmt\fP being one
|
|
of `\f3(\fP' (left parenthesis), `\f3.\fP' (dot), and `\f3I\fP'.
|
|
|
|
The left parenthesis requests a string to be used as the \f3extfdata\fP string discussed below.
|
|
In this case, upon returning, \f3fe->extf\fP should set the \f3fe->size\fP field
|
|
to be the length of the string or a negative value to indicate a null-terminated string.
|
|
|
|
The `\f3I\fP' requests an integer to define the object size.
|
|
|
|
The dot requests an integer for width, precision, base, or a separator.
|
|
In this case, the \f3fe->size\fP field will indicate how many dots have appeared
|
|
in the pattern specification. Note that, if the actual conversion pattern is 'c' or 's',
|
|
the value \f3*form\fP will be one of these characters.
|
|
.Tp
|
|
\f3f\fP:
|
|
This is the input/output stream in the calling formatting function.
|
|
During a call to \f3fe->extf\fP, the stream shall be unlocked
|
|
so that \f3fe->extf\fP can read from or write to it as appropriate.
|
|
.Tp
|
|
\f3v\fP:
|
|
For both \f3sfscanf()\fP and \f3sfprintf()\fP functions,
|
|
\f3v\fP points to a location suitable for storing any scalars or pointers.
|
|
On return, \f3fe->extf\fP treats \f3v\fP as discussed below.
|
|
.Tp
|
|
\f3fe\fP:
|
|
This is the current formatting environment.
|
|
.PP
|
|
The return value \f3rv\fP of \f3fe->extf\fP directs further processing.
|
|
There are two cases.
|
|
When \f3pos$\fP is present, a negative return value means to ignore \f3fe\fP
|
|
in further argument processing while a non-negative return value is treated
|
|
as the case \f3rv == 0\fP below.
|
|
When \f3pos$\fP is not present, \f3fe->extf\fP is called per argument
|
|
immediately before pattern processing and its return values are treated
|
|
as below:
|
|
.Tp
|
|
\f3rv < 0:\fP
|
|
The environment stack is immediately popped.
|
|
.Tp
|
|
\f3rv == 0:\fP
|
|
The extension function has not consumed (in a scanning case) or
|
|
output (in a printing case) data out of or into the given stream \f3f\fP.
|
|
The fields \f3fmt\fP, \f3flags\fP, \f3size\fP,
|
|
\f3width\fP, \f3precis\fP and \f3base\fP of \f3fe\fP
|
|
shall direct further processing.
|
|
|
|
For \f3sfprintf()\fP functions, if \f3fe->flags\fP
|
|
has the bit \f3SFFMT_VALUE\fP,
|
|
\f3fe->extf\fP should have set \f3*v\fP to the value to be processed;
|
|
otherwise, a value should be obtained from the argument list.
|
|
Likewise, for \f3sfscanf()\fP functions,
|
|
\f3SFFMT_VALUE\fP means that
|
|
\f3*v\fP should have a suitable address; otherwise,
|
|
an address to assign value should be obtained from the argument list.
|
|
|
|
When \f3pos$\fP is present,
|
|
if \f3fe->extf\fP changes \f3fe->fmt\fP, this pattern shall be used regardless of
|
|
the pattern defined in the format string. On the other hand, if \f3fe->fmt\fP
|
|
is unchanged by \f3fe->extf\fP, the pattern in the format string is used.
|
|
In any case, the effective pattern should be one of the standardly defined pattern.
|
|
Otherwise, it shall be treated as unmatched.
|
|
.Tp
|
|
\f3rv > 0:\fP
|
|
The extension function has accessed the stream \f3f\fP
|
|
to the extent of \f3rv\fP bytes.
|
|
Processing of the current pattern ceases except that,
|
|
for scanning functions, if \f3fe->flags\fP does not contain
|
|
the bit \f3SFFMT_SKIP\fP, the assignment count shall increase by 1.
|
|
|
|
.Ss "void va_copy(va_list to, va_list fr)"
|
|
This macro function portably copies the argument list \f3fr\fP to
|
|
the argument list \f3to\fP. It should be used to set the field \f3Sffmt_t.args\fP.
|
|
|
|
.Ss "long sffmtversion(Sffmt_t* fe, int type)"
|
|
This macro function initializes
|
|
the formatting environment \f3fe\fP with a version number if \f3type\fP is
|
|
non-zero. Otherwise, it returns the current value of the version number of \f3fe\fP.
|
|
This is useful for applications to find out
|
|
when the format of the structure \f3Sffmt_t\fP changes.
|
|
Note that the version number corresponds to the Sfio version number
|
|
which is defined in the macro value \f3SFIO_VERSION\fP.
|
|
|
|
.Ss " int sfprintf(Sfio_t* f, const char* format, ...);"
|
|
.Ss " char* sfprints(const char* format, ...);"
|
|
.Ss " char* sfvprints(const char* format, va_list args);"
|
|
.Ss " ssize_t sfaprints(char** sp, const char* format, ...);"
|
|
.Ss " ssize_t sfvaprints(char** sp, const char* format, va_list args);"
|
|
.Ss " int sfsprintf(char* s, int n, const char* format, ...)"
|
|
.Ss " int sfvsprintf(char* s, int n, const char* format, va_list args);"
|
|
.Ss " int sfvprintf(Sfio_t* f, const char* format, va_list args);"
|
|
These functions format output data.
|
|
\f3sfprintf()\fP and \f3sfvprintf()\fP write to output stream \f3f\fP.
|
|
\f3sfsprintf()\fP and \f3sfvsprintf()\fP write to buffer \f3s\fP
|
|
which is of size \f3n\fP.
|
|
\f3sfprints()\fP and \f3sfvprints()\fP construct data in some Sfio-defined buffer.
|
|
\f3sfaprints()\fP and \f3sfvaprints()\fP are similar to \f3sfprints()\fP
|
|
and \f3sfvprints()\fP
|
|
but they return a string constructed via \f3malloc()\fP in \f3*sp\fP
|
|
and expect this string to be freed by the caller when no longer needed.
|
|
\f3sfvprintf()\fP is the underlying primitive for the other functions.
|
|
Except for \f3sfprints()\fP and \f3sfvprints()\fP
|
|
which return a null-terminated string or \f3NULL\fP,
|
|
other functions return the number of output bytes or \f3-1\fP on failure.
|
|
|
|
The length of string constructed by \f3sfprints()\fP, \f3sfsprintf()\fP, or
|
|
\f3sfvsprintf()\fP can be retrieved by \f3sfslen()\fP.
|
|
.PP
|
|
The standard patterns are:
|
|
\f3n, s, c, %, h, i, d, p, u, o, x, X, g, G, e, E, f\fP and \f3!\fP.
|
|
Except for \f3!\fP which shall be described below,
|
|
see the ANSI C specification of \f3fprintf(3)\fP for details on the other patterns.
|
|
Let \f3z\fP be some pattern type. A formatting pattern is defined as below:
|
|
|
|
.nf
|
|
.ft 5
|
|
%[pos$][flag][width][.precision[.base]][(extfdata)]z
|
|
.ft 1
|
|
.fi
|
|
|
|
.Tp
|
|
\f3pos$\fP:
|
|
A pattern can specify which argument in the argument list to use.
|
|
This is done via \f3pos$\fP where \f3pos\fP is the argument position.
|
|
Arguments are numbered so that the first argument after \f3format\fP is at position 1.
|
|
If \f3pos\fP is not specified, the argument following the most recently used one
|
|
will be used.
|
|
The pattern \f3%!\fP (see below) cannot be used subsequent to a usage of \f3pos$\fP.
|
|
Doing so may cause unexpected behaviors.
|
|
.Tp
|
|
\f3flag\fP:
|
|
The flag characters are
|
|
\f3h\fP, \f3hh\fP, \f3l\fP, \f3ll\fP, \f3L\fP, \f3I\fP, \f3j\fP, \f3t\fP, \f3z\fP,
|
|
\f3\-\fP, \f3+\fP, \fIspace\fP, \f30\fP, \f3'\fP, \f3=\fP and \f3#\fP.
|
|
|
|
Flag \f3I\fP defines the size or type of the object being formatted.
|
|
There are two cases: (1) \f3I\fP by itself and (2) \f3I\fP
|
|
followed by either a decimal number or `*'.
|
|
|
|
In the first case, for integer and floating point patterns,
|
|
the object type is taken to be the largest appropriate type
|
|
(i.e., one of \f3Sflong_t\fP, \f3Sfulong_t\fP or \f3Sfdouble_t\fP).
|
|
For conversion specifiers \f3s\fP and \f3c\fP, the flag is ignored.
|
|
|
|
In the second case, a given decimal value would define a size while
|
|
`*' would cause the size to be obtained from the argument list.
|
|
Then, if the conversion specifier is \f3s\fP, this size defines the
|
|
length of the string or strings being formatted (see the discussion of \f3base\fP below).
|
|
For integer and floating point patterns,
|
|
the size is used to select a type from one of the below lists as
|
|
indicated by the conversion specifier:
|
|
|
|
.nf
|
|
.ft 5
|
|
Sflong_t, long, int, short
|
|
Sfulong_t, unsigned long, unsigned int, unsigned short
|
|
Sfdouble_t, double, float
|
|
.ft 1
|
|
.fi
|
|
|
|
The selection algorithm always matches types from left to right in any given list.
|
|
Although selection is generally based on sizes in bytes,
|
|
for compatibility with Microsoft-C, the size 64
|
|
is matched with an appropriate type with the same number of bits, if any.
|
|
If the given size does not match any of the listed types,
|
|
it shall match one of \f3int\fP, \f3unsigned int\fP, and \f3double\fP
|
|
as defined by the formatting pattern.
|
|
|
|
Below are a few examples of using the \f3I\fP flag.
|
|
The first example prints an \f3Sflong_t\fP integer.
|
|
This example is actually not portable and
|
|
only works on platforms where \f3sizeof(Sflong_t)\fP is 8.
|
|
The second example shows how to that portably.
|
|
The third example specifies printing a string of length 16.
|
|
This length shall be used regardless of whether or not the given string
|
|
is shorter or longer than 16.
|
|
The last example shows the use of the pattern \f3%n\fP to assign the amount
|
|
of data already output into a \f3short\fP integer \f3n_output\fP.
|
|
|
|
.nf
|
|
.ft 5
|
|
sfprintf(sfstdout,"%I8d", Sflong_obj);
|
|
sfprintf(sfstdout,"%I*d", sizeof(Sflong_obj), Sflong_obj);
|
|
sfprintf(sfstdout,"%I*s", 16, s);
|
|
sfprintf(sfstdout,"%d%I*n", 1001, sizeof(short), &n_output);
|
|
.ft 1
|
|
.fi
|
|
|
|
Flags \f3h\fP, \f3l\fP, \f3j\fP and \f3L\fP are the ANSI C conventions to
|
|
select the types of input objects.
|
|
For example, \f3%hd\fP indicates a \f3short int\fP,
|
|
while \f3%ld\fP indicates a \f3long int\fP.
|
|
|
|
Flag \f3hh\fP addresses the byte value types, i.e., \f3char\fP and \f3unsigned char\fP.
|
|
|
|
Flags \f3z\fP, \f3t\fP and \f3j\fP address respectively
|
|
the types \f3size_t\fP, \f3ptrdiff_t\fP and \f3Sflong_t\fP.
|
|
|
|
Flags \f3ll\fP and \f3L\fP address respectively
|
|
the largest integer and floating value types, i.e.,
|
|
\f3Sfulong_t\fP, \f3Sflong_t\fP, and \f3Sfdouble_t\fP.
|
|
|
|
Flag \f3-\fP left-justifies data within the field (otherwise, right-justification).
|
|
|
|
Flag \f3+\fP means that a signed conversion will always begin with a plus or minus sign.
|
|
|
|
Flag \fIspace\fP is ignored if \f3+\fP is specified; otherwise,
|
|
it means that if the first character of a signed conversion
|
|
is not a sign or if the result is empty, a space will be prepended.
|
|
|
|
Flag \f30\fP means padding with zeros on the left.
|
|
|
|
Flag \f3'\fP outputs thousands-separator used by the current locale.
|
|
\f3setlocale(3)\fP should have been used to set the desired locale.
|
|
|
|
Flag \f3=\fP centers data within the field.
|
|
|
|
Flag \f3#\fP indicates an alternative format processing.
|
|
For \f3%o\fP, the first digit is always a zero.
|
|
For \f3%x\fP and \f3%X\fP, a non-zero result will have a prefix
|
|
\f30x\fP or \f30X\fP. For \f3%e\fP, \f3%E\fP, \f3%f\fP, \f3%g\fP, and \f3%G\fP,
|
|
the result always contains a decimal point. For \f3%g\fP and \f3%G\fP,
|
|
trailing zeros will not be removed. For \f3%d\fP, \f3%i\fP and \f3%u\fP,
|
|
the form is \fIbase#number\fP where \fIbase\fP is the conversion base
|
|
and \fInumber\fP is represented by digits for this \fIbase\fP.
|
|
For example, a base \f32\fP conversion with \f3%#..2d\fP for \f310\fP
|
|
is \f32#1010\fP instead of \f31010\fP as printed with \f3%..2d\fP.
|
|
Finally, for \f3%c\fP, bytes will be printed in the C format.
|
|
For example, when the ASCII character set is used,
|
|
the byte value 10 will be printed as \f3\\n\fP while 255 is printed
|
|
as \f3\\377\fP.
|
|
.Tp
|
|
\f3width\fP:
|
|
This defines the width of the printing field. A value to be printed will
|
|
be justified and padded if necessary to fill out the field width.
|
|
.Tp
|
|
\f3precis\fP:
|
|
After a first dot appears, an integral value defines a precision.
|
|
For floating point value patterns, precision is the number of precision digits.
|
|
For \f3%c\fP, precision defines the number of times to repeat the
|
|
character being formatted.
|
|
For \f3%s\fP, precision defines the maximum number of characters to output;
|
|
-\f3precis\fP also defines the maximum number of characters to output, but
|
|
retains the rightmost \f3precis\fP characters.
|
|
.Tp
|
|
\f3base\fP:
|
|
This is defined after exactly two dots have appeared.
|
|
|
|
For \f3%i\fP, \f3%d\fP, and \f3%u\fP,
|
|
\f3base\fP should be an integer value in the inclusive range \f3[2,64]\fP
|
|
and defines a conversion base.
|
|
If \f3base\fP is not in this range, it is defined to be \f310\fP.
|
|
The digits to represent numbers are:
|
|
|
|
.nf
|
|
.ft 5
|
|
01234567890
|
|
abcdefghijklmnopqrstuvwxyz
|
|
ABCDEFGHIJKLMNOPQRSTUVWXYZ @_
|
|
.ft 1
|
|
.fi
|
|
|
|
For \f3%s\fP and \f3%c\fP, \f3base\fP defines a separator.
|
|
Then, for \f3%s\fP, the input argument is taken to be a NULL-terminated array of strings
|
|
while, for \f3%c\fP, this is a null-terminated array of characters.
|
|
The strings or characters will be formatted one of a time based
|
|
on the usual width and precision rules.
|
|
After each formatted string or character, except for the last one,
|
|
the separator \f3base\fP is output if it is a non-zero.
|
|
|
|
There are further restrictions on the syntax of \f3%s\fP and \f3%c\fP when
|
|
a separator is defined.
|
|
Below are the legitimate sequences for \f3%s\fP and \f3%c\fP after the second dot:
|
|
|
|
.nf
|
|
\f3 s c\fP
|
|
\f3 *s *c\fP
|
|
\f3 \fP\fIz\fP\f3s \fP\fIz\fP\f3c\fP
|
|
.fi
|
|
|
|
In the first case, no separator is defined so \f3base\fP is set to zero.
|
|
In the second case, \f3base\fP is obtained from the argument list.
|
|
In the third case, the character \fIz\fP
|
|
must be non-alphanumeric and \f3base\fP will be set to this character.
|
|
|
|
The below example shows both the call and the result
|
|
of printing a \f3NULL\fP-terminated array
|
|
of three strings \f3apple\fP, \f3orange\fP, and \f3grape\fP:
|
|
|
|
.nf
|
|
.ft 5
|
|
sfprintf(sfstdout,"|%8..:s|",list);
|
|
| apple: orange: grape|
|
|
.ft 1
|
|
.fi
|
|
|
|
.Tp
|
|
\f3(extfdata)\fP:
|
|
This defines a string \f3extfdata\fP
|
|
to be passed to the extension function \f3Sffmt_t.extf\fP.
|
|
Parentheses shall be balanced.
|
|
If \f3extfdata\fP is \f3*\fP, the string is obtained from the argument list.
|
|
|
|
.PP
|
|
.Ss " int sfscanf(Sfio_t* f, const char* format, ...)"
|
|
.Ss " int sfsscanf(const char* s, const char* format, ...)"
|
|
.Ss " int sfvsscanf(const char* s, const char* format, va_list args)"
|
|
.Ss " int sfvscanf(Sfio_t* f, const char* format, va_list args)"
|
|
These functions scan data items.
|
|
\f3sfscanf()\fP scans from the input stream \f3f\fP
|
|
while \f3sfsscanf()\fP and \f3sfvsscanf()\fP
|
|
scan from the null-terminated string \f3s\fP.
|
|
\f3sfvscanf()\fP is the underlying primitive that performs the actual scanning.
|
|
Item types are determined from patterns in string \f3format\fP.
|
|
These functions return
|
|
the number of items successfully scanned or \f3-1\fP on error.
|
|
.PP
|
|
A white space character (blank, tab, or new-line) in \f3format\fP
|
|
normally matches a maximal sequence of input white space characters.
|
|
However, if the input stream is in \f3SF_LINE\fP mode (see \f3sfset()\fP),
|
|
a new-line character only matches white spaces up to an input new-line character.
|
|
This is useful to avoid blocking when scanning typed inputs.
|
|
.PP
|
|
The standard scan patterns are:
|
|
\f3i, d, u, o, x, X, p, n, f, e, E, g, G, c, %, s, []\fP and \f3!\fP.
|
|
Except for \f3!\fP which shall be described below,
|
|
see the ANSI C specification of \f3fscanf(3)\fP for details on other patterns.
|
|
Let \f3z\fP be some pattern type. A formatting pattern is specified as below:
|
|
|
|
.nf
|
|
.ft 5
|
|
%[*][pos$][width][.width.base][(extfdata)][flag]z
|
|
.ft 1
|
|
.fi
|
|
|
|
.Tp
|
|
\f3pos$\fP:
|
|
A pattern can specify which argument in the argument list to use.
|
|
This is done via \f3pos$\fP where \f3pos\fP is the argument position.
|
|
Arguments are numbered so that the first argument after \f3format\fP is at position 1.
|
|
If \f3pos\fP is not specified, the argument following the most recently used one
|
|
will be used.
|
|
The pattern \f3%!\fP (see below) cannot be used subsequent to a usage of \f3pos$\fP.
|
|
.Tp
|
|
\f3*:\fP
|
|
This discards the corresponding scanned item.
|
|
.Tp
|
|
\f3width\fP and \f3base\fP:
|
|
\f3width\fP defines the maximum number of bytes to scan
|
|
and \f3base\fP defines the base of an integral value being scanned.
|
|
The `.' (dot) notation also allows specifying a `*' (star) to obtain
|
|
the value from the argument list. The below example specifies scanning
|
|
4 bytes to obtain the value of an integer in base 10. At the end of scanning,
|
|
the variable \f3v\fP should have the value \f31234\fP.
|
|
|
|
.nf
|
|
.ft 5
|
|
sfsscanf("12345678","%.*.*d", 4, 10, &v);
|
|
.ft 1
|
|
.fi
|
|
|
|
.Tp
|
|
\f3(extfdata)\fP:
|
|
This defines a string \f3extfdata\fP
|
|
to be passed to the extension function \f3Sffmt_t.extf\fP.
|
|
Parentheses shall be balanced.
|
|
If \f3extfdata\fP is \f3*\fP, the string is obtained from the argument list.
|
|
.Tp
|
|
\f3flag:\fP
|
|
This is \f3#\fP, \f3I\fP, or some sequence of \f3h\fP, \f3l\fP, and \f3L\fP.
|
|
|
|
Flag \f3#\fP is significant for pattern \f3%i\fP and \f3%[\fP.
|
|
For \f3%i\fP, it means that the \f3#\fP symbol does not have its usual
|
|
meaning in an input sequence \f3base#value\fP.
|
|
For example, the scanning result of \f3%#i\fP on input \f32#1001\fP is \f32\fP
|
|
and the next \f3sfgetc()\fP call will return \f3#\fP.
|
|
For \f3%[\fP, if the next character in the input stream does not match
|
|
the given scan set of characters, \f3#\fP causes a match to a null string
|
|
instead of a failure.
|
|
|
|
Flag \f3I\fP defines the size or type of the object being formatted.
|
|
There are two cases: (1) \f3I\fP by itself and (2) \f3I\fP
|
|
followed by either a decimal number or `*'.
|
|
|
|
In the first case, for integer and floating point patterns,
|
|
the object type is taken to be the largest appropriate type
|
|
(i.e., one of \f3Sflong_t\fP, \f3Sfulong_t\fP or \f3Sfdouble_t\fP).
|
|
For string patterns such as \f3%s\fP, the flag is ignored.
|
|
|
|
In the second case, a given decimal value would define a size while
|
|
`*' would cause the size to be obtained from the argument list.
|
|
For string patterns such as \f3%s\fP or \f3%[\fP, this size defines the
|
|
length of the buffer to store scanned data.
|
|
Specifying a buffer size only limits the amount of data copied into the buffer.
|
|
Scanned data beyond the buffer limit will be discarded.
|
|
For integer and floating point patterns,
|
|
the size is used to select a type from one of the below lists as
|
|
indicated by the conversion specifier:
|
|
|
|
.nf
|
|
.ft 5
|
|
Sflong_t, long, int, short
|
|
Sfulong_t, unsigned long, unsigned int, unsigned short
|
|
Sfdouble_t, double, float
|
|
.ft 1
|
|
.fi
|
|
|
|
The selection algorithm always matches types from left to right in any given list.
|
|
Although selection is generally based on sizes in bytes,
|
|
for compatibility with Microsoft-C, the size 64
|
|
is matched with an appropriate type with the same number of bits, if any.
|
|
If the given size does not match any of the listed types,
|
|
it shall match one of \f3int\fP, \f3unsigned int\fP, and \f3double\fP
|
|
as indicated by the formatting pattern.
|
|
|
|
Below are examples of using the \f3I\fP flag.
|
|
The first example scans a 64-bit integer.
|
|
The second scans some floating point value
|
|
whose size is explicitly computed and given.
|
|
The last example scans a string into a buffer with the given size 128.
|
|
Note that if the scanned string is longer than 127, only the first 127
|
|
bytes shall be copied into the buffer. The rest of the scanned data
|
|
shall be discarded.
|
|
|
|
.nf
|
|
.ft 5
|
|
sfscanf(sfstdin,"%I64d", &int64_obj);
|
|
sfscanf(sfstdin,"%I*f", sizeof(float_obj), &float_obj);
|
|
sfscanf(sfstdin,"%I*s", 128, buffer);
|
|
.ft 1
|
|
.fi
|
|
|
|
Flags \f3h\fP, \f3l\fP, and \f3L\fP are the ANSI C conventions
|
|
for indicating the type of a scanned element.
|
|
For example, \f3%hd\fP means scanning a \f3short int\fP.
|
|
The flags \f3ll\fP and \f3L\fP mean respectively scanning an
|
|
integer or a floating point value with largest size
|
|
(i.e., \f3Sflong_t\fP or \f3Sfdouble_t\fP).
|
|
.PP
|
|
The \f3%i\fP, \f3%d\fP and \f3%u\fP patterns scan numbers in bases
|
|
from \f32\fP to \f364\fP.
|
|
\f3%i\fP scans integral values in self-describing formats.
|
|
Except for octal, decimal and hexadecimal numbers with the usual formats,
|
|
numbers in general bases are assumed to be of the form: \fIbase#value\fP
|
|
where \fIbase\fP is a number in base 10 and \fIvalue\fP
|
|
is a number in the given base.
|
|
For example, \f32#1001\fP is the binary representation of the decimal value \f39\fP.
|
|
If \fIbase\fP is \f336\fP or less,
|
|
the digits for \fIvalue\fP can be any combination of \f3[0-9], [a-z], [A-Z]\fP
|
|
where upper and lower case digits are not distinguishable.
|
|
If \fIbase\fP is larger than \f336\fP, the set of digits is:
|
|
|
|
.nf
|
|
.ft 5
|
|
0123456789
|
|
abcdefghijklmnopqrstuvwxyz
|
|
ABCDEFGHIJKLMNOPQRSTUVWXYZ @_
|
|
.ft 1
|
|
.fi
|
|
|
|
.PP
|
|
.Ss "BUFFERING, SYNCHRONIZATION"
|
|
.PP
|
|
.Ss " Void_t* sfsetbuf(Sfio_t* f, Void_t* buf, size_t size)"
|
|
This function changes the buffering scheme for the stream \f3f\fP.
|
|
The stream will be synchronized before any buffer modification.
|
|
If a new buffer is successfully set and the old buffer has not been freed,
|
|
\f3sfsetbuf()\fP returns the old buffer. Otherwise, it returns \f3NULL\fP.
|
|
After a \f3sfsetbuf()\fP call,
|
|
\f3sfvalue()\fP returns the size of the returned buffer.
|
|
|
|
Sfio attempts to read data in blocks likely to be serviced fast by the file system.
|
|
This means block sizes being multiples of a suitable alignment value
|
|
(e.g., 512, 1024 or 8192). By default, the alignment value
|
|
is computed via some internal mechanism depending on the local platform but
|
|
it can also be explicitly set via the call \f3sfsetbuf(f, (Void_t*)f, size)\fP.
|
|
|
|
In invocations of \f3sfsetbuf()\fP other than the above case,
|
|
the \f3size\fP argument is treated as follows:
|
|
.Tp
|
|
\f3size == SF_UNBOUND\fP:
|
|
Sfio will pick a suitable buffer size.
|
|
If \f3buf\fP is \f3NULL\fP,
|
|
Sfio will also pick a suitable buffering scheme (such as memory mapping).
|
|
If \f3buf\fP is not \f3NULL\fP, its actual value is ignored
|
|
but the buffer will be allocated via \f3malloc(3)\fP.
|
|
This can be used to avoid memory mapping.
|
|
.Tp
|
|
\f3size > 0\fP:
|
|
This is the suggested size to use for buffering or memory mapping.
|
|
If \f3buf\fP is \f3NULL\fP,
|
|
Sfio will pick a suitable buffering scheme as discussed above.
|
|
If \f3buf\fP is not \f3NULL\fP, then \f3buf\fP and \f3size\fP determine
|
|
a buffer of the given size.
|
|
.Tp
|
|
\f3size == 0\fP:
|
|
If \f3buf\fP is \f3NULL\fP, the stream will be unbuffered.
|
|
If \f3buf\fP is not \f3NULL\fP,
|
|
\f3sfsetbuf()\fP simply returns the stream buffer.
|
|
In this case, no attempt will be made to synchronize the stream.
|
|
|
|
.Ss " int sfsync(Sfio_t* f)"
|
|
This function synchronizes the logical and physical views of stream \f3f\fP.
|
|
It returns a negative value for failure and \f30\fP for success.
|
|
|
|
For a \f3SF_WRITE\fP stream, synchronization means to write out any buffered data.
|
|
For a seekable \f3SF_READ\fP file stream,
|
|
the physical file position is aligned with the logical stream position and,
|
|
if \f3SF_SHARE\fP is on, buffered data is discarded.
|
|
If \f3f\fP is \f3NULL\fP, all streams are synchronized.
|
|
If \f3f\fP is the base of a stream stack (see \f3sfstack()\fP),
|
|
all stacked streams are synchronized.
|
|
Note that a stacked stream can only be synchronized this way.
|
|
If \f3f\fP is in a pool (see \f3sfpool()\fP) but not being the head,
|
|
the pool head is synchronized.
|
|
|
|
If \f3f\fP has flag \f3SF_IOCHECK\fP, the \f3SF_SYNC\fP event is raised
|
|
before and after synchronization. See \f3sfdisc()\fP for details.
|
|
|
|
.Ss " int sfpoll(Sfio_t** flist, int n, int timeout)"
|
|
This function polls a set of streams to see if I/O operations
|
|
can be performed on them without blocking.
|
|
This is useful for multiplexing I/O over a set of streams.
|
|
If a stream has a discipline, the exception function may be called
|
|
before and after the stream is polled (see \f3sfdisc()\fP for details).
|
|
After a successful \f3sfpoll()\fP call,
|
|
for each ready stream \f3f\fP, \f3sfvalue(f)\fP returns
|
|
a bit combination of \f3SF_READ\fP and \f3SF_WRITE\fP to tell which I/O
|
|
mode is available. If \f3SF_READ\fP is available, an attempt to read
|
|
a byte will not block. If \f3SF_WRITE\fP is available,
|
|
an attempt to flush will not block.
|
|
\f3sfpoll()\fP returns the number of ready streams or \f3-1\fP on failure.
|
|
.Tp
|
|
\f3flist\fP and \f3n\fP:
|
|
\f3flist\fP is an array of \f3n\fP streams to be polled.
|
|
Upon return, ready streams are moved to the front
|
|
of \f3flist\fP in the same relative order.
|
|
.Tp
|
|
\f3timeout\fP:
|
|
This defines an elapse time in milliseconds
|
|
to wait to see if any stream is ready for I/O.
|
|
If \f3timeout\fP is negative, \f3sfpoll()\fP will block until some stream become ready.
|
|
Note that \f3SF_STRING\fP and normal file streams never block
|
|
and are always ready for I/O.
|
|
If a stream with discipline is being polled and
|
|
its readiness is as yet undetermined (e.g., empty buffer,)
|
|
the discipline exception function will be called with \f3SF_DPOLL\fP
|
|
before querying the operating system.
|
|
|
|
.Ss " Sfio_t* sfpool(Sfio_t* f, Sfio_t* poolf, int mode)"
|
|
This function manipulates pools of streams.
|
|
In a pool, only one stream is at the head and can have buffered data.
|
|
All other streams in the pool will be synchronized.
|
|
A stream becomes head when it is used for some I/O operation.
|
|
\f3sfpool()\fP returns \f3NULL\fP on failure.
|
|
.Tp
|
|
\f3f\fP and \f3poolf\fP:
|
|
If \f3f\fP is \f3NULL\fP,
|
|
\f3sfpool()\fP simply returns the head of the pool containing \f3poolf\fP.
|
|
If \f3f\fP is not \f3NULL\fP and \f3poolf\fP is \f3NULL\fP,
|
|
\f3f\fP is deleted from its pool.
|
|
In this case, if no other stream from the same pool can become head,
|
|
\f3sfpool()\fP will return \f3NULL\fP; otherwise, it returns some stream
|
|
from the remainder of the pool.
|
|
If both \f3f\fP and \f3poolf\fP are not \f3NULL\fP,
|
|
\f3f\fP is moved from its current pool (if any)
|
|
into the same pool with \f3poolf\fP.
|
|
In this case, \f3poolf\fP is returned.
|
|
.Tp
|
|
\f3mode\fP:
|
|
If \f3poolf\fP is already in a pool, \f3mode\fP is ignored.
|
|
Otherwise, \f3mode\fP should be \f30\fP or \f3SF_SHARE\fP.
|
|
A \f3SF_SHARE\fP pool contains streams with \f3SF_WRITE\fP mode.
|
|
In addition, on change to a new head stream,
|
|
buffered write data of the current head
|
|
is transferred to the new head.
|
|
|
|
.Ss " int sfpurge(Sfio_t* f)"
|
|
This function discards all buffered data
|
|
unless \f3f\fP is a \f3SF_STRING\fP stream.
|
|
Note that if \f3f\fP is a \f3SF_READ\fP stream based on an unseekable device,
|
|
purged data will not be recoverable.
|
|
If \f3f\fP is a \f3sfpopen\fP-stream opened for both read and write,
|
|
data of both the read and write pipe ends will be purged
|
|
(see \f3sfset()\fP to selectively turn off read or write mode
|
|
if one set of data is to be preserved).
|
|
After purging, if \f3f\fP has flag \f3SF_IOCHECK\fP,
|
|
the event \f3SF_PURGE\fP is raised.
|
|
\f3sfpurge()\fP returns \f3-1\fP for failure and \f30\fP for success.
|
|
|
|
.PP
|
|
.Ss "DISCIPLINE, EVENT-HANDLING"
|
|
.PP
|
|
A file stream uses the system calls \f3read(2)\fP, \f3write(2)\fP
|
|
and \f3lseek(2)\fP to read, write and position in the underlying file.
|
|
Disciplines enable application-defined I/O methods including exception handling and
|
|
data pre/post-processing.
|
|
|
|
.Ss " Sfdisc_t* sfdisc(Sfio_t* f, Sfdisc_t* disc)"
|
|
Each stream has a discipline stack whose bottom is a virtual discipline
|
|
representing the actual system calls.
|
|
\f3sfdisc()\fP manipulates the discipline stack of stream \f3f\fP.
|
|
\f3f\fP will be synchronized before any discipline stack manipulation.
|
|
After a successful discipline stack manipulation,
|
|
the stream I/O position (see \f3sfseek()\fP and \f3sftell()\fP)
|
|
and extent (see \f3sfsize()\fP) are updated
|
|
to reflect that defined by the top discipline.
|
|
\f3sfdisc()\fP returns \f3NULL\fP on failure.
|
|
|
|
If the value of \f3disc\fP is identical to the value of \f3f\fP,
|
|
then the top discipline on the discipline
|
|
stack is returned without any further action.
|
|
An application can then use this feature of \f3sfdisc()\fP
|
|
and the field \f3disc\fP (below) of the discipline structure
|
|
to traverse the entire discipline stack of a stream \f3f\fP as follows:
|
|
|
|
.nf
|
|
.ft 5
|
|
for(disc = sfdisc(f, (Sfdisc_t*)f); disc; disc = disc->disc)
|
|
.ft 1
|
|
.fi
|
|
|
|
If \f3disc\fP is \f3SF_POPDISC\fP or \f3(Sfdisc_t*)0\fP,
|
|
the top element of the stack, if any, is popped and its address is returned.
|
|
Otherwise, \f3disc\fP is pushed onto the discipline stack.
|
|
In this case, if successful, \f3sfdisc()\fP returns
|
|
the discipline that was pushed down.
|
|
|
|
Note that a discipline can be used on only one stream at a time.
|
|
An application should take care to allocate different discipline
|
|
structures for use with different streams.
|
|
A discipline structure is of the type \f3Sfdisc_t\fP which
|
|
contains the following public fields:
|
|
|
|
.nf
|
|
.ft 5
|
|
Sfread_f readf;
|
|
Sfwrite_f writef;
|
|
Sfseek_f seekf;
|
|
Sfexcept_f exceptf;
|
|
Sfdisc_t* disc;
|
|
.ft 1
|
|
.fi
|
|
|
|
.PP
|
|
The first three fields of \f3Sfdisc_t\fP specify alternative I/O functions.
|
|
If any of them is \f3NULL\fP, it is inherited
|
|
from a discipline pushed earlier on the stack.
|
|
Note that a file stream always
|
|
has \f3read(2)\fP, \f3write(2)\fP, \f3lseek(2)\fP and \f3NIL(Sfexcept_f)\fP
|
|
as the \fIlogical bottom discipline\fP.
|
|
Arguments to I/O discipline functions
|
|
have the same meaning as that of the
|
|
functions \f3sfrd()\fP, \f3sfwr()\fP and \f3sfsk()\fP described below.
|
|
.PP
|
|
The exception function, \f3(*exceptf)()\fP announces exceptional events during
|
|
I/O operations.
|
|
It is called as \f3(*exceptf)(Sfio_t* f, int type, Void_t* value, Sfdisc_t* disc)\fP.
|
|
Unless noted otherwise, the return value of \f3(*exceptf)()\fP is used as follows:
|
|
.Tp
|
|
\f3<0\fP:
|
|
The on-going operation shall terminate.
|
|
.Tp
|
|
\f3>0\fP:
|
|
If the event was raised due to an I/O error,
|
|
the error has been repaired and the on-going operation shall continue normally.
|
|
For some events, e.g., \f3SF_DPOLL\fP, the return value may also have
|
|
additional meanings.
|
|
.Tp
|
|
\f3=0\fP:
|
|
The on-going operation performs default actions with respect to the raised event.
|
|
For example, on a reading error or reaching end of file, the top stream of a stack
|
|
will be popped and closed and the on-going operation continue with the new top
|
|
stream.
|
|
.PP
|
|
The argument \f3type\fP of \f3(*exceptf)()\fP
|
|
identifies the particular exceptional event:
|
|
.Tp
|
|
\f3SF_LOCKED\fP:
|
|
The stream cannot be accessed.
|
|
Note that this lock state is not related to the mutex lock
|
|
that protects a stream from multiple accesses by different threads
|
|
(see section THREAD SAFETY). Rather, the stream was frozen by
|
|
certain operations such as \f3sfreserve()\fP or \f3sfstack()\fP.
|
|
Thus, a stream can be in this state even if the application is single-threaded.
|
|
.Tp
|
|
\f3SF_READ\fP, \f3SF_WRITE\fP:
|
|
These events are raised around reading and writing operations.
|
|
|
|
If \f3SF_IOCHECK\fP is on, \f3SF_READ\fP and \f3SF_WRITE\fP
|
|
are raised immediately before \f3read(2) and write(2)\fP calls.
|
|
In this case, \f3*((ssize_t*)value)\fP is the amount of data to be processed.
|
|
The return value of \f3(*exceptf)()\fP, if negative,
|
|
indicates that the stream is not ready for I/O
|
|
and the calling operation will abort with failure.
|
|
If it is positive, the stream is ready for I/O
|
|
but the amount should be restricted to the amount specified by this value.
|
|
If the return value is zero, the I/O operation is carried out normally.
|
|
|
|
\f3SF_READ\fP and \f3SF_WRITE\fP are also raised on operation failures.
|
|
In such a case, \f3*((ssize_t*)value)\fP
|
|
is the return value from the failed operation.
|
|
.Tp
|
|
\f3SF_SEEK\fP:
|
|
This event is raised when a seek operation fails.
|
|
.Tp
|
|
\f3SF_NEW\fP, \f3SF_CLOSING\fP (\f3SF_CLOSE\fP), \f3SF_FINAL\fP:
|
|
These events are raised during a stream closing.
|
|
\f3SF_NEW\fP is raised for a stream about to be closed to be renewed (see \f3sfnew()\fP).
|
|
\f3SF_CLOSING\fP is raised for a stream about to be closed.
|
|
\f3SF_FINAL\fP is raised after a stream has been closed and before
|
|
its space is to be destroyed (see \f3sfclose()\fP).
|
|
For these events, a non-zero return value from \f3(*exceptf)()\fP causes
|
|
\f3sfclose()\fP to return immediately with the same value.
|
|
.Tp
|
|
\f3SF_DPUSH\fP, \f3SF_DPOP\fP, \f3SF_DBUFFER\fP:
|
|
Events \f3SF_DPUSH\fP and \f3SF_DPOP\fP are raised when a
|
|
discipline is about to be pushed or popped.
|
|
\f3(Sfdisc_t*)value\fP is the to-be top discipline, if any.
|
|
|
|
A stream buffer is always synchronized before pushing or popping a discipline.
|
|
If this synchronization fails, \f3SF_DBUFFER\fP will be raised with
|
|
\f3*((size_t*)value)\fP being the amount of data still in the buffer.
|
|
If the return value of \f3exceptf\fP is non-negative,
|
|
the push or pop operation will continue normally;
|
|
otherwise, \f3sfdisc()\fP returns failure.
|
|
.Tp
|
|
\f3SF_DPOLL\fP:
|
|
This event is raised by
|
|
\f3sfpoll()\fP to see if the stream is ready for I/O.
|
|
\f3*((int*)value)\fP indicates a time-out interval to wait.
|
|
A negative return value from the exception function means blocking.
|
|
A zero return value means that \f3sfpoll()\fP should
|
|
query the underlying file descriptor.
|
|
A positive return value means non-blocking. In addition,
|
|
this value will be a bit combination of \f3SF_READ\fP and \f3SF_WRITE\fP
|
|
to indicate what I/O modes are ready.
|
|
.Tp
|
|
\f3SF_READY\fP:
|
|
This event is raised by \f3sfpoll()\fP for each ready stream.
|
|
The third argument to the event handler is an integer composed with
|
|
the two bits \f3SF_READ\fP and \f3SF_WRITE\fP to indicate which
|
|
I/O modes are ready.
|
|
.Tp
|
|
\f3SF_SYNC\fP, \f3SF_PURGE\fP:
|
|
If \f3SF_IOCHECK\fP is set,
|
|
these events are raised respectively for a \f3sfsync()\fP or \f3sfpurge()\fP call.
|
|
In each case, the respective event is raised once before the appropriate
|
|
operation (synchronization or purging) with \f3((int)value)\fP being \f31\fP
|
|
and once after with \f3((int)value)\fP being \f30\fP.
|
|
Note that \f3sfsync()\fP is called for each
|
|
\f3SF_WRITE\fP or \f3SF_SHARE|SF_READ\fP stream on closing.
|
|
|
|
.Tp
|
|
\f3SF_ATEXIT\fP:
|
|
This event is raised for each open stream before the process exits.
|
|
|
|
.Ss " int sfraise(Sfio_t* f, int type, Void_t* data)"
|
|
If \f3f\fP is non-\f3NULL\fP, \f3sfraise()\fP calls all exception handlers
|
|
of \f3f\fP with the event \f3type\fP and associated \f3data\fP.
|
|
If an exception handler returns a non-zero value,
|
|
\f3sfraise()\fP immediate returns the same value.
|
|
Application-defined events should start from the value \f3SF_EVENT\fP
|
|
so as to avoid confusion with system-defined events,
|
|
\f3sfraise()\fP returns \f30\fP on success and \f3-1\fP on failure.
|
|
|
|
If \f3f\fP is \f3NULL\fP, \f3sfraise()\fP iterates over all streams
|
|
and raise events as described above. In this case,
|
|
\f3sfraise()\fP returns \f30\fP on success and a negative value
|
|
on failure. The absolute value of the return value tells how many
|
|
streams failed on raising the given event.
|
|
|
|
.Ss " ssize_t sfrd(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)"
|
|
.Ss " ssize_t sfwr(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)"
|
|
.Ss " Sfoff_t sfsk(Sfio_t* f, Sfoff_t offset, int type, Sfdisc_t* disc)"
|
|
These functions provides safe methods for a discipline I/O function to invoke
|
|
earlier discipline I/O functions and to properly handle exceptions.
|
|
They should not be used in any other context.
|
|
\f3sfrd()\fP and \f3sfwr()\fP return the number of bytes read or written.
|
|
\f3sfsk()\fP returns the new seek position.
|
|
On error, all three functions return a negative value which should be \f3-1\fP
|
|
or the value returned by the exception handler.
|
|
|
|
.PP
|
|
.Ss "STREAM CONTROL"
|
|
.PP
|
|
.Ss " int sfresize(Sfio_t* f, Sfoff_t size)"
|
|
This function resizes the stream \f3f\P so that its extent is \f3size\fP.
|
|
If the stream corresponds to a file, the file size is set to \f3size\fP
|
|
via the system call \f3ftruncate()\fP.
|
|
When a stream is made larger, the new data space is filled with zero's.
|
|
\f3sfresize()\fP returns \f30\fP on success and a negative value on failure.
|
|
|
|
.Ss " int sfset(Sfio_t* f, int flags, int set)"
|
|
This function sets control flags for the stream \f3f\fP.
|
|
It returns the previous set of flags or \f30\fP on error.
|
|
|
|
Settable flags are:
|
|
\f3SF_READ\fP, \f3SF_WRITE\fP, \f3SF_IOCHECK\fP,
|
|
\f3SF_LINE\fP, \f3SF_SHARE\fP, \f3SF_PUBLIC\fP, \f3SF_MALLOC\fP and
|
|
\f3SF_STATIC\fP.
|
|
Note that \f3SF_READ\fP and \f3SF_WRITE\fP can be turned on or off only
|
|
if the stream was opened as \f3SF_READ|SF_WRITE\fP.
|
|
Turning off one of them means that the stream is to be treated exclusively
|
|
in the other mode. It is not possible to turn off both.
|
|
If legal, an attempt to turn on either \f3SF_READ\fP or \f3SF_WRITE\fP
|
|
will cause the stream to be in the given I/O mode.
|
|
.Tp
|
|
\f3set == 0:\fP
|
|
If \f3flags\fP is zero, the current set of flags is simply returned.
|
|
Note that when a stream is first opened, not
|
|
all of its flags are initialized yet (more below). If \f3flags\fP is
|
|
non-zero, an attempt is made to turn off the specified flags.
|
|
.Tp
|
|
\f3set != 0:\fP
|
|
If \f3flags\fP is zero, the stream is initialized if not yet done so.
|
|
Then the current set of flags is returned.
|
|
If \f3flags\fP is non-zero, an attempt is made to turn on the
|
|
specified flags.
|
|
|
|
.Ss " int sfsetfd(Sfio_t* f, int fd)"
|
|
This function changes the file descriptor of \f3f\fP.
|
|
Before a change is realized,
|
|
\f3(*notify)(f,SF_SETFD,newfd)\fP (see \f3sfnotify()\fP) is called.
|
|
\f3sfsetfd()\fP returns \f3-1\fP on failure and the new file descriptor on success.
|
|
.Tp
|
|
\f3fd >= 0\fP:
|
|
If the current file descriptor is non-negative,
|
|
it will be changed using \f3dup(3)\fP to a value larger or equal to \f3fd\fP.
|
|
Upon a successful change, the previous file descriptor will be closed.
|
|
If the current file descriptor is negative, it will be set to \f3fd\fP and
|
|
the stream will be reinitialized.
|
|
.Tp
|
|
\f3fd < 0\fP:
|
|
The stream is synchronized (see \f3sfsync()\fP) and its
|
|
file descriptor will be set to this value.
|
|
Then, except for \f3sfclose()\fP, the stream will be inaccessible
|
|
until a future \f3sfsetfd()\fP call resets the file descriptor to a non-negative value.
|
|
Thus, \f3sfsetfd(f,-1)\fP can be used to avoid closing the file descriptor
|
|
of \f3f\fP when \f3f\fP is closed.
|
|
|
|
.Ss " Sfio_t* sfstack(Sfio_t* base, Sfio_t* top)"
|
|
This function stacks or unstacks stream.
|
|
Every stream stack is identified by a base stream
|
|
via which all I/O operations are performed.
|
|
However, an I/O operation always takes effect on the top stream.
|
|
If the top stream reaches the end of file or
|
|
has an unrecoverable error condition,
|
|
it is automatically popped and closed
|
|
(see also \f3sfdisc()\fP for alternative handling of these conditions).
|
|
.Tp
|
|
\f3base\fP:
|
|
This is the base stream of the stack.
|
|
If it is \f3NULL\fP, \f3sfstack()\fP does nothing and returns \f3top\fP.
|
|
.Tp
|
|
\f3top\fP:
|
|
If this is \f3SF_POPSTACK\fP or \f3(Sfio_t*)0\fP,
|
|
the stack is popped and \f3sfstack()\fP returns the popped stream.
|
|
Otherwise, \f3top\fP is pushed on top of the stack identified by \f3base\fP
|
|
and \f3sfstack()\fP returns the \f3base\fP stream.
|
|
|
|
.Ss " Sfio_t* sfswap(Sfio_t* f1, Sfio_t* f2)"
|
|
This function swaps contents of \f3f1\fP and \f3f2\fP.
|
|
This fails if either stream is in a stream stack but not being a base stream.
|
|
If \f3f2\fP is \f3NULL\fP, a new stream is constructed as a duplicate of \f3f1\fP.
|
|
\f3sfswap()\fP returns \f3f2\fP or \f3f1\fP duplicate on success and
|
|
\f3NULL\fP on failure.
|
|
|
|
.PP
|
|
.Ss "STREAM INFORMATION"
|
|
.PP
|
|
.Ss " Sfoff_t sfsize(Sfio_t* f)"
|
|
This function returns the size of stream \f3f\fP (see \f3sfnew()\fP).
|
|
If \f3f\fP is not seekable or if its size is not determinable,
|
|
\f3sfsize()\fP returns \f3-1\fP.
|
|
|
|
.Ss " Sfoff_t sftell(Sfio_t* f)"
|
|
This function returns the current I/O position in stream \f3f\fP.
|
|
Note that if \f3f\fP is \f3SF_APPEND\fP
|
|
and a writing operation was just performed,
|
|
the current I/O position is at the physical end of file.
|
|
If \f3f\fP is unseekable, \f3sftell\fP returns the number of bytes
|
|
read from or written to \f3f\fP.
|
|
See also \f3sfungetc()\fP.
|
|
|
|
.Ss " ssize_t sfvalue(Sfio_t* f)"
|
|
This function returns the string or buffer length
|
|
for \f3sfreserve()\fP, \f3sfsetbuf()\fP, and \f3sfgetr()\fP.
|
|
|
|
.Ss " int sffileno(Sfio_t* f)"
|
|
This function returns the file descriptor of stream \f3f\fP.
|
|
|
|
.Ss " int sfstacked(Sfio_t* f)"
|
|
This function returns a non-zero value
|
|
if stream \f3f\fP has been stacked.
|
|
|
|
.Ss " int sfeof(Sfio_t* f)"
|
|
.Ss " int sferror(Sfio_t* f)"
|
|
.Ss " int sfclrerr(Sfio_t* f)"
|
|
\f3sfeof()\fP tells whether or not the stream has an end-of-file condition.
|
|
\f3sferror()\fP tells whether or not the stream has an error condition.
|
|
\f3sfclrerr()\fP clears both end-of-file and error conditions.
|
|
The end-of-file and error conditions are also cleared on an I/O operation.
|
|
|
|
.Ss " int sfclrlock(Sfio_t* f)"
|
|
This function restores the stream back to a normal state.
|
|
This means clearing locks and possibly throwing away unprocessed data.
|
|
As such, this operation is unsafe and should be used with care.
|
|
For example, it may be used before a long jump (\f3longjmp(3)\fP)
|
|
out of some discipline I/O function to restore the internal stream states.
|
|
\f3sfclrlock()\fP returns the current set of flags.
|
|
|
|
.Ss " int sfnotify((void(*)notify)(Sfio_t*, int, void*) )"
|
|
This sets a function \f3(*notify)()\fP to be called
|
|
as \f3(*notify)(f, type, data)\fP on various stream events.
|
|
Arguments \f3type\fP and \f3data\fP indicate the reason for the call and accompanying data:
|
|
.Tp
|
|
\f3SF_NEW\fP:
|
|
\f3f\fP is being opened and \f3data\fP is the underlying file descriptor.
|
|
.Tp
|
|
\f3SF_CLOSING\fP (\f3SF_CLOSE\fP):
|
|
\f3f\fP is the stream being closed and \f3data\fP is the underlying file descriptor.
|
|
.Tp
|
|
\f3SF_SETFD\fP:
|
|
The file descriptor of \f3f\fP is being changed to the one
|
|
defined by \f3data\fP (see \f3sfsetfd()\fP).
|
|
.Tp
|
|
\f3SF_READ\fP:
|
|
An attempt to change \f3f\fP to read mode failed.
|
|
\f3data\fP is the file descriptor of the stream.
|
|
.Tp
|
|
\f3SF_WRITE\fP:
|
|
An attempt to change \f3f\fP to write mode failed.
|
|
\f3data\fP is the file descriptor of the stream.
|
|
.Tp
|
|
\f3SF_MTACCESS\fP:
|
|
When a notifying function was registered (see \f3sfnotify()\fP),
|
|
every Sfio call on a stream with flag \f3SF_MTSAFE\fP will
|
|
invoke the notifying function
|
|
once on entry after the stream is locked
|
|
as \f3(*notify)(f, SF_MTACCESS, Sfio_t** fp), and
|
|
once on return before unlocking as
|
|
as \f3(*notify)(f, SF_MTACCESS, (Sfio_t**)0).
|
|
In the call entry case,
|
|
the notification function could use the argument \f3fp\fP
|
|
to set a stream that would be used for performing the actual I/O operation.
|
|
In this way, certain global streams such as the standard streams \f3sfstdin\fP,
|
|
\f3sfstdout\fP and \f3sfstderr\fP could be made to act differently when used
|
|
in different streams.
|
|
|
|
.Ss " int sfwalk(Sfwalk_f walkf, Void_t* data, int type)"
|
|
This function invokes \f3(*walkf)(f, data)\fP on every open stream \f3f\fP
|
|
whose flags as defined by \f3sfset()\fP contains all bit flags given in \f3type\fP.
|
|
On such a call, if the return value is negative, \f3sfwalk()\fP will terminate.
|
|
\f3sfwalk()\fP returns 0 if no stream was processed.
|
|
Otherwise, it returns the return value from the last invocation of \f3walkf()\fP.
|
|
|
|
As an example, the call \f3sfwalk(walkf, data, SF_READ)\fP will iterate over all streams
|
|
opened for reading. Similarly, \f3sfwalk(walkf, data, SF_READ|SF_WRITE)\fP
|
|
iterates over all streams opened for both reading and writing.
|
|
Lastly, \f3sfwalk(walkf, data, 0)\fP iterates over all streams.
|
|
|
|
.PP
|
|
.Ss "MISCELLANEOUS FUNCTIONS"
|
|
.PP
|
|
.Ss " ssize_t sfmaxr(ssize_t maxr, int set)"
|
|
Certain records may require too much memory for storage, thus, causing
|
|
undesirable side effects. Therefore, the library normally bounds the amount
|
|
of memory used by \f3sfgetr()\fP. A different memory bound
|
|
can be set via \f3sfmaxr()\fP. While a positive \f3maxr\fP hints to \f3sfgetr()\fP
|
|
to use only about that much memory to construct a record, a non-positive bound
|
|
allows \f3sfgetr()\fP to use as much memory as necessary.
|
|
\f3sfmaxr()\fP sets the value only if \f3set\fP is non-zero.
|
|
It returns the value before setting or the current value if not setting.
|
|
|
|
.Ss " ssize_t sfslen()"
|
|
This function returns the length of a string just constructed
|
|
by \f3sfsprintf()\fP or \f3sfprints()\fP. See also \f3sfvalue()\fP.
|
|
|
|
.Ss " int sfulen(Sfulong_t v)"
|
|
.Ss " int sfllen(Sflong_t v)"
|
|
.Ss " int sfdlen(Sfdouble_t v)"
|
|
These functions return respectively the number of bytes required to code the
|
|
\f3Sfulong_t\fP, \f3Sflong_t\fP or \f3Sfdouble_t\fP value \f3v\fP by \f3sfputu()\fP,
|
|
\f3sfputl()\fP or \f3sfputd()\fP.
|
|
|
|
.Ss " ssize_t sfpkrd(int fd, char* buf, size_t n, int rsc, long tm, int action)"
|
|
This function acts directly on the file descriptor \f3fd\fP.
|
|
It does a combination of peeking on incoming data and a time-out read.
|
|
Upon success, it returns the number of bytes received.
|
|
A return value of \f30\fP means that the end-of-file condition has been detected.
|
|
A negative value represents an error.
|
|
.Tp
|
|
\f3buf\fP, \f3n\fP:
|
|
These define a buffer and its size to read data into.
|
|
.Tp
|
|
\f3rsc\fP:
|
|
If \f3>=0\fP, this defines a record separator.
|
|
If the last returned byte is not the record separator, then
|
|
the read data did not contain a complete record. Otherwise,
|
|
it contains one or more records.
|
|
See also \f3action\fP below.
|
|
.Tp
|
|
\f3tm\fP:
|
|
If \f3>=0\fP, this defines a time interval in milliseconds to wait for incoming data.
|
|
.Tp
|
|
\f3action\fP:
|
|
If \f3action > 0\fP, \f3sfpkrd()\fP will peek on incoming data but
|
|
will not read past it. Therefore, a future \f3sfpkrd()\fP or \f3read(2)\fP will see
|
|
the same data again.
|
|
If \f3action <= 0\fP, \f3sfpkrd()\fP will not peek and there are two cases.
|
|
If \f3rsc < 0\fP, an attempt is made to read \f3n\fP bytes.
|
|
If \f3rsc >= 0\fP, an attempt is made to read one record.
|
|
|
|
.PP
|
|
.Ss "FULL STRUCTURE SFIO_T"
|
|
.PP
|
|
.Ss " #include <sfio_t.h>"
|
|
Most applications based on Sfio only need to include
|
|
the header file \f3sfio.h\fP which defines an abbreviated \f3Sfio_t\fP
|
|
structure without certain fields private to Sfio.
|
|
However, there are times (e.g., debugging)
|
|
when an application may require more details about the full \f3Sfio_t\fP structure.
|
|
In such cases, the header file \f3sfio_t.h\fP can be used in place of \f3sfio.h\fP.
|
|
Note that an application doing this will become sensitive to changes
|
|
in the internal architecture of Sfio.
|
|
|
|
.Ss " #define SFNEW(buf,size,file,flags,disc)"
|
|
This macro function is defined in \f3sfio_t.h\fP for
|
|
use in static initialization of an \f3Sfio_t\fP structure.
|
|
It requires five arguments:
|
|
.Tp
|
|
\f3buf, size\fP:
|
|
These define a buffer and its size.
|
|
.Tp
|
|
\f3file\fP:
|
|
This defines the underlying file descriptor if any.
|
|
.Tp
|
|
\f3flags\fP:
|
|
This is composed from bit flags described above.
|
|
.Tp
|
|
\f3disc\fP:
|
|
This defines a discipline if any.
|
|
|
|
.PP
|
|
.Ss "EXAMPLE DISCIPLINES"
|
|
.PP
|
|
The below functions create disciplines and insert them into
|
|
the given streams \f3f\fP. These functions return \f30\fP
|
|
on success and \f3-1\fP on failure.
|
|
|
|
.Ss "int sfdcdio(Sfio_t* f, size_t bufsize)"
|
|
This creates a discipline that uses the direct IO feature
|
|
available on file systems such as SGI's XFS to speed up IO.
|
|
The argument \f3bufsize\fP suggests a buffer size to use for data transfer.
|
|
|
|
.Ss "int sfdcdos(Sfio_t* f)"
|
|
This creates a discipline to read DOS text files.
|
|
It basically transforms pairs of \er\en to \en.
|
|
|
|
.Ss "int sfdcfilter(Sfio_t* f, const char* cmd)"
|
|
This creates a discipline that sends data from \f3f\fP
|
|
to the given command \f3cmd\fP to process, then reads back the processed data.
|
|
|
|
.Ss "int sfdcseekable(Sfio_t* f)"
|
|
This creates a discipline that makes an unseekable reading stream seekable.
|
|
|
|
.Ss "int sfdcslow(Sfio_t* f)"
|
|
This creates a discipline that makes all Sfio operations return immediately
|
|
on interrupts. This is useful for dealing with slow devices.
|
|
|
|
.Ss "int sfdcsubstream(Sfio_t* f, Sfio_t* parent, Sfoff_t offset, Sfoff_t extent)"
|
|
This creates a discipline that makes \f3f\fP acts as if it
|
|
corresponds exactly to the subsection of \f3parent\fP
|
|
starting at \f3offset\fP with size \f3extent\fP.
|
|
|
|
.Ss "int sfdctee(Sfio_t* f, Sfio_t* tee)"
|
|
This creates a discipline that copies to the stream \f3tee\fP
|
|
any data written to \f3f\fP.
|
|
|
|
.Ss "int sfdcunion(Sfio_t* f, Sfio_t** array, int n)"
|
|
This creates a discipline that makes \f3f\fP act as if it is
|
|
the concatenation of the \f3n\fP streams given in \f3array\fP.
|
|
|
|
.Ss "int sfdclzw(Sfio_t* f)"
|
|
This creates a discipline that would decompress data in \f3f\fP.
|
|
The stream \f3f\fP should have data from a source compressed by
|
|
the Unix \fBcompress\fP program.
|
|
|
|
.Ss "int sfdcgzip(Sfio_t* f, int opt)"
|
|
This creates a discipline for reading/writing data compressed by zlib.
|
|
The argument \f3opt\fP defines the optimization level.
|
|
|
|
.PP
|
|
.Ss "STDIO-COMPATIBILITY"
|
|
.PP
|
|
Sfio provides compatibility functions for all various popular
|
|
Stdio implementations at source and binary level.
|
|
The source Stdio-compatibility interface
|
|
provides the header file \f3stdio.h\fP that defines
|
|
a set of macros or inlined functions to map Stdio calls to Sfio ones.
|
|
This mapping may benignly extend or change the meaning of certain
|
|
original Stdio operations. For example, the Sfio's version of
|
|
\f3popen()\fP allows a coprocess to be opened for both reading and writing
|
|
unlike the original call which only allows a coprocess to be opened for a single mode.
|
|
Similarly, the Sfio's \f3fopen()\fP call can be used to create
|
|
string streams in addition to file streams.
|
|
.PP
|
|
The standard streams \f3stdin\fP, \f3stdout\fP and \f3stderr\fP
|
|
are mapped via \f3#define\fP to \f3sfstdin\fP, \f3sfstdout\fP and \f3sfstderr\fP.
|
|
The latter are typically declared of the type \f3Sfio_t*\fP.
|
|
Certain older Stdio applications require these to be declared
|
|
as addresses of structures so that static initializations of
|
|
the sort ``\f3FILE*\ f\ =\ stdin;\fP'' would work.
|
|
Such applications should use the compile time flag \f3SF_FILE_STRUCT\fP
|
|
to achieve the desired effect.
|
|
.PP
|
|
The binary Stdio-compatibility libraries, \f3libstdio.a\fP and \f3libstdio-mt.a\fP,
|
|
provide complete implementations of Stdio functions suitable
|
|
for linking applications already compiled with native header \f3stdio.h\fP.
|
|
These functions are also slightly altered or extended
|
|
as discussed above.
|
|
.PP
|
|
Below are the supported Stdio functions:
|
|
.PP
|
|
.nf
|
|
.ft 5
|
|
FILE* fopen(const char* file, const char* mode);
|
|
FILE* freopen(const char* file, const char* mode, FILE* stream);
|
|
FILE* fdopen(int filedesc, const char* mode);
|
|
FILE* popen(const char* command, const char* mode);
|
|
FILE* tmpfile();
|
|
int fclose(FILE* stream);
|
|
int pclose(FILE* stream);
|
|
|
|
void flockfile(FILE* stream)
|
|
int ftrylockfile(FILE* stream)
|
|
void funlockfile(FILE* stream)
|
|
|
|
void setbuf(FILE* stream, char* buf);
|
|
int setvbuf(FILE* stream, char* buf, int mode, size_t size);
|
|
void setbuffer(FILE* stream, char* buf, size_t size);
|
|
int setlinebuf(FILE* stream);
|
|
int fflush(FILE* stream);
|
|
int fpurge(FILE* stream);
|
|
|
|
int fseek(FILE* stream, long offset, int whence);
|
|
void rewind(FILE* stream);
|
|
int fgetpos(FILE* stream, fpos_t* pos);
|
|
int fsetpos(FILE* stream, fpos_t* pos);
|
|
long ftell(FILE* stream);
|
|
|
|
int getc(FILE* stream);
|
|
int fgetc(FILE* stream);
|
|
int getchar(void);
|
|
int ungetc(int c, FILE* stream);
|
|
int getw(FILE* stream);
|
|
char* gets(char* s);
|
|
char* fgets(char* s, int n, FILE* stream);
|
|
size_t fread(Void_t* ptr, size_t size, size_t nelt, FILE* stream);
|
|
|
|
int putc(int c, FILE* stream);
|
|
int fputc(int c, FILE* stream);
|
|
int putchar(int c);
|
|
int putw(int w, FILE* stream);
|
|
int puts(const char* s, FILE* stream);
|
|
int fputs(const char* s, FILE* stream);
|
|
size_t fwrite(const Void_t* ptr, size_t size, size_t nelt, FILE* stream);
|
|
|
|
int fscanf(FILE* stream, const char* format, ...);
|
|
int vfscanf(FILE* stream, const char* format, va_list args);
|
|
int _doscan(FILE* stream, const char* format, va_list args);
|
|
int scanf(const char* format, ...);
|
|
int vscanf(const char* format, va_list args);
|
|
int sscanf(const char* s, const char* format, ...);
|
|
int vsscanf(const char* s, const char* format, va_list args);
|
|
|
|
int fprintf(FILE* stream, const char* format, ...);
|
|
int vfprintf(FILE* stream, const char* format, va_list args);
|
|
int _doprnt(FILE* stream, const char* format, va_list args);
|
|
int printf(const char* format, ...);
|
|
int vprintf(const char* format, va_list args);
|
|
int sprintf(const char* s, const char* format, ...);
|
|
int snprintf(const char* s, int n, const char* format, ...);
|
|
int vsprintf(const char* s, const char* format, va_list args);
|
|
int vsnprintf(const char* s, int n, const char* format, va_list args);
|
|
|
|
int feof(FILE* stream);
|
|
int ferror(FILE* stream);
|
|
int clearerr(FILE* stream);
|
|
.ft 1
|
|
.fi
|
|
|
|
.PP
|
|
.Ss "RECENT CHANGES"
|
|
.PP
|
|
A few exception types have been added. In particular, exception handlers shall
|
|
be raised with \f3SF_LOCKED\fP on accessing a stream frozen either by
|
|
an ongoing operation or a previous operation (e.g., \f3sfgetr()\fP).
|
|
Before a process exits, the event \f3SF_ATEXIT\fP is raised for each open stream.
|
|
.PP
|
|
A number of disciplines were added for various processing functions.
|
|
Of interests are disciplines to use the direct I/O feature on IRIX 6.2,
|
|
read DOS text files, and decompress files compressed by Unix \fIcompress\fP.
|
|
.PP
|
|
Various new stream and function flags have been added. For example,
|
|
the third argument of \f3sfgetr()\fP is now a set of bit flags and not
|
|
just a three-value object. However, the old semantics of this argument
|
|
of \f3sfgetr()\fP is still supported.
|
|
.PP
|
|
The \f3sfopen()\fP call has been extended so that sfopen(f,NULL,mode) can be
|
|
used to changed the mode of a file stream before any I/O operations.
|
|
This is most useful for changing the modes of the standard streams.
|
|
.PP
|
|
The buffering strategy has been significantly enhanced for streams
|
|
that perform many seek operations. Also, the handling of stream and
|
|
file positions have been better clarified so that applications that
|
|
share file descriptors across streams and/or processes can be sure that
|
|
the file states will be consistent.
|
|
.PP
|
|
The strategy for mapping between Sfio and Stdio streams in the binary
|
|
compatibility package has been significantly enhanced for efficiency.
|
|
For most platforms, the mapping is now constant time per look-up.
|
|
.PP
|
|
The \f3SF_BUFCONST\fP flag was deleted. This is largely unused anyway.
|
|
.PP
|
|
The library can be built for thread-safety. This is based largely on
|
|
POSIX pthread mutexes except for on UWIN where native Windows APIs
|
|
are used.
|
|
.PP
|
|
The functions \f3sfgetm()\fP and \f3sfputm()\fP were added to encode
|
|
unsigned integer values with known ranges.
|
|
.PP
|
|
The flag \f3SF_APPEND\fP is identical to \f3SF_APPENDWR\fP.
|
|
However it conflicts with a different token of the same name
|
|
defined in the system header \f3stat.h\fP of BSDI Unix systems.
|
|
On such systems, we shall not define \f3SF_APPEND\fP and this
|
|
symbol may be removed in a future release.
|
|
.PP
|
|
Similarly, the exception \f3SF_CLOSE\fP is identical to \f3SF_CLOSING\fP.
|
|
However it conflicts with a different token of the same name
|
|
defined in the system header \f3socket.h\fP of AIX Unix systems.
|
|
On such systems, we shall not define \f3SF_CLOSE\fP and this
|
|
symbol may be removed in a future release.
|
|
.PP
|
|
The printing and scanning functions were extended to handle multibyte characters
|
|
and to conform to the C99 standard.
|
|
.PP
|
|
The function \f3sfpoll()\fP was overhauled to make it useful
|
|
for writing servers that must communicate with multiple streams
|
|
without blocking.
|
|
.PP
|
|
The formatting pattern \f3%c\fP for \f3sf*printf\fP was extended
|
|
to allow the flag \f3#\fP to print unprintable character values
|
|
using the C convention. For example, \f3%#c\fP prints the octal value 012
|
|
as \f3\\n\fP.
|
|
|
|
.SH AUTHORS
|
|
Kiem-Phong Vo, kpv@research.att.com,
|
|
.br
|
|
David G. Korn, dgk@research.att.com, and
|
|
.br
|
|
Glenn S. Fowler, gsf@research.att.com.
|