modules/up/src/rpsl/rpsl/object.cc
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- Object
- read
- read
- parse
- scan
- scan_silent
- scan
- scan_silent
- reportErrors
- PRINT1
- PRINT2
- printPTree
- setClass
- addAttr
- setAttr
- setAttr
1 // $Id: object.cc,v 1.1 2001/03/19 17:15:32 engin Exp $
2 //
3 // Copyright (c) 1994 by the University of Southern California
4 // All rights reserved.
5 //
6 // Permission to use, copy, modify, and distribute this software and its
7 // documentation in source and binary forms for lawful non-commercial
8 // purposes and without fee is hereby granted, provided that the above
9 // copyright notice appear in all copies and that both the copyright
10 // notice and this permission notice appear in supporting documentation,
11 // and that any documentation, advertising materials, and other materials
12 // related to such distribution and use acknowledge that the software was
13 // developed by the University of Southern California, Information
14 // Sciences Institute. The name of the USC may not be used to endorse or
15 // promote products derived from this software without specific prior
16 // written permission.
17 //
18 // THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY
19 // REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
20 // PURPOSE. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
21 // IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
22 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
23 // TITLE, AND NON-INFRINGEMENT.
24 //
25 // IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
26 // SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT, TORT,
27 // OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH, THE USE
28 // OR PERFORMANCE OF THIS SOFTWARE.
29 //
30 // Questions concerning this software should be directed to
31 // ratoolset@isi.edu.
32 //
33 // Author(s): Cengiz Alaettinoglu <cengiz@ISI.EDU>
34
35 #include "config.h"
36 #include <istream.h>
37 #include <cstdio>
38 #include <strstream.h>
39 #include <fstream.h>
40 #include <iomanip.h>
41
42 #include "object.hh"
43 #include "schema.hh"
44
45 extern int rpslparse(void *);
46 extern void rpsl_scan_object(Object *);
47
48 Object::~Object() {
/* [<][>][^][v][top][bottom][index][help] */
49 attrs.clear();
50 }
51
52 const int MAX_KEY_LENGTH = 1024;
53 const int INITIAL_CHUNK_SIZE = 1024;
54 const int TOO_SMALL_CHUNK_SIZE = 64;
55
56
57 bool Object::read(istream &in) {
/* [<][>][^][v][top][bottom][index][help] */
58 return read(*this, in);
59 }
60
61 bool Object::read(Buffer &buf, istream &in) {
/* [<][>][^][v][top][bottom][index][help] */
62 if (in.eof())
63 return false;
64
65 int size = INITIAL_CHUNK_SIZE;
66 int remaining = size;
67
68 char *text = (char *) malloc(size);
69 char *start = text;
70 char *p;
71
72 int linelen;
73 int len = 0;
74
75 while (1) {
76 in.getline(start, remaining);
77
78 linelen = strlen(start);
79 remaining -= linelen;
80 len += linelen;
81 start += linelen;
82
83 if (!linelen || in.eof()) // empty line or eof => end of object
84 break;
85 // blank line => end of object?
86 for (p = start - linelen;
87 *p && (*p == ' ' || *p == '\t' || *p == '\r'); ++p)
88 ;
89 if (! *p)
90 break;
91
92 if (remaining < TOO_SMALL_CHUNK_SIZE) {
93 remaining += size;
94 size *= 2;
95 text = (char *) realloc(text, size);
96 start = text + len;
97 }
98
99 if (in) { // append \n if we successfully read a line
100 *start = '\n';
101 start++;
102 len++;
103 remaining--;
104 } else
105 in.clear();
106 }
107
108 buf.size=len;
109 buf.contents = (char *) realloc(text, len+2);
110
111 return len;
112 }
113
114 void Object::parse() {
/* [<][>][^][v][top][bottom][index][help] */
115 rpsl_scan_object(this);
116 rpslparse(this);
117
118 if (type) {
119 bool forgiving = schema.isForgiving();
120 if (isDeleted || schema.isVeryForgiving()) {
121 if (has_error) {
122 has_error = false;
123 Attr *n_attr;
124
125 for (Attr *attr = attrs.head(); attr; attr = attrs.next(attr))
126 if (! attr->errors.empty()
127 && attr->type && attr->type->isKey()) {
128 has_error = true;
129 break;
130 }
131 }
132 schema.beForgiving();
133 }
134 has_error |= ! type->validate(errors);
135 schema.beForgiving(forgiving);
136 } else {
137 errors = "***Error: Unknown class encountered.";
138 has_error = true;
139 }
140 }
141
142 bool Object::scan(ostream &err) {
/* [<][>][^][v][top][bottom][index][help] */
143 parse();
144
145 if (has_error)
146 reportErrors(err);
147
148 return ! has_error;
149 }
150
151 /* added by Engin, 19/03/2001 */
152 /* a silent version of "Object::scan" */
153 bool Object::scan_silent() {
/* [<][>][^][v][top][bottom][index][help] */
154 parse();
155
156 return ! has_error;
157 }
158
159
160 bool Object::scan(const char *_text, const int sz, ostream &err) {
/* [<][>][^][v][top][bottom][index][help] */
161 contents = (char *) _text;
162 size = sz;
163
164 scan(err);
165
166 contents = NULL;
167 size = 0;
168 return ! has_error;
169 }
170
171 /* added by Engin, 19/03/2001 */
172 /* a silent version of "Object::scan" */
173 bool Object::scan_silent(const char *_text, const int sz) {
/* [<][>][^][v][top][bottom][index][help] */
174 contents = (char *) _text;
175 size = sz;
176
177 scan_silent();
178
179 contents = NULL;
180 size = 0;
181 return ! has_error;
182 }
183
184 void Object::reportErrors(ostream &ostrm) {
/* [<][>][^][v][top][bottom][index][help] */
185 Attr *n_attr;
186
187 for (Attr *attr = attrs.head(); attr; attr = n_attr) {
188 n_attr = attrs.next(attr);
189 if (attr->errors.empty() || attr->errorLeng == 0) {
190 ostrm.write(&contents[attr->offset], attr->len);
191 ostrm << attr->errors;
192 } else {
193 char *begin = &contents[attr->offset];
194 char *end = begin;
195 for (int i = 0; i <= attr->errorLine; ++i)
196 end = strchr(end, '\n') + 1;
197 ostrm.write(begin, end - begin);
198 for (int i = 0; i < attr->errorColon; ++i)
199 ostrm << " ";
200 for (int i = 0; i < attr->errorLeng; ++i)
201 ostrm << "^";
202 ostrm << "\n";
203 ostrm << attr->errors;
204 ostrm.write(end, attr->len - (end - begin));
205 }
206 }
207 if (! attrs.head() && contents)
208 ostrm << contents;
209
210 ostrm << errors;
211 ostrm << "\n";
212 }
213
214 // Added by wlee@isi.edu
215 #ifdef DEBUG
216
217 #define PRINT1(x) os << " " #x " = " << x << endl
/* [<][>][^][v][top][bottom][index][help] */
218 #define PRINT2(x, y) os << " " #x " = " << y << endl
/* [<][>][^][v][top][bottom][index][help] */
219
220 void Object::printPTree(ostream &os) const
/* [<][>][^][v][top][bottom][index][help] */
221 {
222 os << "Object" << endl;
223 PRINT2(contents, "\"...\"");
224 PRINT1(size);
225 os << " type" << endl;
226 os << " "; PRINT2(name, type->name);
227 os << " attrs (List <Attr>)" << endl;
228 os << " "; PRINT2(length, attrs.size());
229 for (Attr *attr = attrs.head(); attr; attr = attrs.next(attr)) {
230 os << " ListNode" << endl;
231 // os << " forw" << endl;
232 // os << " back" << endl;
233 os << " data (Attr *)" << endl;
234 os << " "; PRINT2(offset, attr->offset);
235 os << " "; PRINT2(len, attr->len);
236 os << " " << attr->className() << endl;
237 attr->printClass(os, 10);
238 }
239 }
240
241 #endif // #ifdef DEBUG
242
243 ostream& operator<<(ostream &os, const Object &o) {
244 Attr *attr;
245
246 for (attr = o.attrs.head(); attr; attr = o.attrs.next(attr))
247 if (attr->type && !attr->type->isObsolete())
248 os << *attr << "\n";
249
250 os << "\n";
251 return os;
252 }
253
254 bool Object::setClass(char *cls) {
/* [<][>][^][v][top][bottom][index][help] */
255 type = schema.searchClass(cls);
256 // make sure there is an extra \n at the end
257 append("\n", 1);
258 return type;
259 }
260
261 bool Object::addAttr(char *attr, Item *item) {
/* [<][>][^][v][top][bottom][index][help] */
262 if (!type)
263 return false;
264
265 const AttrAttr *attrType = type->searchAttr(attr);
266 if (!attrType)
267 return false;
268
269 ItemList *items = new ItemList;
270 items->append(item);
271 Attr *attrib = new AttrGeneric(attrType, items);
272
273 ostrstream s;
274 s << *attrib << ends;
275 attrib->offset = size;
276 attrib->len = strlen(s.str());
277
278 // delete the extra \n at the end, and reinsert after this attribute
279 size--;
280 append(s.str(), attrib->len);
281 append("\n", 1);
282 s.freeze(0);
283
284 (*this) += attrib;
285 return true;
286 }
287
288 bool Object::setAttr(char *attrName, Item *item) {
/* [<][>][^][v][top][bottom][index][help] */
289 if (!type)
290 return false;
291
292 const AttrAttr *attrType = type->searchAttr(attrName);
293 if (!attrType)
294 return false;
295
296 ItemList *items = new ItemList;
297 items->append(item);
298 AttrGeneric *attr = new AttrGeneric(attrType, items);
299
300 return setAttr(attrName, attr);
301 }
302
303 bool Object::setAttr(char *attrName, Attr *attr) {
/* [<][>][^][v][top][bottom][index][help] */
304 if (!type)
305 return false;
306
307 const AttrAttr *attrType = type->searchAttr(attrName);
308 if (!attrType)
309 return false;
310
311 Attr *atr2;
312 for (Attr *atr = attrs.head(); atr; atr = atr2) {
313 atr2 = attrs.next(atr);
314 if (atr->type == attrType) {
315 attrs.remove(atr);
316 flush(atr->len, atr->offset);
317 delete atr;
318 }
319 }
320
321 (*this) += attr;
322
323 ostrstream s;
324 s << *attr << "\n" << ends;
325 attr->offset = size;
326 attr->len = strlen(s.str());
327
328 // delete the extra \n at the end, and reinsert after this attribute
329 size--;
330 append(s.str(), attr->len);
331 append("\n", 1);
332 s.freeze(0);
333
334 return true;
335 }
336