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_silent
  7. scan
  8. scan_silent
  9. reportErrors
  10. PRINT1
  11. PRINT2
  12. printPTree
  13. setClass
  14. addAttr
  15. setAttr
  16. 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 

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