modules/up/src/rpsl/rpsl/object.cc

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. Object
  2. read
  3. read
  4. parse
  5. scan
  6. scan
  7. reportErrors
  8. PRINT1
  9. PRINT2
  10. printPTree
  11. setClass
  12. addAttr
  13. setAttr
  14. 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 

/* [<][>][^][v][top][bottom][index][help] */