comparison oldclasslib/include/charsink.h @ 0:13d2b8934445

Import AnaGram (near-)release tree into Mercurial.
author David A. Holland
date Sat, 22 Dec 2007 17:52:45 -0500
parents
children 607e3be6bad8
comparison
equal deleted inserted replaced
-1:000000000000 0:13d2b8934445
1 /*
2 * AnaGram, a System for Syntax Directed Programming
3 *
4 * Character Sink Class Definitions
5 *
6 * Copyright 1993 Parsifal Software. All Rights Reserved.
7 *
8 * This software is provided 'as-is', without any express or implied
9 * warranty. In no event will the authors be held liable for any damages
10 * arising from the use of this software.
11 *
12 * Permission is granted to anyone to use this software for any purpose,
13 * including commercial applications, and to alter it and redistribute it
14 * freely, subject to the following restrictions:
15 *
16 * 1. The origin of this software must not be misrepresented; you must not
17 * claim that you wrote the original software. If you use this software
18 * in a product, an acknowledgment in the product documentation would be
19 * appreciated but is not required.
20 * 2. Altered source versions must be plainly marked as such, and must not be
21 * misrepresented as being the original software.
22 * 3. This notice may not be removed or altered from any source distribution.
23 */
24
25 #ifndef CHARSINK_H
26 #define CHARSINK_H
27
28 #include <stdio.h>
29 #include <assert.h>
30
31
32 // Class Definition for character_sink
33
34 class character_sink {
35 public:
36 virtual ~character_sink() {}
37 virtual character_sink& operator << (int c) = 0;
38 virtual character_sink& operator << (const char *str) = 0;
39 virtual character_sink& operator << (const unsigned char *str) = 0;
40 virtual character_sink& printf(const char *, ...) = 0;
41 };
42
43
44 // Class Definition for output_file
45
46 class output_file : public character_sink {
47 private:
48 FILE *file;
49 char *name;
50 int error_flag;
51 int copy_flag; // is it live or memorex?
52
53 public:
54
55 // Constructors
56
57 output_file() {
58 file = stdout;
59 error_flag = copy_flag = 0;
60 }
61
62 output_file(char *path) : character_sink() {
63 name = path;
64 if (name == NULL) file = stdout;
65 else file = fopen(name = path, "wt");
66 if (file == NULL) file = stdout;
67 error_flag = copy_flag = 0;
68 }
69
70 output_file(output_file &f) : character_sink() {
71 *this = f;
72 copy_flag++;
73 }
74
75
76 // Destructor
77
78 ~output_file() {if (copy_flag == 0) fclose(file);}
79
80
81 // Xmit data to sink
82
83 character_sink& operator << (int c) {
84 error_flag = putc((char) c,file);
85 return *this;
86 }
87
88 character_sink& operator << (const char *str) {
89 fputs(str,file);
90 return *this;
91 }
92
93 character_sink& operator << (const unsigned char *str) {
94 fputs((const char *)str, file);
95 return *this;
96 }
97
98 character_sink& printf(const char *, ...);
99
100
101 // Check for error
102
103 friend int error(output_file &f);
104 };
105
106 inline int error(output_file &f) {
107 return f.error_flag < 0;
108 }
109
110 class string_accumulator : public character_sink {
111 private:
112 char *cs; // character storage
113 unsigned *xs; // index storage
114 unsigned csx; // next available character
115 unsigned xsx; // next available index
116 unsigned csmax; // max number of characters
117 unsigned xsmax; // max number of indices
118 int copy_flag; // is it live or is it memorex?
119
120 public:
121
122 // Constructor
123
124 string_accumulator(int nc, int nx = 1);
125 string_accumulator(const string_accumulator &);
126
127
128 // Destructor
129
130 ~string_accumulator();
131
132
133 // Reset string_accumulator
134
135 friend string_accumulator &reset(string_accumulator &);
136
137
138 // Change stack level
139
140 string_accumulator& operator ++(){ // preincrement stack level
141 assert(copy_flag == 0);
142 assert(xsx);
143 xs[--xsx] = csx;
144 return *this;
145 }
146
147 string_accumulator operator ++ (int); // postincrement stack level
148
149 string_accumulator &operator -- () { // predecrement stack level
150 assert(copy_flag == 0);
151 csx = xs[xsx++]; // discard top string
152 assert(xsx < xsmax);
153 return *this;
154 }
155
156 string_accumulator operator -- (int); // post decrement stack level
157
158 // Append data to stack
159
160 character_sink& operator << (int c) { // append char to top string
161 assert(copy_flag == 0);
162 assert(csx < csmax);
163 cs[csx++] = (char) c;
164 return *this;
165 }
166
167 character_sink &operator << (const char *str); // append string to top string
168
169 character_sink &operator << (const unsigned char *str);
170
171 character_sink &operator << (string_accumulator &s) {
172 assert(this != &s); // prevent disaster
173 return *this << s.top();
174 }
175
176 character_sink &printf(const char *, ...);
177
178
179 // Pop character from stack
180
181 string_accumulator &operator >> (int &c); // pop last character
182
183
184 // Access character on stack
185
186 char &operator [] (unsigned); // inspect character
187
188
189 // Retrieve pointer to top string
190
191 // See README.txt
192 #if 0
193 operator char *() const { // pointer to top string
194 cs[csx] = 0;
195 return &cs[xs[xsx]];
196 }
197
198 operator unsigned char *() const { // pointer to top string
199 cs[csx] = 0;
200 return (unsigned char *) &cs[xs[xsx]];
201 }
202 #else
203 char *top() const {
204 cs[csx] = 0;
205 return &cs[xs[xsx]];
206 }
207 #endif
208
209
210 // Concatenate strings
211
212 friend string_accumulator& concat(string_accumulator &);
213
214
215 // Make permanent copy of string
216
217 friend char *copy(const string_accumulator &);
218
219
220 // Get length of string
221
222 friend unsigned size(const string_accumulator &);
223
224 };
225
226 inline unsigned size(const string_accumulator &s) {
227 assert(s.xsx < s.xsmax);
228 return s.csx - s.xs[s.xsx];
229 }
230
231 #endif