Logo Search packages:      
Sourcecode: afnix version File versions

Folio.cpp

// ---------------------------------------------------------------------------
// - Folio.cpp                                                               -
// - afnix:sps module - folio class implementation                           -
// ---------------------------------------------------------------------------
// - This program is free software;  you can redistribute it  and/or  modify -
// - it provided that this copyright notice is kept intact.                  -
// -                                                                         -
// - This program  is  distributed in  the hope  that it will be useful, but -
// - without  any  warranty;  without  even   the   implied    warranty   of -
// - merchantability or fitness for a particular purpose.  In no event shall -
// - the copyright holder be liable for any  direct, indirect, incidental or -
// - special damages arising in any way out of the use of this software.     -
// ---------------------------------------------------------------------------
// - copyright (c) 1999-2007 amaury darsch                                   -
// ---------------------------------------------------------------------------

#include "Folio.hpp"
#include "Boolean.hpp"
#include "Integer.hpp"
#include "Runnable.hpp"
#include "QuarkZone.hpp"
#include "Exception.hpp"

namespace afnix {

  // -------------------------------------------------------------------------
  // - private section                                                       -
  // -------------------------------------------------------------------------

  // the folio magic number
  const long SPS_MSIZE   = 4;
  const char SPS_MAGIC[] = {'\377', 'S', 'P', 'S'};

  // this function write the folio header
  static void write_folio_magic (Output& os) {
    for (long i = 0; i < SPS_MSIZE; i++) os.write (SPS_MAGIC[i]);
  }

  // this function check that the header matches the edc magic number
  static bool check_folio_magic (Input* is) {
    // check for nil and reset
    if (is == nilp) return false;
    // read in the magic number
    char mbuf[SPS_MSIZE];
    for (long i = 0; i < SPS_MSIZE; i++) {
      mbuf[i] = is->read ();
      if (mbuf[i] != SPS_MAGIC[i]) {
      is->pushback (mbuf, i+1);
      return false;
      }
    }
    return true;
  }

  // -------------------------------------------------------------------------
  // - class section                                                         -
  // -------------------------------------------------------------------------

  // create a nil folio

00061   Folio::Folio (void) {
    reset ();
  }
  
  // create a new folio by name
  
00067   Folio::Folio (const String& name) {
    reset ();
    d_name = name;
  }
  
  // create a new folio by name and info

00074   Folio::Folio (const String& name, const String& info) {
    reset ();
    d_name = name;
    d_info = info;
  }
            
  // create a new folio by stream

00082   Folio::Folio (Input* is) {
    // reset the folio
    reset ();
    // check for valid header
    if (check_folio_magic (is) == false)
      throw Exception ("folio-error", "invalid stream header");
    // read-in data
    rdstream (*is);
  }
            
  // return the object name

00094   String Folio::repr (void) const {
    return "Folio";
  }

  // reset this folio

00100   void Folio::reset (void) {
    wrlock ();
    try {
      d_name = "";
      d_info = "";
      d_prop.reset ();
      d_vsht.reset ();
      unlock ();
    } catch (...) {
      unlock ();
      throw;
    }
  }
      
