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
- reportErrors
- PRINT1
- PRINT2
- printPTree
- setClass
- addAttr
- setAttr
- setAttr
1 // $Id: object.cc,v 1.1.1.1 2000/03/10 16:32:24 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 bool Object::scan(const char *_text, const int sz, ostream &err) {
/* [<][>][^][v][top][bottom][index][help] */
152 contents = (char *) _text;
153 size = sz;
154
155 scan(err);
156
157 contents = NULL;
158 size = 0;
159 return ! has_error;
160 }
161
162 void Object::reportErrors(ostream &ostrm) {
/* [<][>][^][v][top][bottom][index][help] */
163 Attr *n_attr;
164
165 for (Attr *attr = attrs.head(); attr; attr = n_attr) {
166 n_attr = attrs.next(attr);
167 if (attr->errors.empty() || attr->errorLeng == 0) {
168 ostrm.write(&contents[attr->offset], attr->len);
169 ostrm << attr->errors;
170 } else {
171 char *begin = &contents[attr->offset];
172 char *end = begin;
173 for (int i = 0; i <= attr->errorLine; ++i)
174 end = strchr(end, '\n') + 1;
175 ostrm.write(begin, end - begin);
176 for (int i = 0; i < attr->errorColon; ++i)
177 ostrm << " ";
178 for (int i = 0; i < attr->errorLeng; ++i)
179 ostrm << "^";
180 ostrm << "\n";
181 ostrm << attr->errors;
182 ostrm.write(end, attr->len - (end - begin));
183 }
184 }
185 if (! attrs.head() && contents)
186 ostrm << contents;
187
188 ostrm << errors;
189 ostrm << "\n";
190 }
191
192 // Added by wlee@isi.edu
193 #ifdef DEBUG
194
195 #define PRINT1(x) os << " " #x " = " << x << endl
/* [<][>][^][v][top][bottom][index][help] */
196 #define PRINT2(x, y) os << " " #x " = " << y << endl
/* [<][>][^][v][top][bottom][index][help] */
197
198 void Object::printPTree(ostream &os) const
/* [<][>][^][v][top][bottom][index][help] */
199 {
200 os << "Object" << endl;
201 PRINT2(contents, "\"...\"");
202 PRINT1(size);
203 os << " type" << endl;
204 os << " "; PRINT2(name, type->name);
205 os << " attrs (List <Attr>)" << endl;
206 os << " "; PRINT2(length, attrs.size());
207 for (Attr *attr = attrs.head(); attr; attr = attrs.next(attr)) {
208 os << " ListNode" << endl;
209 // os << " forw" << endl;
210 // os << " back" << endl;
211 os << " data (Attr *)" << endl;
212 os << " "; PRINT2(offset, attr->offset);
213 os << " "; PRINT2(len, attr->len);
214 os << " " << attr->className() << endl;
215 attr->printClass(os, 10);
216 }
217 }
218
219 #endif // #ifdef DEBUG
220
221 ostream& operator<<(ostream &os, const Object &o) {
222 Attr *attr;
223
224 for (attr = o.attrs.head(); attr; attr = o.attrs.next(attr))
225 if (attr->type && !attr->type->isObsolete())
226 os << *attr << "\n";
227
228 os << "\n";
229 return os;
230 }
231
232 bool Object::setClass(char *cls) {
/* [<][>][^][v][top][bottom][index][help] */
233 type = schema.searchClass(cls);
234 // make sure there is an extra \n at the end
235 append("\n", 1);
236 return type;
237 }
238
239 bool Object::addAttr(char *attr, Item *item) {
/* [<][>][^][v][top][bottom][index][help] */
240 if (!type)
241 return false;
242
243 const AttrAttr *attrType = type->searchAttr(attr);
244 if (!attrType)
245 return false;
246
247 ItemList *items = new ItemList;
248 items->append(item);
249 Attr *attrib = new AttrGeneric(attrType, items);
250
251 ostrstream s;
252 s << *attrib << ends;
253 attrib->offset = size;
254 attrib->len = strlen(s.str());
255
256 // delete the extra \n at the end, and reinsert after this attribute
257 size--;
258 append(s.str(), attrib->len);
259 append("\n", 1);
260 s.freeze(0);
261
262 (*this) += attrib;
263 return true;
264 }
265
266 bool Object::setAttr(char *attrName, Item *item) {
/* [<][>][^][v][top][bottom][index][help] */
267 if (!type)
268 return false;
269
270 const AttrAttr *attrType = type->searchAttr(attrName);
271 if (!attrType)
272 return false;
273
274 ItemList *items = new ItemList;
275 items->append(item);
276 AttrGeneric *attr = new AttrGeneric(attrType, items);
277
278 return setAttr(attrName, attr);
279 }
280
281 bool Object::setAttr(char *attrName, Attr *attr) {
/* [<][>][^][v][top][bottom][index][help] */
282 if (!type)
283 return false;
284
285 const AttrAttr *attrType = type->searchAttr(attrName);
286 if (!attrType)
287 return false;
288
289 Attr *atr2;
290 for (Attr *atr = attrs.head(); atr; atr = atr2) {
291 atr2 = attrs.next(atr);
292 if (atr->type == attrType) {
293 attrs.remove(atr);
294 flush(atr->len, atr->offset);
295 delete atr;
296 }
297 }
298
299 (*this) += attr;
300
301 ostrstream s;
302 s << *attr << "\n" << ends;
303 attr->offset = size;
304 attr->len = strlen(s.str());
305
306 // delete the extra \n at the end, and reinsert after this attribute
307 size--;
308 append(s.str(), attr->len);
309 append("\n", 1);
310 s.freeze(0);
311
312 return true;
313 }
314