xfile.c
来自「国外网站上的一些精典的C程序」· C语言 代码 · 共 202 行
C
202 行
/* 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 <stdlib.h>#include <string.h>#include <fcntl.h>#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 == NULL) 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 NULL;}/*** 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 NULL; /* ** 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) /* insufficient 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 sufficient... */ if (n < 0) { f->nextChar = f->buf; f->buf[0] = 0; return NULL; } 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 ? NULL : s;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?