  // write the folio to an output stream
  
00116   void Folio::write (Output& os) {
    rdlock ();
    try {
      // write the header
      write_folio_magic (os);
      // serialize the folio
      wrstream (os);
      unlock ();
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // serialize a folio

00132   void Folio::wrstream (Output& os) const {
    rdlock ();
    // save the folio name
    d_name.wrstream (os);
    // save the folio info
    d_info.wrstream (os);
    // save the folio prop
    d_prop.wrstream (os);
    // save the vector
    d_vsht.wrstream (os);
    unlock ();
  }

  // deserialize this folio

00147   void Folio::rdstream (Input& is) {
    wrlock ();
    // get the folio name
    d_name.rdstream (is);
    // get the folio info
    d_info.rdstream (is);
    // get the folio prop
    d_prop.rdstream (is);
    // get the vector
    d_vsht.rdstream (is);
    unlock ();
  }

  // return the folio name

00162   String Folio::getname (void) const {
    rdlock ();
    String result = d_name;
    unlock ();
    return result;
  }

  // set the folio name

00171   void Folio::setname (const String& name) {
    wrlock ();
    d_name = name;
    unlock ();
  }

  // return the folio info

00179   String Folio::getinfo (void) const {
    rdlock ();
    String result = d_info;
    unlock ();
    return result;
  }

  // set the folio info

00188   void Folio::setinfo (const String& info) {
    wrlock ();
    d_info = info;
    unlock ();
  }

  // return true if a property exists

00196   bool Folio::isprop (const String& name) {
    rdlock ();
    try {
      bool result = d_prop.exists (name);
      unlock ();
      return result;
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // return the number of folio properties

00210   long Folio::lenprop (void) const {
    rdlock ();
    try {
      long result = d_prop.length ();
      unlock ();
      return result;
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // return a folio property by index
    
00224   Property* Folio::getprop (const long index) const {
    rdlock ();
    try {
      Property* result = d_prop.get (index);
      unlock ();
      return result;
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // return a folio property by name

00238   Property* Folio::findprop (const String& name) const {
    rdlock ();
    try {
      Property* result = d_prop.find (name);
      unlock ();
      return result;
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // return a folio property by name or throw an exception

00252   Property* Folio::lookprop (const String& name) const {
    rdlock ();
    try {
      Property* result = d_prop.lookup (name);
      unlock ();
      return result;
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // return a folio property value by name

00266   String Folio::getpval (const String& name) const {
    rdlock ();
    try {
      String result = d_prop.getpval (name);
      unlock ();
      return result;
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // add a folio property

00280   void Folio::addprop (Property* prop) {
    wrlock ();
    try {
      d_prop.add (prop);
      unlock ();
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // add a property by name and value

00293   void Folio::addprop (const String& name, const Literal& lval) {
    wrlock ();
    try {
      d_prop.add (name, lval);
      unlock ();
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // set a property by name and value

00306   void Folio::setprop (const String& name, const Literal& lval) {
    wrlock ();
    try {
      d_prop.set (name, lval);
      unlock ();
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // return the length of the folio

00319   long Folio::length (void) const {
    rdlock ();
    long result = d_vsht.length ();
    unlock ();
    return result;
  }

  // add a sheet in this folio

00328   void Folio::add (Sheet* sheet) {
    wrlock ();
    d_vsht.append (sheet);
    unlock ();
  }

  // get a folio sheet by index

00336   Sheet* Folio::get (const long index) const {
    rdlock ();
    try {
      Sheet* result = dynamic_cast <Sheet*> (d_vsht.get (index));
      unlock ();
      return result;
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // set this folio by index and sheet

00350   void Folio::set (const long index, Sheet* sheet) {
    wrlock ();
    d_vsht.set (index, sheet);
    unlock ();
  }

  // return true if a tag exists

00358   bool Folio::istag (const String& tag) const {
    rdlock ();
    try {
      // get the folio length and iterate
      long len = length ();
      for (long i = 0; i < len; i++) {
      Sheet* sheet = get (i);
      if (sheet == nilp) continue;
      if (sheet->istag (tag) == true) {
        unlock ();
        return true;
      }
      }
      unlock ();
      return false;
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // return the sheet index by tag

00381   Index* Folio::getsidx (const String& tag) const {
    rdlock ();
    Index* indx= new Index;
    try {
      // get the folio length and iterate
      long len = length ();
      for (long i = 0; i < len; i++) {
      Sheet* sheet = get (i);
      if (sheet == nilp) continue;
      if (sheet->istag (tag) == true) {
        indx->add (-1, -1, i);
      }
      }
      unlock ();
      return indx;
    } catch (...) {
      delete indx;
      unlock ();
      throw;
    }
  }

  // find a sheet by tag - the first found is returned

00405   Sheet* Folio::find (const String& tag) const {
    rdlock ();
    try {
      // get the folio length and iterate
      long len = length ();
      for (long i = 0; i < len; i++) {
      Sheet* sheet = get (i);
      if (sheet == nilp) continue;
      if (sheet->istag (tag) == false) continue;
      unlock ();
      return sheet;
      }
      unlock ();
      return nilp;
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // find a sheet by tag of throw an exception

00427   Sheet* Folio::lookup (const String& tag) const {
    rdlock ();
    try {
      Sheet* result = find (tag);
      if (result == nilp) {
      throw Exception ("lookup-error", "cannot find sheet with tag", tag);
      }
      unlock ();
      return result;
    } catch (...) {
      unlock ();
      throw;
    }
  }

  // filter a folio by tag and return a new folio

00444   Folio* Folio::filter (const String& tag) const {
    rdlock ();
    // create a result folio
    Folio* result = new Folio;
    try {
      // get the folio length and iterate
      long len = length ();
      for (long i = 0; i < len; i++) {
      Sheet* sheet = get (i);
      if (sheet == nilp) continue;
      if (sheet->istag (tag) == false) continue;
      result->add (sheet);
      }
    } catch (...) {
      delete result;
      unlock ();
      throw;
    }
    unlock ();
    return result;
  }
  
  // get a full xref table

00468   Xref* Folio::getxref (void) const {
    rdlock ();
    Xref* xref = new Xref;
    try {
      // iterate in the folio
      long flen = length ();
      for (long i = 0; i < flen; i++) {
      // get the next sheet
      Sheet* sheet = get (i);
      if (sheet == nilp) continue;
      // iterate in the sheet
      long slen = sheet->length ();
      for (long j = 0; j < slen; j++) {
        // get the next record
        Record* rcd = sheet->get (j);
        if (rcd == nilp) continue;
        // iterate in the record
        long rlen = rcd->length ();
        for (long k = 0; k < rlen; k++) {
          // get the next cell
          Cell* cell = rcd->get (k);
          if (cell == nilp) continue;
          // get the cell name and update
          String name = cell->getname ();
          xref->add (name, k, j, i);
        }
      }
      }
      unlock ();
      return xref;
    } catch (...) {
      delete xref;
      unlock ();
      throw;
    }
  }

  // get a xref table by tag

00507   Xref* Folio::getxref (const String& tag) const {
    rdlock ();
    Xref* xref = new Xref;
    try {
      // iterate in the folio
      long flen = length ();
      for (long i = 0; i < flen; i++) {
      // get the next sheet
      Sheet* sheet = get (i);
      if (sheet == nilp) continue;
      if (sheet->istag (tag) == false) continue;
      // iterate in the sheet
      long slen = sheet->length ();
      for (long j = 0; j < slen; j++) {
        // get the next record
        Record* rcd = sheet->get (j);
        if (rcd == nilp) continue;
        // iterate in the record
        long rlen = rcd->length ();
        for (long k = 0; k < rlen; k++) {
          // get the next cell
          Cell* cell = rcd->get (k);
          if (cell == nilp) continue;
          // get the cell name and update
          String name = cell->getname ();
          xref->add (name, k, j, i);
        }
      }
      }
      unlock ();
      return xref;
    } catch (...) {
      delete xref;
      unlock ();
      throw;
    }
  }

  // get a xref table by coordinate

00547   Xref* Folio::getxref (const long cidx) const {
    rdlock ();
    Xref* xref = new Xref;
    try {
      // iterate in the folio
      long flen = length ();
      for (long i = 0; i < flen; i++) {
      // get the next sheet
      Sheet* sheet = get (i);
      if (sheet == nilp) continue;
      // iterate in the sheet
      long slen = sheet->length ();
      for (long j = 0; j < slen; j++) {
        // get the next record
        Record* rcd = sheet->get (j);
        if (rcd == nilp) continue;
        // get the cell at the index
        Cell* cell = rcd->get (cidx);
        if (cell == nilp) continue;
        // get the cell name and update
        String name = cell->getname ();
        xref->add (name, cidx, j, i);
      }
      }
      unlock ();
      return xref;
    } catch (...) {
      delete xref;
      unlock ();
      throw;
    }
  }

  // get a xref table by coordinate

00582   Xref* Folio::getxref (const long cidx, const long ridx) const {
    rdlock ();
    Xref* xref = new Xref;
    try {
      // iterate in the folio
      long flen = length ();
      for (long i = 0; i < flen; i++) {
      // get the next sheet
      Sheet* sheet = get (i);
      if (sheet == nilp) continue;
      // get the record at the index
      Record* rcd = sheet->get (ridx);
      if (rcd == nilp) continue;
      // get the cell at the index
      Cell* cell = rcd->get (cidx);
      if (cell == nilp) continue;
      // get the cell name and update
      String name = cell->getname ();
      xref->add (name, cidx, ridx, i);
      }
      unlock ();
      return xref;
    } catch (...) {
      delete xref;
      unlock ();
      throw;
    }
  }

  // -------------------------------------------------------------------------
  // - object section                                                         -
  // -------------------------------------------------------------------------
  
  // the quark zone
  static const long QUARK_ZONE_LENGTH = 24;
  static QuarkZone  zone (QUARK_ZONE_LENGTH);

  // the object supported quarks
  static const long QUARK_ADD     = zone.intern ("add");
  static const long QUARK_GET     = zone.intern ("get");
  static const long QUARK_SET     = zone.intern ("set");
  static const long QUARK_FIND    = zone.intern ("find");
  static const long QUARK_RESET   = zone.intern ("reset");
  static const long QUARK_WRITE   = zone.intern ("write");
  static const long QUARK_LOOKUP  = zone.intern ("lookup");
  static const long QUARK_FILTER  = zone.intern ("filter");
  static const long QUARK_LENGTH  = zone.intern ("length");
  static const long QUARK_ISTAGP  = zone.intern ("tag-p");
  static const long QUARK_PROPLEN = zone.intern ("property-length");
  static const long QUARK_ISPROPP = zone.intern ("property-p");
  static const long QUARK_ADDPROP = zone.intern ("add-property");
  static const long QUARK_SETPROP = zone.intern ("set-property");
  static const long QUARK_GETPROP = zone.intern ("get-property");
  static const long QUARK_GETPVAL = zone.intern ("get-property-value");
  static const long QUARK_FNDPROP = zone.intern ("find-property");
  static const long QUARK_LOKPROP = zone.intern ("lookup-property");
  static const long QUARK_GETINDX = zone.intern ("get-index");
  static const long QUARK_GETNAME = zone.intern ("get-name");
  static const long QUARK_SETNAME = zone.intern ("set-name");
  static const long QUARK_GETINFO = zone.intern ("get-info");
  static const long QUARK_SETINFO = zone.intern ("set-info");
  static const long QUARK_GETXREF = zone.intern ("get-xref");

  // create a new object in a generic way

00647   Object* Folio::mknew (Vector* argv) {
    // get number of arguments
    long argc = (argv == nilp) ? 0 : argv->length ();
    // check for 0 argument
    if (argc == 0) return new Folio;
    // check for 1 argument
    if (argc == 1) {
      Object*  obj = argv->get (0);
      // check for a name
      String* sobj = dynamic_cast <String*> (obj);
      if (sobj != nilp) return new Folio (*sobj);
      // check for an input stream
      Input* iobj = dynamic_cast <Input*> (obj);
      if (iobj != nilp) return new Folio (iobj);
      // invalid argument
      throw Exception ("argument-error", "invalid folio argument",
                   Object::repr (obj));
    }
    // check for 2 arguments
    if (argc == 2) {
      String name = argv->getstring (0);
      String info = argv->getstring (1);
      return new Folio (name, info);
    }
    throw Exception ("argument-error", "too many argument with folio");
  }

  // return true if the given quark is defined

00676   bool Folio::isquark (const long quark, const bool hflg) const {
    rdlock ();
    if (zone.exists (quark) == true) {
      unlock ();
      return true;
    }
    bool result = hflg ? Persist::isquark (quark, hflg) : false;
    unlock ();
    return result;
  }

  // applythis object with a set of arguments and a quark

00689   Object* Folio::apply (Runnable* robj, Nameset* nset, const long quark,
                  Vector* argv) {
    // get the number of arguments
    long argc = (argv == nilp) ? 0 : argv->length ();
    
    // dispatch 0 argument
    if (argc == 0) {
      if (quark == QUARK_LENGTH ) return new Integer (length  ());
      if (quark == QUARK_PROPLEN) return new Integer (lenprop ());
      if (quark == QUARK_GETNAME) return new String  (getname ());
      if (quark == QUARK_GETINFO) return new String  (getinfo ());
      if (quark == QUARK_RESET) {
      reset ();
      return nilp;
      }
      if (quark == QUARK_GETXREF) {
      return getxref ();
      }
    }
    // dispatch 1 argument
    if (argc == 1) {
      if (quark == QUARK_SETNAME) {
      String name = argv->getstring (0);
      setname (name);
      return nilp;
      }
      if (quark == QUARK_SETINFO) {
      String name = argv->getstring (0);
      setinfo (name);
      return nilp;
      }
      if (quark == QUARK_ISPROPP) {
      String name = argv->getstring (0);
      return new Boolean (isprop (name));
      }
      if (quark == QUARK_ADDPROP) {
        Object* obj = argv->get (0);
        Property* prop = dynamic_cast <Property*> (obj);
        if ((obj != nilp) && (prop == nilp)) {
          throw Exception ("type-error", "invalid object with add-property",
                           Object::repr (obj));
        }
        addprop (prop);
        return nilp;
      }
      if (quark == QUARK_GETPROP) {
      long index = argv->getint (0);
      rdlock();
      try {
        Object* result = getprop (index);
        robj->post (result);
        unlock ();          
        return result;
      } catch (...) {
        unlock ();
        throw;
      }
      }
      if (quark == QUARK_GETPVAL) {
      String name = argv->getstring (0);
      return new String (getpval (name));
      }
      if (quark == QUARK_FNDPROP) {
      rdlock ();
      try {
        String name = argv->getstring (0);
        Object* result = findprop (name);
        robj->post (result);
        unlock ();
        return result;
      } catch (...) {
        unlock ();
        throw;
      }
      }
      if (quark == QUARK_LOKPROP) {
      rdlock ();
      try {
        String name = argv->getstring (0);
        Object* result = lookprop (name);
        robj->post (result);
        unlock ();
        return result;
      } catch (...) {
        unlock ();
        throw;
      }
      }
      if (quark == QUARK_GET) {
      long idx = argv->getint (0);
      rdlock ();
      try {
        Object* result = get (idx);
        robj->post (result);
        unlock ();
        return result;
      } catch (...) {
        unlock ();
        throw;
      }
      }
      if (quark == QUARK_ADD) {
      Object* obj = argv->get (0);
      Sheet*  sht = dynamic_cast <Sheet*> (obj);
      if ((obj != nilp) && (sht == nilp)) 
        throw Exception ("type-error", "invalid object to add in folio",
                     Object::repr (obj));
      add (sht);
      return nilp;
      }
      if (quark == QUARK_ISTAGP) {
      String tag = argv->getstring (0);
      return new Boolean (istag (tag));
      }
      if (quark == QUARK_GETINDX) {
      String tag = argv->getstring (0);
      return getsidx (tag);
      }
      if (quark == QUARK_FIND) {
      rdlock ();
      try {
        String tag = argv->getstring (0);
        Sheet* result = find (tag);
        robj->post (result);
        unlock ();
        return result;
      } catch (...) {
        unlock ();
        throw;
      }
      }
      if (quark == QUARK_LOOKUP) {
      rdlock ();
      try {
        String tag = argv->getstring (0);
        Sheet* result = lookup (tag);
        robj->post (result);
        unlock ();
        return result;
      } catch (...) {
        unlock ();
        throw;
      }
      }
      if (quark == QUARK_FILTER) {
      String tag = argv->getstring (0);
      return filter (tag);
      }
      if (quark == QUARK_GETXREF) {
      Object* obj = argv->get (0);
      // check for an integer
      Integer* iobj = dynamic_cast <Integer*> (obj);
      if (iobj != nilp) {
        long cidx = iobj->tointeger ();
        return getxref (cidx);
      }
      // check for a string
      String* sobj = dynamic_cast <String*> (obj);
      if (sobj != nilp) {
        return getxref (*sobj);
      }
      // invalid type
      throw Exception ("type-error", "invalid object with get-xref",
                   Object::repr (obj));
      }
      if (quark == QUARK_WRITE) {
      Object* obj = argv->get (0);
      Output*  os = dynamic_cast <Output*> (obj);
      if (os == nilp) {
        throw Exception ("type-error", "invalid object with write",
                     Object::repr (obj));
      }
      write (*os);
      return nilp;
      }
    }
    // dispatch 2 argument
    if (argc == 2) {
      if (quark == QUARK_ADDPROP) {
        String   name = argv->getstring (0);
        Object*   obj = argv->get (1);
        Literal* lobj = dynamic_cast <Literal*> (obj);
        if (lobj == nilp) {
        throw Exception ("type-error", "invalid object with add-property",
                     Object::repr (obj));
        }
        addprop (name, *lobj);
        return nilp;
      }
      if (quark == QUARK_SETPROP) {
        String   name = argv->getstring (0);
        Object*   obj = argv->get (1);
        Literal* lobj = dynamic_cast <Literal*> (obj);
        if (lobj == nilp) {
        throw Exception ("type-error", "invalid object with set-property",
                         Object::repr (obj));
        }
        setprop (name, *lobj);
        return nilp;
      }
      if (quark == QUARK_SET) {
      long    idx = argv->getint (0);
      Object* obj = argv->get (1);
      Sheet*  sht = dynamic_cast <Sheet*> (obj);
      if ((obj != nilp) && (sht == nilp)) 
        throw Exception ("type-error", "invalid object to set in folio",
                     Object::repr (obj));
      set (idx, sht);
      return nilp;
      }
      if (quark == QUARK_GETXREF) {
      long cidx = argv->getint (0);
      long ridx = argv->getint (1);
      return getxref (cidx, ridx);
      }
    }
    // call the persist method
    return Persist::apply (robj, nset, quark, argv);
  }
}

Generated by  Doxygen 1.6.0   Back to index