// --------------------------------------------------------------------------- // - Sheet.cpp - // - afnix:sps module - sheet 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 "Sheet.hpp" #include "Input.hpp" #include "Spssid.hxx" #include "Boolean.hpp" #include "Integer.hpp" #include "Importer.hpp" #include "Runnable.hpp" #include "QuarkZone.hpp" #include "Exception.hpp" namespace afnix { // ------------------------------------------------------------------------- // - private section - // ------------------------------------------------------------------------- class SheetSorter { private: // the column index long d_col; // the sorting mode bool d_mode; // compare two objects for ascending order bool cmplth (Object* ref, Object* slv) const { // check that we have a object records Record* rref = dynamic_cast (ref); Record* rslv = dynamic_cast (slv); // map the cell to their object Object* robj = nilp; try { robj = (rref == nilp) ? nilp : rref->map (d_col); } catch (...) { robj = nilp; } Object* sobj = nilp; try { sobj = (rslv == nilp) ? nilp : rslv->map (d_col); } catch (...) { sobj = nilp; } // compare with operator if (robj == nilp) return true; Object* obj = robj->oper (Object::LTH, sobj); Boolean* bobj = dynamic_cast (obj); bool result = (bobj == nilp) ? false : bobj->toboolean (); Object::cref (obj); return result; } // compare two objects for descending order bool cmpgth (Object* ref, Object* slv) const { // check that we have a object records Record* rref = dynamic_cast (ref); Record* rslv = dynamic_cast (slv); // map the cell to their object Object* robj = nilp; try { robj = (rref == nilp) ? nilp : rref->map (d_col); } catch (...) { robj = nilp; } Object* sobj = nilp; try { sobj = (rslv == nilp) ? nilp : rslv->map (d_col); } catch (...) { sobj = nilp; } // compare with operator if ((robj == nilp) && (sobj == nilp)) return true; if ((robj == nilp) && (sobj != nilp)) return false; Object* obj = robj->oper (Object::GTH, sobj); Boolean* bobj = dynamic_cast (obj); bool result = (bobj == nilp) ? false : bobj->toboolean (); Object::cref (obj); return result; } // partition the vector and returns the pivot index long partition (Vector& argv, const long first, const long last) const { // initialize the pivot index, last index and next (unknown) index long pidx = first; long lidx = first; long uidx = lidx + 1; // get the pivot object - and protect it Object* pvt = Object::iref (argv.get (pidx)); // swap until we have reached the last element while (uidx <= last) { Object* ref = Object::iref (argv.get (uidx)); bool cflg = d_mode ? cmplth (ref, pvt) : cmpgth (ref, pvt); if (cflg == true) { lidx++; argv.set (uidx, argv.get (lidx)); argv.set (lidx, ref); } Object::tref (ref); // the intel is in the other region uidx++; } // place the pivot in proper position argv.set (first, argv.get (lidx)); argv.set (lidx, pvt); Object::tref (pvt); // the pivot index is now the last index return lidx; } // this function performs a recursive quick sort void quicksort (Vector& argv, const long first, const long last) const { if (first >= last) return; long pidx = partition (argv, first, last); quicksort (argv, first, pidx - 1); quicksort (argv, pidx + 1, last); } public: // create a default sheet sorter SheetSorter (void) { d_col = 0; d_mode = false; } // create a sorting object by index SheetSorter (const long col, const bool mode) { d_col = col; d_mode = mode; } // sort a vector void qsort (Vector& argv) const { // sort the vector in place argv.wrlock (); try { long argc = argv.length (); quicksort (argv, 0, argc - 1); argv.unlock (); } catch (...) { argv.unlock (); throw; } } }; // this function computes the maximum between two numbers static inline long max (const long x, const long y) { return (x < y) ? y : x; } // this procedure returns a new sheet object for deserialization static Serial* mksob (void) { return new Sheet; } // register this cell serial id static const t_byte SERIAL_ID = Serial::setsid (SERIAL_SHTT_ID, mksob); // ------------------------------------------------------------------------- // - class section - // ------------------------------------------------------------------------- // create a nil sheet Sheet::Sheet (void) { reset (); } // create a new sheet by name Sheet::Sheet (const String& name) { d_name = name; reset (); } // create a new sheet by name and info Sheet::Sheet (const String& name, const String& info) { d_name = name; d_info = info; reset (); } // copy construct this sheet Sheet::Sheet (const Sheet& that) { that.rdlock (); try { d_name = that.d_name; d_info = that.d_info; d_tags = that.d_tags; d_mark = that.d_mark; d_sign = that.d_sign; d_head = that.d_head; d_foot = that.d_foot; long slen = that.length (); for (long i = 0; i < slen; i++) { Record* rcd = that.get (i); add (new Record (*rcd)); } that.unlock (); } catch (...) { that.unlock (); throw; } } // return the object name String Sheet::repr (void) const { return "Sheet"; } // return a clone of this object Object* Sheet::clone (void) const { return new Sheet (*this); } // return the sheet serial id t_byte Sheet::serialid (void) const { return SERIAL_SHTT_ID; } // serialize a sheet void Sheet::wrstream (Output& os) const { rdlock (); // save the sheet name d_name.wrstream (os); // save the sheet info d_info.wrstream (os); /// save the tags d_tags.wrstream (os); // save the markers d_mark.wrstream (os); // save the signature d_sign.wrstream (os); // save the header d_head.wrstream (os); // save the footer d_foot.wrstream (os); // save the vector d_body.wrstream (os); unlock (); } // deserialize this sheet void Sheet::rdstream (Input& is) { wrlock (); // get the sheet name d_name.rdstream (is); // get the sheet info d_info.rdstream (is); // get the tags d_tags.rdstream (is); // get the markers d_mark.rdstream (is); // get the signature d_sign.rdstream (is); // get the header d_head.rdstream (is); // get the footer d_foot.rdstream (is); // get the vector d_body.rdstream (is); unlock (); } // reset the sheet void Sheet::reset (void) { wrlock (); try { d_head.reset (); d_foot.reset (); d_body.reset (); unlock (); } catch (...) { unlock (); throw; } } // return the sheet name String Sheet::getname (void) const { rdlock (); String result = d_name; unlock (); return result; } // set the sheet name void Sheet::setname (const String& name) { wrlock (); d_name = name; unlock (); } // return the sheet info String Sheet::getinfo (void) const { rdlock (); String result = d_info; unlock (); return result; } // set the sheet info void Sheet::setinfo (const String& info) { wrlock (); d_info = info; unlock (); } // add a sheet tag void Sheet::addtag (const String& tag) { wrlock (); try { if (d_tags.exists (tag) == false) d_tags.add (tag); unlock (); } catch (...) { unlock (); throw; } } // add a vector of literals in the tags descriptor void Sheet::addtag (const Vector* argv) { long argc = (argv == nilp) ? 0 : argv->length (); if (argc == 0) return; wrlock (); try { for (long i = 0; i < argc; i++) { Object* obj = argv->get (i); Literal* lobj = dynamic_cast (obj); if (lobj == nilp) { throw Exception ("type-error", "non literal object with sheet add-tag", Object::repr (obj)); } d_tags.add (lobj->tostring ()); } unlock (); } catch (...) { unlock (); throw; } } // return the tag descriptor length long Sheet::tagslen (void) const { rdlock (); try { long result = d_tags.length (); unlock (); return result; } catch (...) { unlock (); throw; } } // check if a tag exists bool Sheet::istag (const String& tag) const { rdlock (); try { bool result = d_tags.exists (tag); unlock (); return result; } catch (...) { unlock (); throw; } } // get a tag by index String Sheet::gettag (const long index) const { wrlock (); try { String result = d_tags.get (index); unlock (); return result; } catch (...) { unlock (); throw; } } // set the sheet tag by index void Sheet::settag (const long index, Literal* lobj) { wrlock (); try { String value = (lobj == nilp) ? "" : lobj->tostring (); d_tags.set (index, value); unlock (); } catch (...) { unlock (); throw; } } // find a tag index by tag long Sheet::findtag (const String& tag) const { rdlock (); try { long result = d_tags.lookup (tag); unlock (); return result; } catch (...) { unlock (); throw; } } // add a literal in the markers descriptor void Sheet::addmark (const String& mark) { wrlock (); try { d_mark.add (mark); unlock (); } catch (...) { unlock (); throw; } } // add a vector of objects in the marker record void Sheet::addmark (const Vector* argv) { long argc = (argv == nilp) ? 0 : argv->length (); if (argc == 0) return; wrlock (); try { for (long i = 0; i < argc; i++) { Object* obj = argv->get (i); Literal* lobj = dynamic_cast (obj); if (lobj == nilp) { throw Exception ("type-error", "non literal object with sheet add-mark", Object::repr (obj)); } d_mark.add (lobj->tostring ()); } unlock (); } catch (...) { unlock (); throw; } } // return the marker length long Sheet::marklen (void) const { rdlock (); try { long result = d_mark.length (); unlock (); return result; } catch (...) { unlock (); throw; } } // check if a marker exists exists bool Sheet::ismark (const String& mark) const { rdlock (); try { bool result = d_mark.exists (mark); unlock (); return result; } catch (...) { unlock (); throw; } } // get a sheet marker by index String Sheet::getmark (const long index) const { wrlock (); try { String result = d_mark.get (index); unlock (); return result; } catch (...) { unlock (); throw; } } // set the sheet marker by index void Sheet::setmark (const long index, Literal* lobj) { wrlock (); try { String value = (lobj == nilp) ? "" : lobj->tostring (); d_mark.set (index, value); unlock (); } catch (...) { unlock (); throw; } } // find a marker index by mark long Sheet::findmark (const String& mark) const { rdlock (); try { long result = d_mark.lookup (mark); unlock (); return result; } catch (...) { unlock (); throw; } } // add a literal in the signature descriptor void Sheet::addsign (const String& sign) { wrlock (); try { d_sign.add (sign); unlock (); } catch (...) { unlock (); throw; } } // add a vector of objects in the signature record void Sheet::addsign (const Vector* argv) { long argc = (argv == nilp) ? 0 : argv->length (); if (argc == 0) return; wrlock (); try { for (long i = 0; i < argc; i++) { Object* obj = argv->get (i); Literal* lobj = dynamic_cast (obj); if (lobj == nilp) { throw Exception ("type-error", "non literal object with sheet add-sign", Object::repr (obj)); } d_sign.add (lobj->tostring ()); } unlock (); } catch (...) { unlock (); throw; } } // return the signer length long Sheet::signlen (void) const { rdlock (); try { long result = d_sign.length (); unlock (); return result; } catch (...) { unlock (); throw; } } // check if a signer exists exists bool Sheet::issign (const String& sign) const { rdlock (); try { bool result = d_sign.exists (sign); unlock (); return result; } catch (...) { unlock (); throw; } } // get a sheet signer by index String Sheet::getsign (const long index) const { wrlock (); try { String result = d_sign.get (index); unlock (); return result; } catch (...) { unlock (); throw; } } // set the sheet signer by index void Sheet::setsign (const long index, Literal* lobj) { wrlock (); try { String value = (lobj == nilp) ? "" : lobj->tostring (); d_sign.set (index, value); unlock (); } catch (...) { unlock (); throw; } } // find a signer index by sign long Sheet::findsign (const String& sign) const { rdlock (); try { long result = d_sign.lookup (sign); unlock (); return result; } catch (...) { unlock (); throw; } } // add an object in the header record void Sheet::addhead (Object* object) { wrlock (); try { d_head.add (object); unlock (); } catch (...) { unlock (); throw; } } // add a vector of objects in the header record void Sheet::addhead (const Vector* argv) { long argc = (argv == nilp) ? 0 : argv->length (); if (argc == 0) return; wrlock (); try { for (long i = 0; i < argc; i++) d_head.add (argv->get (i)); unlock (); } catch (...) { unlock (); throw; } } // get a header cell by index Cell* Sheet::gethead (const long index) const { rdlock (); try { Cell* result = dynamic_cast (d_head.get (index)); unlock (); return result; } catch (...) { unlock (); throw; } } // evaluate a header cell by index Literal* Sheet::maphead (const long index) const { rdlock (); try { Cell* cell = gethead (index); Literal* result = (cell == nilp) ? nilp : cell->get (); unlock (); return result; } catch (...) { unlock (); throw; } } // set a record header by index and literal void Sheet::sethead (const long index, Literal* lobj) { wrlock (); try { Cell* cell = dynamic_cast (d_head.get (index)); if (cell != nilp) cell->set (lobj); unlock (); } catch (...) { unlock (); throw; } } // add an object in the footer record void Sheet::addfoot (Object* object) { wrlock (); try { d_foot.add (object); unlock (); } catch (...) { unlock (); throw; } } // add a vector of objects in the footer record void Sheet::addfoot (const Vector* argv) { long argc = (argv == nilp) ? 0 : argv->length (); if (argc == 0) return; wrlock (); try { for (long i = 0; i < argc; i++) d_foot.add (argv->get (i)); unlock (); } catch (...) { unlock (); throw; } } // get a footer cell by index Cell* Sheet::getfoot (const long index) const { rdlock (); try { Cell* result = dynamic_cast (d_foot.get (index)); unlock (); return result; } catch (...) { unlock (); throw; } } // evaluate a footer cell by index Literal* Sheet::mapfoot (const long index) const { rdlock (); try { Cell* cell = getfoot (index); Literal* result = (cell == nilp) ? nilp : cell->get (); unlock (); return result; } catch (...) { unlock (); throw; } } // set a record footer by index and literal void Sheet::setfoot (const long index, Literal* lobj) { wrlock (); try { Cell* cell = dynamic_cast (d_foot.get (index)); if (cell != nilp) cell->set (lobj); unlock (); } catch (...) { unlock (); throw; } } // add a record in this sheet void Sheet::add (Record* rcd) { if (rcd == nilp) return; wrlock (); try { d_body.append (rcd); unlock (); } catch (...) { unlock (); throw; } } // get a record by index Record* Sheet::get (const long index) const { rdlock (); try { Record* result = dynamic_cast (d_body.get (index)); unlock (); return result; } catch (...) { unlock (); throw; } } // get a cell by row and column Cell* Sheet::get (const long row, const long col) const { rdlock (); try { // get the record Record* rcd = get (row); if (rcd == nilp) { unlock (); return nilp; } // get the cell Cell* cell = rcd->get (col); unlock (); return cell; } catch (...) { unlock (); throw; } } // map a cell literal by ow and column Literal* Sheet::map (const long row, const long col) const { rdlock (); try { Cell* cell = get (row, col); Literal* lobj = (cell == nilp) ? nilp : cell->get (); unlock (); return lobj; } catch (...) { unlock (); throw; } } // set a record in this sheet by index void Sheet::set (const long index, Record* rcd) { wrlock (); try { d_body.set (index, rcd); unlock (); } catch (...) { unlock (); throw; } } // set an object in this sheet by row and column void Sheet::set (const long row, const long col, Object* object) { wrlock (); try { // check if we have enough record long slen = length (); if (row >= slen) { long delta = row - slen + 1; for (long i = 0; i < delta; i++) add (new Record); } // get the record Record* rcd = get (row); if (rcd == nilp) { unlock (); return; } // set the cell rcd->set (col, object); unlock (); } catch (...) { unlock (); throw; } } // add a vector of literal as a record void Sheet::adddata (const Vector* argv) { long argc = (argv == nilp) ? 0 : argv->length (); if (argc == 0) return; wrlock (); Record* rcd = new Record; try { for (long i = 0; i < argc; i++) rcd->add (argv->get (i)); d_body.append (rcd); unlock (); } catch (...) { Object::cref (rcd); unlock (); throw; } } // return the length of the sheet list long Sheet::length (void) const { rdlock (); try { long result = d_body.length (); unlock (); return result; } catch (...) { unlock (); throw; } } // return the number of columns long Sheet::getcols (void) const { rdlock (); try { // get the sheet length long tlen = length (); // compute the maximum columns long result = 0; for (long i = 0; i < tlen; i++) { Record* rcd = get (i); if (rcd == nilp) continue; result = max (result, rcd->length ()); } unlock (); return result; } catch (...) { unlock (); throw; } } // import data in this sheet void Sheet::import (Input* is) { // do nothing if nil if (is == nilp) return; // protect us during the importation wrlock (); Object::iref (this); // create a new importer try { Sheeting si (this); si.import (is); Object::tref (this); unlock (); } catch (...) { Object::tref (this); unlock (); throw; } } // convert this sheet into a print sheet PrintTable* Sheet::convert (long max, long start, bool flag) const { rdlock (); // get the number of rows long rows = length (); // check for start index if ((rows != 0) && ((start < 0) || (start >= rows))) { unlock (); throw Exception ("sheet-error", "start index out of range for convert"); } // check for max index long tlen = start + ((max == 0) ? rows : max); if (tlen > rows) { unlock (); throw Exception ("sheet-error", "max index is out of range for convert"); } // format result long cols = getcols (); PrintTable* result = new PrintTable (cols); try { // iterate through the record for (long i = start; i < tlen; i++) { Record* rcd = get (i); if (rcd == nilp) continue; long row = result->add (); // get the record length long rlen = rcd->length (); for (long j = 0; j < rlen; j++) { Literal* lobj = rcd->map (j); if (lobj == nilp) { result->set (row, j, "nil"); } else { String data = flag ? lobj->tostring () : lobj->toliteral (); result->set (row, j, data); } } // fill the rest of the sheet for (long j = rlen; j < cols; j++) result->set (row, j, "nil"); } unlock (); return result; } catch (...) { delete result; unlock (); throw; } } // sort this sheet by column index and mode void Sheet::sort (const long col, const bool mode) { wrlock (); try { // build the sorter object SheetSorter sorter (col, mode); // sort the vector sorter.qsort (d_body); unlock (); } catch (...) { unlock (); throw; } } // link a sheet column into this sheet void Sheet::lkcol (const Sheet* sheet, const long col) { // check for a sheet and lock if ((sheet == nilp) || (sheet == this)) return; sheet->rdlock (); wrlock (); try { // get the insert column long cidx = getcols (); // get the column size long size = sheet->length (); // copy the column for (long i = 0; i < size; i++) { Cell* cell = sheet->get (i, col); set (i, cidx, cell); } } catch (...) { unlock (); sheet->unlock (); throw; } } // ------------------------------------------------------------------------- // - object section - // ------------------------------------------------------------------------- // the quark zone static const long QUARK_ZONE_LENGTH = 42; static QuarkZone zone (QUARK_ZONE_LENGTH); // the sheet supported quarks static const long QUARK_ADD = zone.intern ("add"); static const long QUARK_GET = zone.intern ("get"); static const long QUARK_MAP = zone.intern ("map"); static const long QUARK_SET = zone.intern ("set"); static const long QUARK_SORT = zone.intern ("sort"); static const long QUARK_RESET = zone.intern ("reset"); static const long QUARK_IMPORT = zone.intern ("import"); static const long QUARK_LENGTH = zone.intern ("length"); static const long QUARK_COLLEN = zone.intern ("column-length"); static const long QUARK_ADDTAG = zone.intern ("add-tag"); static const long QUARK_TAGLEN = zone.intern ("tag-length"); static const long QUARK_ISTAGP = zone.intern ("tag-p"); static const long QUARK_GETTAG = zone.intern ("get-tag"); static const long QUARK_SETTAG = zone.intern ("set-tag"); static const long QUARK_FINDTAG = zone.intern ("find-tag"); static const long QUARK_CONVERT = zone.intern ("convert"); 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_ADDMARK = zone.intern ("add-marker"); static const long QUARK_MARKLEN = zone.intern ("marker-length"); static const long QUARK_ISMARKP = zone.intern ("marker-p"); static const long QUARK_GETMARK = zone.intern ("get-marker"); static const long QUARK_SETMARK = zone.intern ("set-marker"); static const long QUARK_FINDMRK = zone.intern ("find-marker"); static const long QUARK_ADDSIGN = zone.intern ("add-sign"); static const long QUARK_SIGNLEN = zone.intern ("signature-length"); static const long QUARK_ISSIGNP = zone.intern ("sign-p"); static const long QUARK_GETSIGN = zone.intern ("get-sign"); static const long QUARK_SETSIGN = zone.intern ("set-sign"); static const long QUARK_FINDSGN = zone.intern ("find-sign"); static const long QUARK_ADDHEAD = zone.intern ("add-header"); static const long QUARK_GETHEAD = zone.intern ("get-header"); static const long QUARK_MAPHEAD = zone.intern ("map-header"); static const long QUARK_SETHEAD = zone.intern ("set-header"); static const long QUARK_ADDFOOT = zone.intern ("add-footer"); static const long QUARK_GETFOOT = zone.intern ("get-footer"); static const long QUARK_MAPFOOT = zone.intern ("map-footer"); static const long QUARK_SETFOOT = zone.intern ("set-footer"); static const long QUARK_ADDDATA = zone.intern ("add-data"); static const long QUARK_LINKCOL = zone.intern ("link-column"); // create a new object in a generic way Object* Sheet::mknew (Vector* argv) { // get number of arguments long argc = (argv == nilp) ? 0 : argv->length (); // check for 0 argument if (argc == 0) return new Sheet; // check for 1 argument if (argc == 1) { String name = argv->getstring (0); return new Sheet (name); } // check for 2 arguments if (argc == 2) { String name = argv->getstring (0); String info = argv->getstring (1); return new Sheet (name, info); } throw Exception ("argument-error", "too many argument with sheet"); } // return true if the given quark is defined bool Sheet::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; } // apply this object with a set of arguments and a quark Object* Sheet::apply (Runnable* robj, Nameset* nset, const long quark, Vector* argv) { // check for generic quark if (quark == QUARK_ADDDATA) { adddata (argv); return nilp; } if (quark == QUARK_ADDTAG) { addtag (argv); return nilp; } if (quark == QUARK_ADDMARK) { addmark (argv); return nilp; } if (quark == QUARK_ADDSIGN) { addsign (argv); return nilp; } if (quark == QUARK_ADDHEAD) { addhead (argv); return nilp; } if (quark == QUARK_ADDFOOT) { addfoot (argv); return nilp; } // 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_COLLEN ) return new Integer (getcols ()); if (quark == QUARK_TAGLEN ) return new Integer (tagslen ()); if (quark == QUARK_MARKLEN) return new Integer (marklen ()); if (quark == QUARK_SIGNLEN) return new Integer (signlen ()); if (quark == QUARK_GETNAME) return new String (getname ()); if (quark == QUARK_GETINFO) return new String (getinfo ()); if (quark == QUARK_CONVERT) return convert (0, 0, true); if (quark == QUARK_RESET) { reset (); return nilp; } if (quark == QUARK_SORT) { sort (0, true); return nilp; } } // dispatch 1 argument if (argc == 1) { if (quark == QUARK_SETNAME) { String name = argv->getstring (0); setname (name); return nilp; } if (quark == QUARK_SETINFO) { String info = argv->getstring (0); setinfo (info); return nilp; } if (quark == QUARK_ISTAGP) { Object* obj = argv->get (0); Literal* lobj = dynamic_cast (obj); if (lobj == nilp) { throw Exception ("type-error", "non literal object with tag-p", Object::repr (obj)); } String tag = lobj->tostring (); return new Boolean (istag (tag)); } if (quark == QUARK_GETTAG) { long index = argv->getint (0); return new String (gettag (index)); } if (quark == QUARK_ISMARKP) { Object* obj = argv->get (0); Literal* lobj = dynamic_cast (obj); if (lobj == nilp) { throw Exception ("type-error", "non literal object with marker-p", Object::repr (obj)); } String mark = lobj->tostring (); return new Boolean (ismark (mark)); } if (quark == QUARK_ISSIGNP) { Object* obj = argv->get (0); Literal* lobj = dynamic_cast (obj); if (lobj == nilp) { throw Exception ("type-error", "non literal object with sign-p", Object::repr (obj)); } String sign = lobj->tostring (); return new Boolean (issign (sign)); } if (quark == QUARK_GETMARK) { long index = argv->getint (0); return new String (getmark (index)); } if (quark == QUARK_GETSIGN) { long index = argv->getint (0); return new String (getsign (index)); } if (quark == QUARK_FINDTAG) { Object* obj = argv->get (0); Literal* lobj = dynamic_cast (obj); if (lobj == nilp) { throw Exception ("type-error", "non literal object with find-tag", Object::repr (obj)); } String tag = lobj->tostring (); return new Integer (findtag (tag)); } if (quark == QUARK_FINDMRK) { Object* obj = argv->get (0); Literal* lobj = dynamic_cast (obj); if (lobj == nilp) { throw Exception ("type-error", "non literal object with find-marker", Object::repr (obj)); } String mark = lobj->tostring (); return new Integer (findmark (mark)); } if (quark == QUARK_FINDSGN) { Object* obj = argv->get (0); Literal* lobj = dynamic_cast (obj); if (lobj == nilp) { throw Exception ("type-error", "non literal object with find-sign", Object::repr (obj)); } String sign = lobj->tostring (); return new Integer (findsign (sign)); } 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); Record* rcd = dynamic_cast (obj); if (rcd != nilp) { add (rcd); return nilp; } throw Exception ("type-error", "invalid object to add in sheet", Object::repr (obj)); } if (quark == QUARK_GETHEAD) { long index = argv->getint (0); rdlock (); try { Object* result = gethead (index); robj->post (result); unlock (); return result; } catch (...) { unlock (); throw; } } if (quark == QUARK_MAPHEAD) { long index = argv->getint (0); rdlock (); try { Object* result = maphead (index); robj->post (result); unlock (); return result; } catch (...) { unlock (); throw; } } if (quark == QUARK_GETFOOT) { long index = argv->getint (0); rdlock (); try { Object* result = getfoot (index); robj->post (result); unlock (); return result; } catch (...) { unlock (); throw; } } if (quark == QUARK_MAPFOOT) { long index = argv->getint (0); rdlock (); try { Object* result = mapfoot (index); robj->post (result); unlock (); return result; } catch (...) { unlock (); throw; } } if (quark == QUARK_IMPORT) { Object* obj = argv->get (0); Input* is = dynamic_cast (obj); if (is != nilp) { import (is); return nilp; } throw Exception ("type-error", "invalid object for sheet importation", Object::repr (obj)); } if (quark == QUARK_CONVERT) { long max = argv->getint (0); return convert (max, 0, true); } if (quark == QUARK_SORT) { Object* obj = argv->get (0); // check for integer Integer* col = dynamic_cast (obj); if (col != nilp) { sort (col->tointeger (), true); return nilp; } // check for boolean Boolean* mode = dynamic_cast (obj); if (mode != nilp) { sort (0, mode->toboolean ()); return nilp; } // invalid arguments throw Exception ("type-error", "invalid object for sorting ", Object::repr (obj)); } } // dispatch 2 argument if (argc == 2) { if (quark == QUARK_SETTAG) { long idx = argv->getint (0); Object* obj = argv->get (1); Literal* lobj = dynamic_cast (obj); if ((obj != nilp) && (lobj == nilp)) throw Exception ("type-error", "invalid object to set in tags", Object::repr (obj)); settag (idx, lobj); return nilp; } if (quark == QUARK_SETMARK) { long idx = argv->getint (0); Object* obj = argv->get (1); Literal* lobj = dynamic_cast (obj); if ((obj != nilp) && (lobj == nilp)) throw Exception ("type-error", "invalid object to set in marker", Object::repr (obj)); setmark (idx, lobj); return nilp; } if (quark == QUARK_SETSIGN) { long idx = argv->getint (0); Object* obj = argv->get (1); Literal* lobj = dynamic_cast (obj); if ((obj != nilp) && (lobj == nilp)) throw Exception ("type-error", "invalid object to set in signature", Object::repr (obj)); setsign (idx, lobj); return nilp; } if (quark == QUARK_SETHEAD) { long idx = argv->getint (0); Object* obj = argv->get (1); Literal* lobj = dynamic_cast (obj); if ((obj != nilp) && (lobj == nilp)) throw Exception ("type-error", "invalid object to set in header", Object::repr (obj)); sethead (idx, lobj); return nilp; } if (quark == QUARK_SETFOOT) { long idx = argv->getint (0); Object* obj = argv->get (1); Literal* lobj = dynamic_cast (obj); if ((obj != nilp) && (lobj == nilp)) throw Exception ("type-error", "invalid object to set in footer", Object::repr (obj)); setfoot (idx, lobj); return nilp; } if (quark == QUARK_GET) { long row = argv->getint (0); long col = argv->getint (1); rdlock (); try { Object* result = get (row, col); robj->post (result); unlock (); return result; } catch (...) { unlock (); throw; } } if (quark == QUARK_MAP) { long row = argv->getint (0); long col = argv->getint (1); rdlock (); try { Object* result = map (row, col); robj->post (result); unlock (); return result; } catch (...) { unlock (); throw; } } if (quark == QUARK_SET) { long idx = argv->getint (0); Object* obj = argv->get (1); Record* rcd = dynamic_cast (obj); if ((obj != nilp) && (rcd == nilp)) throw Exception ("type-error", "invalid object to set in sheet", Object::repr (obj)); set (idx, rcd); return nilp; } if (quark == QUARK_CONVERT) { long max = argv->getint (0); long start = argv->getint (1); return convert (max, start, true); } if (quark == QUARK_SORT) { long col = argv->getint (0); bool mode = argv->getbool (1); sort (col, mode); return nilp; } if (quark == QUARK_LINKCOL) { Object* obj = argv->get (0); Sheet* sht = dynamic_cast (obj); if (sht == nilp) { throw Exception ("type-error", "invalid object with link-column", Object::repr (obj)); } long col = argv->getint (1); lkcol (sht, col); return nilp; } } // dispatch 3 arguments if (argc == 3) { if (quark == QUARK_CONVERT) { long max = argv->getint (0); long start = argv->getint (1); bool flag = argv->getbool (2); return convert (max, start, flag); } if (quark == QUARK_SET) { long row = argv->getint (0); long col = argv->getint (1); Object* obj = argv->get (2); set (row, col, obj); return nilp; } } // call the persist method return Persist::apply (robj, nset, quark, argv); } }