Mercurial > ~dholland > hg > ag > index.cgi
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:13d2b8934445 |
---|---|
1 /* | |
2 * AnaGram, A System for Syntax Directed Programming | |
3 * Copyright 1993-2002 Parsifal Software. All Rights Reserved. | |
4 * See the file COPYING for license and usage terms. | |
5 * | |
6 * textfile.cpp | |
7 */ | |
8 | |
9 #include <sys/types.h> | |
10 #include <sys/stat.h> | |
11 #include <fcntl.h> | |
12 #include <errno.h> | |
13 | |
14 #include "port.h" | |
15 | |
16 #include "agstack.h" | |
17 #include "config.h" | |
18 #include "file.h" | |
19 #include "minmax.h" | |
20 //#include "stacks.h" | |
21 #include "textfile.h" | |
22 | |
23 //#define INCLUDE_LOGGING | |
24 #include "log.h" | |
25 | |
26 | |
27 #define BUF_SIZE 0x4000000 | |
28 | |
29 text_file::text_file(const text_file &t) | |
30 : name(t.name), text(t.text), lx(t.lx), width(t.width) | |
31 , stringLength(t.stringLength) | |
32 , truncated(0) | |
33 , readFlags(t.readFlags) | |
34 { | |
35 LOGSECTION("text_file::text_file"); | |
36 LOGV(name) LCV(width); | |
37 LOGV((int) text.pointer()); | |
38 } | |
39 | |
40 text_file &text_file::operator =(const text_file &t) { | |
41 name = t.name; /* name of file */ | |
42 text = t.text; /* body of file */ | |
43 lx = t.lx; /* array of line indices */ | |
44 width = t.width; /* length of longest line? */ | |
45 truncated = t.truncated; | |
46 stringLength = t.stringLength; | |
47 readFlags = t.readFlags; | |
48 return *this; | |
49 } | |
50 | |
51 | |
52 text_file::text_file(const char *n) | |
53 : name(n), text(), lx(), width(0), stringLength(0) | |
54 , truncated(0) | |
55 , readFlags(O_TEXT|O_RDONLY) | |
56 { | |
57 LOGSECTION("text_file::text_file"); | |
58 LOGV(name); | |
59 LOGV((int) text.pointer()); | |
60 read_file(readFlags); | |
61 } | |
62 | |
63 text_file::text_file(const AgString n) | |
64 : name(n), text(), lx(), width(0), stringLength(0) | |
65 , truncated(0) | |
66 , readFlags(O_TEXT|O_RDONLY) | |
67 { | |
68 LOGSECTION("text_file::text_file"); | |
69 LOGV(name.pointer()); | |
70 LOGV((int) text.pointer()); | |
71 LOGV((int) readFlags); | |
72 read_file(readFlags); | |
73 } | |
74 | |
75 text_file::text_file(const char *n, int flags) | |
76 : name(n), text(), lx(), width(0), stringLength(0) | |
77 , truncated(0) | |
78 , readFlags(flags) | |
79 { | |
80 LOGSECTION("text_file::text_file"); | |
81 LOGV(name); | |
82 LOGV((int) text.pointer()); | |
83 read_file(flags); | |
84 } | |
85 | |
86 text_file::text_file(const AgString n, int flags) | |
87 : name(n), text(), lx(), width(0), stringLength(0) | |
88 , truncated(0) | |
89 , readFlags(flags) | |
90 { | |
91 LOGSECTION("text_file::text_file"); | |
92 LOGV(name.pointer()); | |
93 LOGV((int) text.pointer()); | |
94 LOGV((int) flags); | |
95 read_file(flags); | |
96 } | |
97 | |
98 void text_file::find_lines(void) { | |
99 char *p, *b, *bl, *q; | |
100 int w, wmax; | |
101 LOGSECTION("text_file::find_lines"); | |
102 AgStack<int> lineStack; | |
103 | |
104 wmax = w = 0; | |
105 p = b = text.pointer(); | |
106 LOGV(p); | |
107 if (p != NULL) { | |
108 do { | |
109 p = strchr(bl = p,'\n'); | |
110 lineStack.push((int)(bl-b)); | |
111 if (p != NULL) { | |
112 *p = 0; | |
113 } | |
114 else { | |
115 q = strchr(bl, 0); | |
116 if (q == bl) { | |
117 break; | |
118 } | |
119 } | |
120 q = bl; | |
121 w = 0; | |
122 LOGV(lineStack.size()) LCV(bl); | |
123 while (*q) { | |
124 w += (*q++ == '\t') ? tab_spacing - w%tab_spacing : 1; | |
125 } | |
126 if (w > wmax) { | |
127 wmax = w; | |
128 } | |
129 if (p == NULL) { | |
130 break; | |
131 } | |
132 *p++ = '\n'; | |
133 } while(*p); | |
134 } | |
135 | |
136 LOGS("Line scan complete"); | |
137 LOGV((int) &lineStack[0]) LCV((int) &lineStack[lineStack.size() - 1]); | |
138 | |
139 lx = AgArray<int>(lineStack); | |
140 LOGS("Line array completed"); | |
141 | |
142 width = wmax; | |
143 } | |
144 | |
145 void text_file::read_file() { | |
146 read_file(readFlags); | |
147 } | |
148 | |
149 void text_file::read_file(int flags) { | |
150 int fh; | |
151 long n; | |
152 | |
153 LOGSECTION("text_file::read_file"); | |
154 LOGV(name); | |
155 LOGV(flags); | |
156 fh = open_shared_any(name.pointer(),flags); | |
157 LOGV(fh); | |
158 if (fh < 0) { | |
159 LOGV(errno); | |
160 LOGV(strerror(errno)); | |
161 return; | |
162 } | |
163 LOGV(name); | |
164 char *buf, *bufptr; | |
165 long length; | |
166 long buffer_length; | |
167 struct stat statbuf; | |
168 | |
169 fstat(fh, &statbuf); | |
170 //file_time_stamp = statbuf.st_atime; | |
171 length = statbuf.st_size; | |
172 stringLength = 0; | |
173 LOGV(length); | |
174 buffer_length = min((long)(length+1), (long)(MAX_BYTES - 1 - sizeof(short))); | |
175 LOGV((int) text.pointer()); | |
176 text = AgString(buffer_length); | |
177 LOGV((int) text.pointer()); | |
178 buf = bufptr = text.pointer(); | |
179 LOGV((int) text.pointer()); | |
180 n = 0; | |
181 while (1) { | |
182 unsigned k; | |
183 unsigned read_request = (unsigned) min(buffer_length, (long) BUF_SIZE); | |
184 LOGV(read_request); | |
185 if ((long)read_request > length) { | |
186 read_request = (unsigned) length; | |
187 } | |
188 length -= read_request; | |
189 LOGV(read_request) LCV(length); | |
190 k = read(fh, bufptr, read_request); | |
191 bufptr[k] = 0; | |
192 LOGV(k) LCV(stringLength); | |
193 // XXX howabout checking for -1 before dereferencing with it? | |
194 if (k == 0 || k == (unsigned) -1) { | |
195 break; | |
196 } | |
197 stringLength += k; | |
198 LOGV(k) LCV(stringLength); | |
199 bufptr += k; | |
200 LOGV((int) (bufptr- 10)) LCV(bufptr - 10); | |
201 buffer_length -= k; | |
202 n += k; | |
203 } | |
204 truncated = length != 0; | |
205 LOGV(stringLength) LCV(n) LCV(length); | |
206 LOGV(buf[n-5]) LCV(buf[n-4]) LCV(buf[n-3]) LCV(buf[n-2]) LCV(buf[n-1]); | |
207 buf[(unsigned)n] = 0; | |
208 close(fh); | |
209 find_lines(); | |
210 LOGV(lx.size()) LCV((int) lx.pointer()); | |
211 //printf("text_file::read_file\n"); | |
212 } | |
213 | |
214 int text_file::findNext(cint &loc, AgString s) { | |
215 LOGSECTION("text_file::findNext"); | |
216 LOGV(name); | |
217 LOGV(loc) LCV(s); | |
218 searchProcess.setKey(s); | |
219 assert((unsigned) loc.y < lx.size()); | |
220 unsigned start = lx[loc.y] + loc.x; | |
221 LOGV(lx[loc.y]) LCV(start) LCV(stringLength); | |
222 assert(start <= stringLength); | |
223 if (start == stringLength) { | |
224 return 0; | |
225 } | |
226 char *initial = text.pointer() + start + 1; | |
227 char *ptr = searchProcess.scanForward(initial, stringLength - start); | |
228 if (ptr == 0) { | |
229 return 0; | |
230 } | |
231 unsigned index = ptr - text.pointer(); | |
232 while ((unsigned) loc.y < lx.size() && (unsigned) lx[loc.y] < index) { | |
233 loc.y++; | |
234 } | |
235 if ((unsigned) loc.y >= lx.size() || (unsigned) lx[loc.y] > index) { | |
236 loc.y--; | |
237 } | |
238 loc.x = index - lx[loc.y]; | |
239 return 1; | |
240 } | |
241 | |
242 int text_file::findPrev(cint &loc, AgString s) { | |
243 LOGSECTION("text_file::findPrev"); | |
244 LOGV(loc) LCV(s); | |
245 searchProcess.setKey(s); | |
246 assert((unsigned) loc.y < lx.size()); | |
247 unsigned length = lx[loc.y] + loc.x - 1; | |
248 LOGV(length); | |
249 char *ptr = searchProcess.scanReverse(text.pointer(), length); | |
250 if (ptr == 0) { | |
251 return 0; | |
252 } | |
253 unsigned index = ptr - text.pointer(); | |
254 while (loc.y && (unsigned) lx[loc.y] > index) { | |
255 loc.y--; | |
256 } | |
257 loc.x = index - lx[loc.y]; | |
258 LOGV(loc) LCV(index); | |
259 return 1; | |
260 } |