1
// ---------------------------------------------------------------------------
3
// - afnix:sps module - sheet class implementation -
4
// ---------------------------------------------------------------------------
5
// - This program is free software; you can redistribute it and/or modify -
6
// - it provided that this copyright notice is kept intact. -
8
// - This program is distributed in the hope that it will be useful, but -
9
// - without any warranty; without even the implied warranty of -
10
// - merchantability or fitness for a particular purpose. In no event shall -
11
// - the copyright holder be liable for any direct, indirect, incidental or -
12
// - special damages arising in any way out of the use of this software. -
13
// ---------------------------------------------------------------------------
14
// - copyright (c) 1999-2015 amaury darsch -
15
// ---------------------------------------------------------------------------
19
#include "Boolean.hpp"
20
#include "Integer.hpp"
21
#include "Importer.hpp"
22
#include "Runnable.hpp"
23
#include "QuarkZone.hpp"
24
#include "Exception.hpp"
25
#include "InputStream.hpp"
26
#include "OutputStream.hpp"
30
// -------------------------------------------------------------------------
31
// - private section -
32
// -------------------------------------------------------------------------
41
// compare two objects for ascending order
42
bool cmplth (Object* ref, Object* slv) const {
43
// check that we have a object records
44
Record* rref = dynamic_cast <Record*> (ref);
45
Record* rslv = dynamic_cast <Record*> (slv);
46
// map the cell to their object
49
robj = (rref == nilp) ? nilp : rref->map (d_col);
55
sobj = (rslv == nilp) ? nilp : rslv->map (d_col);
59
// compare with operator
60
if (robj == nilp) return true;
61
Object* obj = robj->oper (Object::LTH, sobj);
62
Boolean* bobj = dynamic_cast <Boolean*> (obj);
63
bool result = (bobj == nilp) ? false : bobj->tobool ();
68
// compare two objects for descending order
69
bool cmpgth (Object* ref, Object* slv) const {
70
// check that we have a object records
71
Record* rref = dynamic_cast <Record*> (ref);
72
Record* rslv = dynamic_cast <Record*> (slv);
73
// map the cell to their object
76
robj = (rref == nilp) ? nilp : rref->map (d_col);
82
sobj = (rslv == nilp) ? nilp : rslv->map (d_col);
86
// compare with operator
87
if ((robj == nilp) && (sobj == nilp)) return true;
88
if ((robj == nilp) && (sobj != nilp)) return false;
89
Object* obj = robj->oper (Object::GTH, sobj);
90
Boolean* bobj = dynamic_cast <Boolean*> (obj);
91
bool result = (bobj == nilp) ? false : bobj->tobool ();
96
// partition the vector and returns the pivot index
98
long partition (Vector& argv, const long first, const long last) const {
99
// initialize the pivot index, last index and next (unknown) index
102
long uidx = lidx + 1;
103
// get the pivot object - and protect it
104
Object* pvt = Object::iref (argv.get (pidx));
105
// swap until we have reached the last element
106
while (uidx <= last) {
107
Object* ref = Object::iref (argv.get (uidx));
108
bool cflg = d_mode ? cmplth (ref, pvt) : cmpgth (ref, pvt);
111
argv.set (uidx, argv.get (lidx));
112
argv.set (lidx, ref);
115
// the intel is in the other region
118
// place the pivot in proper position
119
argv.set (first, argv.get (lidx));
120
argv.set (lidx, pvt);
122
// the pivot index is now the last index
126
// this function performs a recursive quick sort
128
void quicksort (Vector& argv, const long first, const long last) const {
129
if (first >= last) return;
130
long pidx = partition (argv, first, last);
131
quicksort (argv, first, pidx - 1);
132
quicksort (argv, pidx + 1, last);
136
// create a default sheet sorter
142
// create a sorting object by index
143
SheetSorter (const long col, const bool mode) {
150
void qsort (Vector& argv) const {
151
// sort the vector in place
154
long argc = argv.length ();
155
quicksort (argv, 0, argc - 1);
164
// this function computes the maximum between two numbers
165
static inline long max (const long x, const long y) {
166
return (x < y) ? y : x;
169
// this procedure returns a new sheet object for deserialization
170
static Serial* mksob (void) {
173
// register this cell serial id
174
static const t_byte SERIAL_ID = Serial::setsid (SERIAL_SHTT_ID, mksob);
177
// -------------------------------------------------------------------------
179
// -------------------------------------------------------------------------
181
// create a nil sheet
183
Sheet::Sheet (void) {
187
// create a new sheet by name
189
Sheet::Sheet (const String& name) {
194
// create a new sheet by name and info
196
Sheet::Sheet (const String& name, const String& info) {
202
// copy construct this sheet
204
Sheet::Sheet (const Sheet& that) {
207
d_name = that.d_name;
208
d_info = that.d_info;
209
d_tags = that.d_tags;
210
d_sign = that.d_sign;
211
d_mark = that.d_mark;
212
d_head = that.d_head;
213
d_foot = that.d_foot;
214
long hlen = that.d_hstl.length ();
215
for (long k = 0L; k < hlen; k++) {
216
Style* obj = dynamic_cast <Style*> (that.d_hstl.get (k));
217
Style* stl = (obj == nilp) ? nilp : new Style (*obj);
220
long slen = that.length ();
221
for (long i = 0; i < slen; i++) {
222
Record* rcd = that.get (i);
223
add (new Record (*rcd));
232
// return the object name
234
String Sheet::repr (void) const {
238
// return a clone of this object
240
Object* Sheet::clone (void) const {
241
return new Sheet (*this);
244
// return the sheet serial id
246
t_byte Sheet::serialid (void) const {
247
return SERIAL_SHTT_ID;
252
void Sheet::wrstream (OutputStream& os) const {
255
// save the sheet name
256
d_name.wrstream (os);
257
// save the sheet info
258
d_info.wrstream (os);
260
d_tags.wrstream (os);
261
// save the signature
262
d_sign.wrstream (os);
263
// save the header style
264
d_hstl.wrstream (os);
266
d_mark.wrstream (os);
268
d_head.wrstream (os);
270
d_foot.wrstream (os);
272
d_body.wrstream (os);
280
// deserialize this sheet
282
void Sheet::rdstream (InputStream& is) {
285
// get the sheet name
286
d_name.rdstream (is);
287
// get the sheet info
288
d_info.rdstream (is);
290
d_tags.rdstream (is);
292
d_sign.rdstream (is);
293
// get the header style
294
d_hstl.rdstream (is);
296
d_mark.rdstream (is);
298
d_head.rdstream (is);
300
d_foot.rdstream (is);
302
d_body.rdstream (is);
310
// assign a sheet to this one
312
Sheet& Sheet::operator = (const Sheet& that) {
313
// check for self assignation
314
if (this == &that) return *this;
320
d_name = that.d_name;
321
d_info = that.d_info;
322
d_tags = that.d_tags;
323
d_sign = that.d_sign;
324
d_mark = that.d_mark;
325
d_head = that.d_head;
326
d_foot = that.d_foot;
327
long hlen = that.d_hstl.length ();
328
for (long k = 0L; k < hlen; k++) {
329
Style* obj = dynamic_cast <Style*> (that.d_hstl.get (k));
330
Style* stl = (obj == nilp) ? nilp : new Style (*obj);
333
long slen = that.length ();
334
for (long i = 0; i < slen; i++) {
335
Record* rcd = that.get (i);
336
add (new Record (*rcd));
350
void Sheet::reset (void) {
368
void Sheet::clear (void) {
373
long blen = d_body.length ();
374
for (long k = 0L; k < blen; k++) {
375
Record* rcd = get (k);
376
if (rcd != nilp) rcd->clear ();
385
// return the sheet name
387
String Sheet::getname (void) const {
390
String result = d_name;
399
// set the sheet name
401
void Sheet::setname (const String& name) {
412
// return the sheet info
414
String Sheet::getinfo (void) const {
417
String result = d_info;
426
// set the sheet info
428
void Sheet::setinfo (const String& info) {
441
void Sheet::addtag (const String& tag) {
444
if (d_tags.exists (tag) == false) d_tags.add (tag);
452
// add a vector of literals in the tags descriptor
454
void Sheet::addtag (const Vector* argv) {
455
long argc = (argv == nilp) ? 0 : argv->length ();
456
if (argc == 0) return;
459
for (long i = 0; i < argc; i++) {
460
Object* obj = argv->get (i);
461
Literal* lobj = dynamic_cast <Literal*> (obj);
463
throw Exception ("type-error",
464
"non literal object with sheet add-tag",
467
d_tags.add (lobj->tostring ());
476
// return the tag descriptor length
478
long Sheet::tagslen (void) const {
481
long result = d_tags.length ();
490
// check if a tag exists
492
bool Sheet::istag (const String& tag) const {
495
bool result = d_tags.exists (tag);
504
// get a tag by index
506
String Sheet::gettag (const long index) const {
509
String result = d_tags.get (index);
518
// set the sheet tag by index
520
void Sheet::settag (const long index, Literal* lobj) {
523
String value = (lobj == nilp) ? "" : lobj->tostring ();
524
d_tags.set (index, value);
532
// find a tag index by tag
534
long Sheet::findtag (const String& tag) const {
537
long result = d_tags.lookup (tag);
546
// set a sheet signature
548
void Sheet::setsign (const String& sign) {
559
// get a sheet signature
561
String Sheet::getsign (void) const {
564
String result = d_sign;
573
// set a header style by index
575
void Sheet::sethstl (const long index, const Style& hstl) {
578
d_hstl.add (index, new Style (hstl));
586
// get a header style
588
Style* Sheet::gethstl (const long index) const {
591
long hlen = d_hstl.length ();
592
Style* result = (index < hlen)
593
? dynamic_cast <Style*> (d_hstl.get (index))
603
// add a boolean marker
605
void Sheet::addmark (const bool bval) {
616
// add an integer marker
618
void Sheet::addmark (const long ival) {
631
void Sheet::addmark (const t_real rval) {
642
// add a literal marker
644
void Sheet::addmark (Literal* mark) {
655
// get the sheet marker
657
Literal* Sheet::getmark (void) const {
660
Literal* result = d_mark.get (d_mark.getlidx ());
669
// add an object in the header record
671
void Sheet::addhead (Object* object) {
682
// add a vector of objects in the header record
684
void Sheet::addhead (const Vector* argv) {
685
long argc = (argv == nilp) ? 0 : argv->length ();
686
if (argc == 0) return;
689
for (long i = 0; i < argc; i++) d_head.add (argv->get (i));
697
// get a header cell by index
699
Cell* Sheet::gethead (const long index) const {
702
Cell* result = d_head.get (index);
711
// evaluate a header cell by index
713
Literal* Sheet::maphead (const long index) const {
716
Cell* cell = gethead (index);
717
Literal* result = (cell == nilp) ? nilp : cell->get ();
726
// set a record header by index and literal
728
Cell* Sheet::sethead (const long index, Literal* lobj) {
731
Cell* cell = d_head.set (index, lobj);
740
// add an object in the footer record
742
void Sheet::addfoot (Object* object) {
753
// add a vector of objects in the footer record
755
void Sheet::addfoot (const Vector* argv) {
756
long argc = (argv == nilp) ? 0 : argv->length ();
757
if (argc == 0) return;
760
for (long i = 0; i < argc; i++) d_foot.add (argv->get (i));
768
// get a footer cell by index
770
Cell* Sheet::getfoot (const long index) const {
773
Cell* result = dynamic_cast <Cell*> (d_foot.get (index));
782
// evaluate a footer cell by index
784
Literal* Sheet::mapfoot (const long index) const {
787
Cell* cell = getfoot (index);
788
Literal* result = (cell == nilp) ? nilp : cell->get ();
797
// set a record footer by index and literal
799
Cell* Sheet::setfoot (const long index, Literal* lobj) {
802
Cell* cell = dynamic_cast <Cell*> (d_foot.get (index));
803
if (cell != nilp) cell->set (lobj);
812
// return the length of the sheet list
814
long Sheet::length (void) const {
817
long result = d_body.length ();
826
// return the number of columns
828
long Sheet::getcols (void) const {
831
// get the sheet length
832
long tlen = length ();
833
// compute the maximum columns
835
for (long i = 0; i < tlen; i++) {
836
Record* rcd = get (i);
837
if (rcd == nilp) continue;
838
result = max (result, rcd->length ());
848
// add a record in this sheet
850
void Sheet::add (Record* rcd) {
851
if (rcd == nilp) return;
862
// get a record by index
864
Record* Sheet::get (const long index) const {
867
Record* result = dynamic_cast <Record*> (d_body.get (index));
876
// get a cell by row and column
878
Cell* Sheet::get (const long row, const long col) const {
882
Record* rcd = get (row);
888
Cell* cell = rcd->get (col);
897
// map a cell literal by ow and column
899
Literal* Sheet::map (const long row, const long col) const {
902
Cell* cell = get (row, col);
903
Literal* lobj = (cell == nilp) ? nilp : cell->get ();
912
// set a record in this sheet by index
914
void Sheet::set (const long index, Record* rcd) {
917
d_body.set (index, rcd);
925
// set an object in this sheet by row and column
927
Cell* Sheet::set (const long row, const long col, Object* object) {
930
// check if we have enough record
931
long slen = length ();
933
for (long k = slen; k <= row; k++) add (new Record);
936
Record* rcd = get (row);
938
Cell* cell = rcd->set (col, object);
947
// add a vector of literal as a record
949
void Sheet::adddata (const Vector* argv) {
950
long argc = (argv == nilp) ? 0 : argv->length ();
951
if (argc == 0) return;
953
Record* rcd = new Record;
955
for (long i = 0; i < argc; i++) rcd->add (argv->get (i));
965
// remove a record by index
967
void Sheet::remove (const long index) {
970
d_body.remove (index);
977
// import data in this sheet
979
void Sheet::import (InputStream* is) {
981
if (is == nilp) return;
982
// protect us during the importation
985
// create a new importer
998
// convert this sheet into a print sheet
1000
PrintTable* Sheet::convert (long max, long start, bool flag) const {
1002
PrintTable* result = nilp;
1004
// get the number of rows
1005
long rows = length ();
1006
// check for start index
1007
if ((rows != 0) && ((start < 0) || (start >= rows))) {
1008
throw Exception ("sheet-error", "start index out of range for convert");
1010
// check for max index
1011
long tlen = start + ((max == 0) ? rows : max);
1013
throw Exception ("sheet-error",
1014
"max index is out of range for convert");
1016
// create the print table
1017
long cols = getcols ();
1018
result = new PrintTable (cols);
1019
// set the column style if any
1020
for (long k = 0L; k < cols; k++) {
1021
Style* hstl = gethstl (k);
1022
if (hstl != nilp) result->setstyle (k, *hstl);
1024
// set the header if any
1025
for (long k = 0L; k < cols; k++) {
1026
Literal* lobj = maphead (k);
1028
if (flag == false) result->sethead (k, "nil");
1030
String data = flag ? lobj->tostring () : lobj->toliteral ();
1031
result->sethead (k, data);
1034
// set the footer if any
1035
for (long k = 0L; k < cols; k++) {
1036
Literal* lobj = mapfoot (k);
1038
if (flag == false) result->sethead (k, "nil");
1040
String data = flag ? lobj->tostring () : lobj->toliteral ();
1041
result->setfoot (k, data);
1044
// iterate through the record
1045
for (long i = start; i < tlen; i++) {
1046
Record* rcd = get (i);
1047
if (rcd == nilp) continue;
1048
long row = result->add ();
1049
// get the record length
1050
long rlen = rcd->length ();
1051
for (long j = 0; j < rlen; j++) {
1053
Literal* lobj = rcd->map (j);
1054
// get the associated style
1055
Style* cstl = rcd->getstyle (j);
1056
if (cstl == nilp) cstl = gethstl (j);
1057
// translate the literal
1059
String data = flag ? "" : "nil";
1060
result->set (row, j, data);
1063
String data = flag ? lobj->tostring () : lobj->toliteral ();
1064
result->set (row, j, data);
1066
String data = flag ? lobj->format (*cstl) : lobj->toliteral ();
1067
result->set (row, j, data);
1071
// fill the rest of the sheet
1072
String text = flag ? "" : "nil";
1073
for (long j = rlen; j < cols; j++) result->set (row, j, text);
1084
// sort this sheet by column index and mode
1086
void Sheet::sort (const long col, const bool mode) {
1089
// build the sorter object
1090
SheetSorter sorter (col, mode);
1092
sorter.qsort (d_body);
1100
// link a sheet column into this sheet
1102
void Sheet::lkcol (const Sheet* sheet, const long col) {
1103
// check for a sheet and lock
1104
if ((sheet == nilp) || (sheet == this)) return;
1108
// get the insert column
1109
long cidx = getcols ();
1110
// get the column size
1111
long size = sheet->length ();
1113
for (long i = 0; i < size; i++) {
1114
Cell* cell = sheet->get (i, col);
1115
set (i, cidx, cell);
1124
// check if a row exists by column index and literal
1126
bool Sheet::isrow (const long col, const Literal& lobj) const {
1129
// get the number of rows
1130
long rows = length ();
1131
// initialize result
1132
bool result = false;
1133
// loop in the sheet and check
1134
for (long row = 0; row < rows; row++) {
1135
Record* rcd = get (row);
1136
if (rcd == nilp) continue;
1137
if (rcd->isequal (col, lobj) == true) {
1150
// find a row by column index and literal
1152
long Sheet::rfind (const long col, const Literal& lobj) const {
1155
// get the number of rows
1156
long rows = length ();
1157
// initialize result
1159
// loop in the sheet and check
1160
for (long row = 0; row < rows; row++) {
1161
Record* rcd = get (row);
1162
if (rcd == nilp) continue;
1163
if (rcd->isequal (col, lobj) == true) {
1176
// find a row by column index and literal or throw an exception
1178
long Sheet::rlookup (const long col, const Literal& lobj) const {
1181
long result = rfind (col, lobj);
1183
throw Exception ("lookup-error", "cannot find row by literal",
1194
// -------------------------------------------------------------------------
1195
// - object section -
1196
// -------------------------------------------------------------------------
1199
static const long QUARK_ZONE_LENGTH = 38;
1200
static QuarkZone zone (QUARK_ZONE_LENGTH);
1202
// the sheet supported quarks
1203
static const long QUARK_ADD = zone.intern ("add");
1204
static const long QUARK_GET = zone.intern ("get");
1205
static const long QUARK_MAP = zone.intern ("map");
1206
static const long QUARK_SET = zone.intern ("set");
1207
static const long QUARK_SORT = zone.intern ("sort");
1208
static const long QUARK_RESET = zone.intern ("reset");
1209
static const long QUARK_CLEAR = zone.intern ("clear");
1210
static const long QUARK_RFIND = zone.intern ("find-row");
1211
static const long QUARK_REMOVE = zone.intern ("remove");
1212
static const long QUARK_ISROWP = zone.intern ("row-p");
1213
static const long QUARK_IMPORT = zone.intern ("import");
1214
static const long QUARK_LENGTH = zone.intern ("length");
1215
static const long QUARK_COLLEN = zone.intern ("column-length");
1216
static const long QUARK_ADDTAG = zone.intern ("add-tag");
1217
static const long QUARK_TAGLEN = zone.intern ("tag-length");
1218
static const long QUARK_ISTAGP = zone.intern ("tag-p");
1219
static const long QUARK_GETTAG = zone.intern ("get-tag");
1220
static const long QUARK_SETTAG = zone.intern ("set-tag");
1221
static const long QUARK_FINDTAG = zone.intern ("find-tag");
1222
static const long QUARK_CONVERT = zone.intern ("convert");
1223
static const long QUARK_SETNAME = zone.intern ("set-name");
1224
static const long QUARK_GETINFO = zone.intern ("get-info");
1225
static const long QUARK_SETINFO = zone.intern ("set-info");
1226
static const long QUARK_GETSIGN = zone.intern ("get-signature");
1227
static const long QUARK_SETSIGN = zone.intern ("set-signature");
1228
static const long QUARK_ADDMARK = zone.intern ("add-marker");
1229
static const long QUARK_GETMARK = zone.intern ("get-marker");
1230
static const long QUARK_ADDHEAD = zone.intern ("add-header");
1231
static const long QUARK_GETHEAD = zone.intern ("get-header");
1232
static const long QUARK_MAPHEAD = zone.intern ("map-header");
1233
static const long QUARK_SETHEAD = zone.intern ("set-header");
1234
static const long QUARK_ADDFOOT = zone.intern ("add-footer");
1235
static const long QUARK_GETFOOT = zone.intern ("get-footer");
1236
static const long QUARK_MAPFOOT = zone.intern ("map-footer");
1237
static const long QUARK_SETFOOT = zone.intern ("set-footer");
1238
static const long QUARK_ADDDATA = zone.intern ("add-data");
1239
static const long QUARK_LINKCOL = zone.intern ("link-column");
1240
static const long QUARK_RLOOKUP = zone.intern ("lookup-row");
1242
// create a new object in a generic way
1244
Object* Sheet::mknew (Vector* argv) {
1245
// get number of arguments
1246
long argc = (argv == nilp) ? 0 : argv->length ();
1247
// check for 0 argument
1248
if (argc == 0) return new Sheet;
1249
// check for 1 argument
1251
String name = argv->getstring (0);
1252
return new Sheet (name);
1254
// check for 2 arguments
1256
String name = argv->getstring (0);
1257
String info = argv->getstring (1);
1258
return new Sheet (name, info);
1260
throw Exception ("argument-error", "too many argument with sheet");
1263
// return true if the given quark is defined
1265
bool Sheet::isquark (const long quark, const bool hflg) const {
1267
if (zone.exists (quark) == true) {
1271
bool result = hflg ? Saveas::isquark (quark, hflg) : false;
1276
// apply this object with a set of arguments and a quark
1278
Object* Sheet::apply (Runnable* robj, Nameset* nset, const long quark,
1280
// check for generic quark
1281
if (quark == QUARK_ADDDATA) {
1285
if (quark == QUARK_ADDTAG) {
1289
if (quark == QUARK_ADDHEAD) {
1293
if (quark == QUARK_ADDFOOT) {
1298
// get the number of arguments
1299
long argc = (argv == nilp) ? 0 : argv->length ();
1301
// dispatch 0 argument
1303
if (quark == QUARK_LENGTH ) return new Integer (length ());
1304
if (quark == QUARK_COLLEN ) return new Integer (getcols ());
1305
if (quark == QUARK_TAGLEN ) return new Integer (tagslen ());
1306
if (quark == QUARK_GETINFO) return new String (getinfo ());
1307
if (quark == QUARK_GETSIGN) return new String (getsign ());
1308
if (quark == QUARK_GETMARK) return getmark ();
1309
if (quark == QUARK_CONVERT) return convert (0, 0, true);
1310
if (quark == QUARK_RESET) {
1314
if (quark == QUARK_CLEAR) {
1318
if (quark == QUARK_SORT) {
1324
// dispatch 1 argument
1326
if (quark == QUARK_SETNAME) {
1327
String name = argv->getstring (0);
1331
if (quark == QUARK_SETINFO) {
1332
String info = argv->getstring (0);
1336
if (quark == QUARK_ADDMARK) {
1337
Object* obj = argv->get (0);
1338
Literal* lobj = dynamic_cast <Literal*> (obj);
1339
if ((obj != nilp) && (lobj == nilp)) {
1340
throw Exception ("type-error", "non literal object with add-marker",
1341
Object::repr (obj));
1346
if (quark == QUARK_SETSIGN) {
1347
String sign = argv->getstring (0);
1351
if (quark == QUARK_ISTAGP) {
1352
Object* obj = argv->get (0);
1353
Literal* lobj = dynamic_cast <Literal*> (obj);
1355
throw Exception ("type-error", "non literal object with tag-p",
1356
Object::repr (obj));
1358
String tag = lobj->tostring ();
1359
return new Boolean (istag (tag));
1361
if (quark == QUARK_GETTAG) {
1362
long index = argv->getlong (0);
1363
return new String (gettag (index));
1365
if (quark == QUARK_FINDTAG) {
1366
Object* obj = argv->get (0);
1367
Literal* lobj = dynamic_cast <Literal*> (obj);
1369
throw Exception ("type-error", "non literal object with find-tag",
1370
Object::repr (obj));
1372
String tag = lobj->tostring ();
1373
return new Integer (findtag (tag));
1375
if (quark == QUARK_GET) {
1376
long idx = argv->getlong (0);
1379
Object* result = get (idx);
1380
robj->post (result);
1388
if (quark == QUARK_ADD) {
1389
Object* obj = argv->get (0);
1390
Record* rcd = dynamic_cast <Record*> (obj);
1395
throw Exception ("type-error", "invalid object to add in sheet",
1396
Object::repr (obj));
1398
if (quark == QUARK_GETHEAD) {
1399
long index = argv->getlong (0);
1402
Object* result = gethead (index);
1403
robj->post (result);
1411
if (quark == QUARK_MAPHEAD) {
1412
long index = argv->getlong (0);
1415
Object* result = maphead (index);
1416
robj->post (result);
1424
if (quark == QUARK_GETFOOT) {
1425
long index = argv->getlong (0);
1428
Object* result = getfoot (index);
1429
robj->post (result);
1437
if (quark == QUARK_MAPFOOT) {
1438
long index = argv->getlong (0);
1441
Object* result = mapfoot (index);
1442
robj->post (result);
1450
if (quark == QUARK_REMOVE) {
1451
long index= argv->getlong (0);
1455
if (quark == QUARK_IMPORT) {
1456
Object* obj = argv->get (0);
1457
InputStream* is = dynamic_cast <InputStream*> (obj);
1462
throw Exception ("type-error", "invalid object for sheet importation",
1463
Object::repr (obj));
1465
if (quark == QUARK_CONVERT) {
1466
long max = argv->getlong (0);
1467
return convert (max, 0, true);
1469
if (quark == QUARK_SORT) {
1470
Object* obj = argv->get (0);
1471
// check for integer
1472
Integer* col = dynamic_cast <Integer*> (obj);
1474
sort (col->tolong (), true);
1477
// check for boolean
1478
Boolean* mode = dynamic_cast <Boolean*> (obj);
1480
sort (0, mode->tobool ());
1483
// invalid arguments
1484
throw Exception ("type-error", "invalid object for sorting ",
1485
Object::repr (obj));
1489
// dispatch 2 argument
1491
if (quark == QUARK_SETTAG) {
1492
long idx = argv->getlong (0);
1493
Object* obj = argv->get (1);
1494
Literal* lobj = dynamic_cast <Literal*> (obj);
1495
if ((obj != nilp) && (lobj == nilp))
1496
throw Exception ("type-error", "invalid object to set in tags",
1497
Object::repr (obj));
1501
if (quark == QUARK_SETHEAD) {
1502
long idx = argv->getlong (0);
1503
Object* obj = argv->get (1);
1504
Literal* lobj = dynamic_cast <Literal*> (obj);
1505
if ((obj != nilp) && (lobj == nilp))
1506
throw Exception ("type-error", "invalid object to set in header",
1507
Object::repr (obj));
1510
Object* result = sethead (idx, lobj);
1511
robj->post (result);
1519
if (quark == QUARK_SETFOOT) {
1520
long idx = argv->getlong (0);
1521
Object* obj = argv->get (1);
1522
Literal* lobj = dynamic_cast <Literal*> (obj);
1523
if ((obj != nilp) && (lobj == nilp))
1524
throw Exception ("type-error", "invalid object to set in footer",
1525
Object::repr (obj));
1528
Object* result = setfoot (idx, lobj);
1529
robj->post (result);
1537
if (quark == QUARK_GET) {
1538
long row = argv->getlong (0);
1539
long col = argv->getlong (1);
1542
Object* result = get (row, col);
1543
robj->post (result);
1551
if (quark == QUARK_MAP) {
1552
long row = argv->getlong (0);
1553
long col = argv->getlong (1);
1556
Object* result = map (row, col);
1557
robj->post (result);
1565
if (quark == QUARK_SET) {
1566
long idx = argv->getlong (0);
1567
Object* obj = argv->get (1);
1568
Record* rcd = dynamic_cast <Record*> (obj);
1569
if ((obj != nilp) && (rcd == nilp))
1570
throw Exception ("type-error", "invalid object to set in sheet",
1571
Object::repr (obj));
1575
if (quark == QUARK_CONVERT) {
1576
long max = argv->getlong (0);
1577
long start = argv->getlong (1);
1578
return convert (max, start, true);
1580
if (quark == QUARK_SORT) {
1581
long col = argv->getlong (0);
1582
bool mode = argv->getbool (1);
1586
if (quark == QUARK_LINKCOL) {
1587
Object* obj = argv->get (0);
1588
Sheet* sht = dynamic_cast <Sheet*> (obj);
1590
throw Exception ("type-error", "invalid object with link-column",
1591
Object::repr (obj));
1593
long col = argv->getlong (1);
1597
if (quark == QUARK_ISROWP) {
1598
long col = argv->getlong (0);
1599
Object* obj = argv->get (1);
1600
Literal* lobj = dynamic_cast <Literal*> (obj);
1601
if ((obj != nilp) && (lobj == nilp))
1602
throw Exception ("type-error", "invalid object for row check",
1603
Object::repr (obj));
1604
bool result = isrow (col, *lobj);
1605
return new Boolean (result);
1607
if (quark == QUARK_RFIND) {
1608
long col = argv->getlong (0);
1609
Object* obj = argv->get (1);
1610
Literal* lobj = dynamic_cast <Literal*> (obj);
1611
if ((obj != nilp) && (lobj == nilp))
1612
throw Exception ("type-error", "invalid object for row find",
1613
Object::repr (obj));
1614
long result = rfind (col, *lobj);
1615
return new Integer (result);
1617
if (quark == QUARK_RLOOKUP) {
1618
long col = argv->getlong (0);
1619
Object* obj = argv->get (1);
1620
Literal* lobj = dynamic_cast <Literal*> (obj);
1621
if ((obj != nilp) && (lobj == nilp))
1622
throw Exception ("type-error", "invalid object for row lookup",
1623
Object::repr (obj));
1624
long result = rlookup (col, *lobj);
1625
return new Integer (result);
1628
// dispatch 3 arguments
1630
if (quark == QUARK_CONVERT) {
1631
long max = argv->getlong (0);
1632
long start = argv->getlong (1);
1633
bool flag = argv->getbool (2);
1634
return convert (max, start, flag);
1636
if (quark == QUARK_SET) {
1637
long row = argv->getlong (0);
1638
long col = argv->getlong (1);
1639
Object* obj = argv->get (2);
1642
Object* result = set (row, col, obj);
1643
robj->post (result);
1652
// call the saveas method
1653
return Saveas::apply (robj, nset, quark, argv);