Mercurial > ~dholland > hg > ag > index.cgi
diff anagram/agcore/textfile.cpp @ 0:13d2b8934445
Import AnaGram (near-)release tree into Mercurial.
author | David A. Holland |
---|---|
date | Sat, 22 Dec 2007 17:52:45 -0500 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/anagram/agcore/textfile.cpp Sat Dec 22 17:52:45 2007 -0500 @@ -0,0 +1,260 @@ +/* + * AnaGram, A System for Syntax Directed Programming + * Copyright 1993-2002 Parsifal Software. All Rights Reserved. + * See the file COPYING for license and usage terms. + * + * textfile.cpp + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +#include "port.h" + +#include "agstack.h" +#include "config.h" +#include "file.h" +#include "minmax.h" +//#include "stacks.h" +#include "textfile.h" + +//#define INCLUDE_LOGGING +#include "log.h" + + +#define BUF_SIZE 0x4000000 + +text_file::text_file(const text_file &t) + : name(t.name), text(t.text), lx(t.lx), width(t.width) + , stringLength(t.stringLength) + , truncated(0) + , readFlags(t.readFlags) +{ + LOGSECTION("text_file::text_file"); + LOGV(name) LCV(width); + LOGV((int) text.pointer()); +} + +text_file &text_file::operator =(const text_file &t) { + name = t.name; /* name of file */ + text = t.text; /* body of file */ + lx = t.lx; /* array of line indices */ + width = t.width; /* length of longest line? */ + truncated = t.truncated; + stringLength = t.stringLength; + readFlags = t.readFlags; + return *this; +} + + +text_file::text_file(const char *n) + : name(n), text(), lx(), width(0), stringLength(0) + , truncated(0) + , readFlags(O_TEXT|O_RDONLY) +{ + LOGSECTION("text_file::text_file"); + LOGV(name); + LOGV((int) text.pointer()); + read_file(readFlags); +} + +text_file::text_file(const AgString n) +: name(n), text(), lx(), width(0), stringLength(0) + , truncated(0) + , readFlags(O_TEXT|O_RDONLY) +{ + LOGSECTION("text_file::text_file"); + LOGV(name.pointer()); + LOGV((int) text.pointer()); + LOGV((int) readFlags); + read_file(readFlags); +} + +text_file::text_file(const char *n, int flags) + : name(n), text(), lx(), width(0), stringLength(0) + , truncated(0) + , readFlags(flags) +{ + LOGSECTION("text_file::text_file"); + LOGV(name); + LOGV((int) text.pointer()); + read_file(flags); +} + +text_file::text_file(const AgString n, int flags) +: name(n), text(), lx(), width(0), stringLength(0) + , truncated(0) + , readFlags(flags) +{ + LOGSECTION("text_file::text_file"); + LOGV(name.pointer()); + LOGV((int) text.pointer()); + LOGV((int) flags); + read_file(flags); +} + +void text_file::find_lines(void) { + char *p, *b, *bl, *q; + int w, wmax; + LOGSECTION("text_file::find_lines"); + AgStack<int> lineStack; + + wmax = w = 0; + p = b = text.pointer(); + LOGV(p); + if (p != NULL) { + do { + p = strchr(bl = p,'\n'); + lineStack.push((int)(bl-b)); + if (p != NULL) { + *p = 0; + } + else { + q = strchr(bl, 0); + if (q == bl) { + break; + } + } + q = bl; + w = 0; + LOGV(lineStack.size()) LCV(bl); + while (*q) { + w += (*q++ == '\t') ? tab_spacing - w%tab_spacing : 1; + } + if (w > wmax) { + wmax = w; + } + if (p == NULL) { + break; + } + *p++ = '\n'; + } while(*p); + } + + LOGS("Line scan complete"); + LOGV((int) &lineStack[0]) LCV((int) &lineStack[lineStack.size() - 1]); + + lx = AgArray<int>(lineStack); + LOGS("Line array completed"); + + width = wmax; +} + +void text_file::read_file() { + read_file(readFlags); +} + +void text_file::read_file(int flags) { + int fh; + long n; + + LOGSECTION("text_file::read_file"); + LOGV(name); + LOGV(flags); + fh = open_shared_any(name.pointer(),flags); + LOGV(fh); + if (fh < 0) { + LOGV(errno); + LOGV(strerror(errno)); + return; + } + LOGV(name); + char *buf, *bufptr; + long length; + long buffer_length; + struct stat statbuf; + + fstat(fh, &statbuf); + //file_time_stamp = statbuf.st_atime; + length = statbuf.st_size; + stringLength = 0; + LOGV(length); + buffer_length = min((long)(length+1), (long)(MAX_BYTES - 1 - sizeof(short))); + LOGV((int) text.pointer()); + text = AgString(buffer_length); + LOGV((int) text.pointer()); + buf = bufptr = text.pointer(); + LOGV((int) text.pointer()); + n = 0; + while (1) { + unsigned k; + unsigned read_request = (unsigned) min(buffer_length, (long) BUF_SIZE); + LOGV(read_request); + if ((long)read_request > length) { + read_request = (unsigned) length; + } + length -= read_request; + LOGV(read_request) LCV(length); + k = read(fh, bufptr, read_request); + bufptr[k] = 0; + LOGV(k) LCV(stringLength); + // XXX howabout checking for -1 before dereferencing with it? + if (k == 0 || k == (unsigned) -1) { + break; + } + stringLength += k; + LOGV(k) LCV(stringLength); + bufptr += k; + LOGV((int) (bufptr- 10)) LCV(bufptr - 10); + buffer_length -= k; + n += k; + } + truncated = length != 0; + LOGV(stringLength) LCV(n) LCV(length); + LOGV(buf[n-5]) LCV(buf[n-4]) LCV(buf[n-3]) LCV(buf[n-2]) LCV(buf[n-1]); + buf[(unsigned)n] = 0; + close(fh); + find_lines(); + LOGV(lx.size()) LCV((int) lx.pointer()); + //printf("text_file::read_file\n"); +} + +int text_file::findNext(cint &loc, AgString s) { + LOGSECTION("text_file::findNext"); + LOGV(name); + LOGV(loc) LCV(s); + searchProcess.setKey(s); + assert((unsigned) loc.y < lx.size()); + unsigned start = lx[loc.y] + loc.x; + LOGV(lx[loc.y]) LCV(start) LCV(stringLength); + assert(start <= stringLength); + if (start == stringLength) { + return 0; + } + char *initial = text.pointer() + start + 1; + char *ptr = searchProcess.scanForward(initial, stringLength - start); + if (ptr == 0) { + return 0; + } + unsigned index = ptr - text.pointer(); + while ((unsigned) loc.y < lx.size() && (unsigned) lx[loc.y] < index) { + loc.y++; + } + if ((unsigned) loc.y >= lx.size() || (unsigned) lx[loc.y] > index) { + loc.y--; + } + loc.x = index - lx[loc.y]; + return 1; +} + +int text_file::findPrev(cint &loc, AgString s) { + LOGSECTION("text_file::findPrev"); + LOGV(loc) LCV(s); + searchProcess.setKey(s); + assert((unsigned) loc.y < lx.size()); + unsigned length = lx[loc.y] + loc.x - 1; + LOGV(length); + char *ptr = searchProcess.scanReverse(text.pointer(), length); + if (ptr == 0) { + return 0; + } + unsigned index = ptr - text.pointer(); + while (loc.y && (unsigned) lx[loc.y] > index) { + loc.y--; + } + loc.x = index - lx[loc.y]; + LOGV(loc) LCV(index); + return 1; +}