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/srchfile.c | 225 ++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100755 reference/C/CONTRIB/SNIP/srchfile.c (limited to 'reference/C/CONTRIB/SNIP/srchfile.c') diff --git a/reference/C/CONTRIB/SNIP/srchfile.c b/reference/C/CONTRIB/SNIP/srchfile.c new file mode 100755 index 0000000..d55fb88 --- /dev/null +++ b/reference/C/CONTRIB/SNIP/srchfile.c @@ -0,0 +1,225 @@ +/* +** SRCHFILE.C - Functions for searching files +** +** public domain by Bob Stout +** +** Note: Although this snippet demonstrates some useful techniques, even +** the fast text searching algorithm used can't provide particularly +** good performance. Left as an exercise for the user is to perform +** explicit buffering using fread() rather than fgets() as is used +** here. See CHBYTES.C in SNIPPETS for how to perform searches in +** user-managed buffers. +*/ + +#include +#include +#include + +#define SUCCESS 0 + +/* +** Allocate a big buffer, use it to buffer a specified stream +*/ + +static size_t fsetup(FILE *fp, size_t minbuf) +{ + register size_t bufsize; + register char *buffer; + + /* Allocate the largest buffer we can */ + + for (bufsize = 0x4000; bufsize >= minbuf; bufsize >>= 1) + { + if (NULL != (buffer = (char *) malloc(bufsize))) + break; + } + if (NULL == buffer) + return 0; + + /* Use the buffer to buffer the file */ + + if (SUCCESS == setvbuf(fp, buffer, _IOFBF, bufsize)) + return bufsize; + else return 0; +} + +/* +** Search a file for a pattern match (forward) +** +** Arguments: FILE pointer +** pattern to search for +** size of pattern +** find Nth occurance +** +** Returns: -1L if pattern not found +** -2L in case of error +*/ + +long ffsearch(FILE *fp, const char *pattern, const size_t size, int N) +{ + long pos = -2L, tempos = 0L; + char *sbuf, *p; + size_t i, skip; + int ch = 0; + + /* Allocate a search buffer */ + + if (NULL == (sbuf = (char *)malloc(size - 1))) + goto FDONE; + + /* Buffer the file and position us within it */ + + if (0 == fsetup(fp, size)) + goto FDONE; + pos = -1L; + fseek(fp, 0L, SEEK_SET); + + /* Set up for smart searching */ + + if (1 < strlen(pattern) && NULL != (p = strchr(pattern + 1, *pattern))) + skip = p - (char *)pattern; + else skip = strlen(pattern); + + /* Look for the pattern */ + + while (EOF != ch) + { + if (EOF == (ch = fgetc(fp))) + break; + if ((int)*pattern == ch) + { + tempos = ftell(fp); + if (size - 1 > fread(sbuf, sizeof(char), size - 1, fp)) + goto FDONE; + if (SUCCESS == memcmp(sbuf, &pattern[1], size - 1)) + { + if (0 == --N) + { + pos = tempos - 1L; + goto FDONE; + } + } + fseek(fp, tempos + skip, SEEK_SET); + } + } + + /* Clean up and leave */ + +FDONE: + free(sbuf); + return pos; +} + +/* +** Search a file for a pattern match (backwards) +** +** Arguments: FILE pointer +** pattern to search for +** size of pattern +** find Nth occurance +** +** Returns: -1L if pattern not found +** -2L in case of error +*/ + +long rfsearch(FILE *fp, const char *pattern, const size_t size, int N) +{ + long pos = -2L, tempos; + char *sbuf, *p; + size_t i, skip; + int ch = 0; + + /* Allocate a search buffer */ + + if (NULL == (sbuf = (char *)malloc(size - 1))) + goto RDONE; + + /* Buffer the file and position us within it */ + + if (0 == fsetup(fp, size)) + goto RDONE; + pos = -1L; + fseek(fp, -1L, SEEK_END); + tempos = ftell(fp) - strlen(pattern); + + /* Set up for smart searching */ + + if (1 < strlen(pattern) && NULL != (p = strrchr(pattern + 1, *pattern))) + skip = strlen(pattern) - (p - (char *)pattern); + else skip = strlen(pattern); + + /* Look for the pattern */ + + while (0L <= tempos) + { + fseek(fp, tempos, SEEK_SET); + if (EOF == (ch = fgetc(fp))) + break; + if ((int)*pattern == ch) + { + if (size - 1 <= fread(sbuf, sizeof(char), size - 1, fp)) + { + if (SUCCESS == memcmp(sbuf, &pattern[1], size - 1)) + { + if (0 == --N) + { + pos = tempos; + goto RDONE; + } + } + } + tempos -= skip; + } + else --tempos; + } + + /* Clean up and leave */ + +RDONE: + free(sbuf); + return pos; +} + +#ifdef TEST + +int main(int argc, char *argv[]) +{ + long pos; + int N = 1; + size_t size = strlen(argv[1]); + char buf[256], *fname = "SRCHFILE.C"; + FILE *fp; + + if (2 > argc) + { + puts("Usage: SRCHFILE string [N] [file]"); + puts("where: N = find Nth occurance"); + puts(" If file is specified, N must be given"); + return EXIT_FAILURE; + } + + if (2 < argc) + N = atoi(argv[2]); + + if (3 < argc) + fname = strupr(argv[3]); + + fp = fopen(fname, "r"); + printf("ffsearch(%s, %s) returned %ld\n", fname, argv[1], + pos = ffsearch(fp, argv[1], size, N)); + fseek(fp, pos, SEEK_SET); + fgets(buf, 256, fp); + printf("...which contains \"%s\"\n\n", buf); + fclose(fp); + + fp = fopen(fname, "rb"); + printf("rfsearch(%s, %s) returned %ld\n", fname, argv[1], + pos = rfsearch(fp, argv[1], size, N)); + fseek(fp, pos, SEEK_SET); + fgets(buf, 256, fp); + printf("...which contains \"%s\"\n\n", buf); + fclose(fp); + return EXIT_SUCCESS; +} + +#endif /* TEST */ -- cgit v1.2.3-54-g00ecf