From 7e0f021a9aec35fd8e6725e87e3313b101d26f5e Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sun, 27 Jan 2008 11:37:44 +0100 Subject: Initial import (2.0.2-6) --- reference/C/CONTRIB/SNIP/xfile.c | 200 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100755 reference/C/CONTRIB/SNIP/xfile.c (limited to 'reference/C/CONTRIB/SNIP/xfile.c') diff --git a/reference/C/CONTRIB/SNIP/xfile.c b/reference/C/CONTRIB/SNIP/xfile.c new file mode 100755 index 0000000..7be9d51 --- /dev/null +++ b/reference/C/CONTRIB/SNIP/xfile.c @@ -0,0 +1,200 @@ +/* xfile.c -- implementation for fast line buffered files +** +** Currently (Sat 06-15-1991) XFILEs are for reading CR-LF terminated lines +** from MS-DOS text files. Period. It's not that the method can't be used +** as well for output buffering, or (in some form) for binary files, it's +** that such are handled fast enough to suit me already, whereas text mode +** input performance leaves me wishing for more speed. This attempts to +** solve that problem. +** +** Sun 06-16-1991 -- CR-LF accepted, but so is bare LF now; the extracted +** line does NOT have a NEWLINE at the end anymore (which will likely be +** a mixed blessing...) +** +** The code should be fairly portable: if/when I get around to polishing it +** (and that won't be until I've used it some and am sure it's stable) I'll +** be aiming for near-ANSI portability; for now I'm not pushing so very hard +** for that. +** +** The semantics are a bit odd: the lines are returned in a buffer that the +** XFILE owns, and may be altered by a call to xgetline or xclose. For +** applications that resent this, XFILEs probably aren't a big win anyway, +** but there might be some cases where using XFILE and copying (some) lines +** is still a good idea. The performance with long lines is good: it can +** handle lines the size of the buffer, though it may truncate up to one +** QUANTUM less one bytes "early": this depends on the location of the start +** of the line in the buffer when we begin scanning. In practice, XBUFSIZE +** is probably larger than you'd set for a line buffer size anyway... +** +** INTERNALS: +** +** Reading the first buffer's worth at open time makes the EOF case easier to +** detect. +** +** TO DO: +** +** clean up xgetline! +*/ + +#include +#include +#include "xfile.h" + +#if !defined(__ZTC__) && !defined(__TURBOC__) + static int DOS_OPEN(const char *name, int mode, ...) + { + int hdl; + + if (0 == _dos_open(name, mode, &hdl)) + return hdl; + else return -1; + } + + static int READ(int fd, void *buf, size_t len) + { + unsigned count; + + if (0 == _dos_read(fd, buf, len, &count)) + return count; + else return -1; + } +#endif + +#ifndef XBUFN /* set default # of quanta in buffer, allow -D */ + #define XBUFN 8 +#endif + +#define QUANTUM 512 +#define XBUFSIZE (XBUFN * QUANTUM) + + +/* xopen -- allocate and open an XFILE +** +** NB: currently I'm designing these for READ-ONLY TEXT FILES only: the xopen +** interface may have to be changed... +** +** returns pointer to XFILE of opened file or null pointer on error +** +** ? should it leave a better error description somewhere ? +*/ + +XFILE *xopen(char const *name) +{ + XFILE *f = malloc(sizeof(XFILE) + XBUFSIZE + 1); + int n; + + if (f == 0) + goto error0; + f->buf = (char *)f + sizeof(XFILE); + + if ((f->fd = DOS_OPEN(name, O_RDONLY)) < 0) + goto error1; + + if ((n = READ(f->fd, f->buf, XBUFSIZE)) < 0) + goto error2; + + f->buf[n] = 0; + f->nextChar = f->buf; + return f; + +error2: + CLOSE(f->fd); +error1: + free(f); +error0: + return 0; +} + + +/* +** xclose -- close and deallocate an XFILE +*/ + +void xclose(XFILE *f) +{ + CLOSE(f->fd); + free(f); +} + + +/* +** xgetline -- get the next text line into memory +** +** returns a pointer to the line (a NUL-terminated string) or a null pointer +*/ + +char *xgetline(XFILE *f) +{ + char *s = f->nextChar, *p; + int n; + + for (p = s; *p != 0; ++p) + { + if (*p == '\n') + { + if (s < p && p[-1] == '\r') + p[-1] = 0; + else *p = 0; + f->nextChar = p + 1; + return s; + } + } + + /* + ** end of line not found in buffer -- p points to the sentinel NUL + */ + + if (p == f->buf) /* iff empty, EOF */ + return 0; + + /* + ** move prefix of line to bottom of buffer + */ + + if (s != f->buf) + { + for (p = f->buf; (*p = *s) != 0; ++p, ++s) + ; + s = f->buf; + } + + n = XBUFSIZE - (p - f->buf); + + if (n < QUANTUM) /* insufficent room, break line */ + { + f->nextChar = p; + return s; + } + + n = (n / QUANTUM) * QUANTUM; /* quantize: count to read */ + n = READ(f->fd, p, n); + + /* + ** read error is sort of ignored here... same return as EOF. + ** we'll see if this proves to be sufficent... + */ + + if (n < 0) + { + f->nextChar = f->buf; + f->buf[0] = 0; + return 0; + } + + p[n] = 0; + + for ( ; *p != 0; ++p) + { + if (*p == '\n') + { + if (s < p && p[-1] == '\r') + p[-1] = 0; + else *p = 0; + ++p; + break; + } + } + + f->nextChar = p; + return p == s ? 0 : s; +} -- cgit v1.2.3-54-g00ecf