// --------------------------------------------------------------------------- // - Importer.cpp - // - afnix:sps module - sps objects importer 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 "Reader.hpp" #include "Importer.hpp" #include "Runnable.hpp" #include "QuarkZone.hpp" namespace afnix { // ------------------------------------------------------------------------- // - class section (record importer) - // ------------------------------------------------------------------------- // create a default record importer Recording::Recording (void) { p_ircd = nilp; setrcd (new Record); } // create a record importer with a record Recording::Recording (Record* rcd) { p_ircd = nilp; setrcd (rcd); } // destroy this record importer Recording::~Recording (void) { Object::dref (p_ircd); } // return the object name String Recording::repr (void) const { return "Recording"; } // return the importation record Record* Recording::getrcd (void) const { rdlock (); Record* result = p_ircd; unlock (); return result; } // set the record to import void Recording::setrcd (Record* rcd) { wrlock (); Object::dref (p_ircd); Object::iref (p_ircd = rcd); unlock (); } // import a list of literal into the record void Recording::import (Cons* cons) { if (cons == nilp) return; wrlock (); try { // iterate in the cons cell while (cons != nilp) { // get the object and reduce it Object* car = cons->getcar (); Object* obj = (car == nilp) ? nilp : car->mini (); p_ircd->add (obj); cons = cons->getcdr (); } } catch (...) { unlock (); throw; } } // import stream data into the record void Recording::import (Input* is) { if (is == nilp) return; wrlock (); // create a new reader Reader rd (is); wrlock (); Form* form = nilp; try { // parse with the reader while (true) { form = rd.parse (); if (form == nilp) break; import (form); } } catch (Exception& e) { if (form == nilp) { e.setlnum (rd.getlnum ()); } else { e.setlnum (form->getlnum ()); Object::cref (form); } unlock (); throw; } catch (...) { unlock (); throw; } } // ------------------------------------------------------------------------- // - object section (record importer) - // ------------------------------------------------------------------------- // the quark zone static const long QUARK_RZON_LENGTH = 3; static QuarkZone rzon (QUARK_RZON_LENGTH); // the object supported quarks static const long QUARK_SETRCD = rzon.intern ("set-record"); static const long QUARK_GETRCD = rzon.intern ("get-record"); static const long QUARK_RIMPORT = rzon.intern ("import"); // create a new object in a generic way Object* Recording::mknew (Vector* argv) { // get number of arguments long argc = (argv == nilp) ? 0 : argv->length (); // check for 0 argument if (argc == 0) return new Recording; // check for 1 argument if (argc == 1) { Object* obj = argv->get (0); Record* rcd = dynamic_cast <Record*> (obj); if (rcd != nilp) { return new Recording (rcd); } throw Exception ("type-error", "invalid argument with record import"); } throw Exception ("argument-error", "too many argument with record import"); } // return true if the given quark is defined bool Recording::isquark (const long quark, const bool hflg) const { rdlock (); if (rzon.exists (quark) == true) { unlock (); return true; } bool result = hflg ? Object::isquark (quark, hflg) : false; unlock (); return result; } // apply this object with a set of arguments and a quark Object* Recording::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_GETRCD) { rdlock (); Record* rcd = getrcd (); robj->post (rcd); unlock (); return rcd; } } // dispatch 1 argument if (argc == 1) { if (quark == QUARK_SETRCD) { Object* obj = argv->get (0); Record* rcd = dynamic_cast <Record*> (obj); if (rcd == nilp) throw Exception ("type-error", "invalid object for set-record ", Object::repr (obj)); setrcd (rcd); return nilp; } if (quark == QUARK_RIMPORT) { Object* obj = argv->get (0); // check for an input stream Input* is = dynamic_cast <Input*> (obj); if (is != nilp) { import (is); return nilp; } // check for a cons cell Cons* cons = dynamic_cast <Cons*> (obj); if (cons != nilp) { import (cons); return nilp; } throw Exception ("type-error", "invalid object for import ", Object::repr (obj)); } } // call the object method return Object::apply (robj, nset, quark, argv); } // ------------------------------------------------------------------------- // - object section (sheet importer) - // ------------------------------------------------------------------------- // create a default sheet importer Sheeting::Sheeting (void) { p_isht = nilp; setsht (new Sheet); } // create a sheet importer with a sheet Sheeting::Sheeting (Sheet* rcd) { p_isht = nilp; setsht (rcd); } // destroy this sheet importer Sheeting::~Sheeting (void) { Object::dref (p_isht); } // return the object name String Sheeting::repr (void) const { return "Sheeting"; } // return the importation sheet Sheet* Sheeting::getsht (void) const { rdlock (); Sheet* result = p_isht; unlock (); return result; } // set the sheet to import void Sheeting::setsht (Sheet* sht) { wrlock (); Object::dref (p_isht); Object::iref (p_isht = sht); unlock (); } // import a list of literal into the sheet void Sheeting::import (Cons* cons) { if (cons == nilp) return; wrlock (); Record* rcd = new Record; try { // iterate in the cons cell while (cons != nilp) { // get the object and reduce it Object* car = cons->getcar (); Object* obj = (car == nilp) ? nilp : car->mini (); rcd->add (obj); cons = cons->getcdr (); } p_isht->add (rcd); } catch (...) { Object::cref (rcd); unlock (); throw; } } // import stream data into the sheet void Sheeting::import (Input* is) { if (is == nilp) return; wrlock (); // create a new reader Reader rd (is); wrlock (); Form* form = nilp; try { // parse with the reader while (true) { form = rd.parse (); if (form == nilp) break; import (form); } } catch (Exception& e) { if (form == nilp) { e.setlnum (rd.getlnum ()); } else { e.setlnum (form->getlnum ()); Object::cref (form); } unlock (); throw; } catch (...) { unlock (); throw; } } // ------------------------------------------------------------------------- // - object section (sheet importer) - // ------------------------------------------------------------------------- // the quark zone static const long QUARK_SZON_LENGTH = 3; static QuarkZone szon (QUARK_SZON_LENGTH); // the object supported quarks static const long QUARK_SETSHT = szon.intern ("set-sheet"); static const long QUARK_GETSHT = szon.intern ("get-sheet"); static const long QUARK_SIMPORT = szon.intern ("import"); // create a new object in a generic way Object* Sheeting::mknew (Vector* argv) { // get number of arguments long argc = (argv == nilp) ? 0 : argv->length (); // check for 0 argument if (argc == 0) return new Sheeting; // check for 1 argument if (argc == 1) { Object* obj = argv->get (0); Sheet* sht = dynamic_cast <Sheet*> (obj); if (sht != nilp) { return new Sheeting (sht); } throw Exception ("type-error", "invalid argument with sheet import"); } throw Exception ("argument-error", "too many argument with sheet import"); } // return true if the given quark is defined bool Sheeting::isquark (const long quark, const bool hflg) const { rdlock (); if (szon.exists (quark) == true) { unlock (); return true; } bool result = hflg ? Object::isquark (quark, hflg) : false; unlock (); return result; } // apply this object with a set of arguments and a quark Object* Sheeting::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_GETSHT) { rdlock (); Sheet* sht = getsht (); robj->post (sht); unlock (); return sht; } } // dispatch 1 argument if (argc == 1) { if (quark == QUARK_SETSHT) { Object* obj = argv->get (0); Sheet* sht = dynamic_cast <Sheet*> (obj); if (sht == nilp) throw Exception ("type-error", "invalid object for set-sheet ", Object::repr (obj)); setsht (sht); return nilp; } if (quark == QUARK_SIMPORT) { Object* obj = argv->get (0); // check for an input stream Input* is = dynamic_cast <Input*> (obj); if (is != nilp) { import (is); return nilp; } // check for a cons cell Cons* cons = dynamic_cast <Cons*> (obj); if (cons != nilp) { import (cons); return nilp; } throw Exception ("type-error", "invalid object for import ", Object::repr (obj)); } } // call the object method return Object::apply (robj, nset, quark, argv); } }