00001
00002
00003
00004
00005 #ifndef IBIS_BORD_H
00006 #define IBIS_BORD_H
00007 #include "table.h"
00008 #include "util.h"
00009 #include "part.h"
00010
00014 namespace ibis {
00015 class bord;
00016 }
00017
00028 class ibis::bord : public ibis::table {
00029 public:
00030 typedef std::vector<void *> bufferList;
00031 bord(const char *tn, const char *td, uint64_t nr,
00032 const ibis::table::stringList &cn,
00033 const ibis::table::typeList &ct,
00034 const bufferList &buf, const ibis::table::stringList *cdesc=0);
00035 virtual ~bord() {clear();}
00036
00037 virtual uint64_t nRows() const {return mypart.nRows();}
00038 virtual uint32_t nColumns() const {return mypart.nColumns();}
00039
00040 virtual ibis::table::stringList columnNames() const;
00041 virtual ibis::table::typeList columnTypes() const;
00042
00043 virtual void describe(std::ostream&) const;
00044 virtual void dumpNames(std::ostream&, const char*) const;
00045 virtual int dump(std::ostream&, const char*) const;
00046 virtual int dump(std::ostream&, uint64_t, const char*) const;
00047
00048 virtual int64_t getColumnAsBytes(const char*, char*) const;
00049 virtual int64_t getColumnAsUBytes(const char*, unsigned char*) const;
00050 virtual int64_t getColumnAsShorts(const char*, int16_t*) const;
00051 virtual int64_t getColumnAsUShorts(const char*, uint16_t*) const;
00052 virtual int64_t getColumnAsInts(const char*, int32_t*) const;
00053 virtual int64_t getColumnAsUInts(const char*, uint32_t*) const;
00054 virtual int64_t getColumnAsLongs(const char*, int64_t*) const;
00055 virtual int64_t getColumnAsULongs(const char*, uint64_t*) const;
00056 virtual int64_t getColumnAsFloats(const char*, float*) const;
00057 virtual int64_t getColumnAsDoubles(const char*, double*) const;
00058 virtual int64_t getColumnAsDoubles(const char*,
00059 std::vector<double>&) const;
00060 virtual int64_t getColumnAsStrings(const char*,
00061 std::vector<std::string>&) const;
00062
00063 virtual long getHistogram(const char*, const char*,
00064 double, double, double,
00065 std::vector<uint32_t>&) const;
00066 virtual long getHistogram2D(const char*, const char*,
00067 double, double, double,
00068 const char*,
00069 double, double, double,
00070 std::vector<uint32_t>&) const;
00071 virtual long getHistogram3D(const char*, const char*,
00072 double, double, double,
00073 const char*,
00074 double, double, double,
00075 const char*,
00076 double, double, double,
00077 std::vector<uint32_t>&) const;
00078
00079 virtual void estimate(const char* cond,
00080 uint64_t& nmin, uint64_t& nmax) const;
00081 virtual void estimate(const ibis::qExpr* cond,
00082 uint64_t& nmin, uint64_t& nmax) const;
00083 using table::select;
00084 virtual table* select(const char* sel, const char* cond) const;
00085 virtual table* groupby(const ibis::table::stringList&) const;
00086 virtual table* groupby(const char* str) const;
00087 virtual void orderby(const ibis::table::stringList&);
00088 virtual void orderby(const char* str) {
00089 ibis::table::orderby(str);
00090 }
00091 virtual void reverseRows();
00092
00093 virtual int buildIndex(const char*, const char*) {return -1;}
00094 virtual int buildIndexes(const char*) {return -1;}
00095 virtual const char* indexSpec(const char*) const {return 0;}
00096 virtual void indexSpec(const char*, const char*) {return;}
00097 virtual int getPartitions(std::vector<const ibis::part*> &) const;
00098
00099
00100 class cursor;
00102 virtual ibis::table::cursor* createCursor() const;
00103
00104 int restoreCategoriesAsStrings(const ibis::part&, const char*);
00105 ibis::table* groupby(const ibis::selectClause&) const;
00106
00107 protected:
00108 class column;
00110 class part : public ibis::part {
00111 public:
00112 part(const char *tn, const char *td, uint64_t nr,
00113 const ibis::table::stringList &cn,
00114 const ibis::table::typeList &ct,
00115 const ibis::bord::bufferList &buf,
00116 const ibis::table::stringList *cdesc=0);
00117
00118 template <typename E>
00119 long doScan(const array_t<E>& varr,
00120 const ibis::qContinuousRange& cmp,
00121 const ibis::bitvector& mask,
00122 ibis::bitvector& hits) const {
00123 return ibis::part::doScan(varr, cmp, mask, hits);}
00124
00125 ibis::table* groupby(const ibis::selectClause&) const;
00126 virtual long reorder(const ibis::table::stringList&);
00127 virtual long reorder() {return ibis::part::reorder();}
00128
00129 virtual int dump(std::ostream&, uint32_t, const char*) const;
00130
00131 void describe(std::ostream&) const;
00132 void dumpNames(std::ostream&, const char*) const;
00133 void reverseRows();
00134 int limit(uint32_t);
00135
00136 template <typename T>
00137 long sortValues(array_t<T>& vals,
00138 const array_t<uint32_t>& indin,
00139 array_t<uint32_t>& indout,
00140 array_t<uint32_t>& starts) const;
00141 template <typename T>
00142 long reorderValues(array_t<T>& vals,
00143 const array_t<uint32_t>& ind) const;
00144 long sortStrings(std::vector<std::string>& vals,
00145 const array_t<uint32_t>& idxin,
00146 array_t<uint32_t>& idxout,
00147 array_t<uint32_t>& starts) const;
00148 long reorderStrings(std::vector<std::string>& vals,
00149 const array_t<uint32_t>& ind) const;
00150
00151 int restoreCategoriesAsStrings(const ibis::part&, const char*);
00152
00153 private:
00154 part();
00155 part(const part&);
00156 part& operator=(const part&);
00157 };
00158
00159 part mypart;
00160
00162 void clear();
00164 int64_t computeHits(const char* cond) const;
00165
00166 private:
00167
00168 bord(const bord&);
00169 bord& operator=(const bord&);
00170
00171 friend class cursor;
00172 };
00173
00183 class ibis::bord::column : public ibis::column {
00184 public:
00185 column(const ibis::bord::part* tbl, ibis::TYPE_T t,
00186 const char* name, void *buf,
00187 const char* desc="", double low=DBL_MAX, double high=-DBL_MAX);
00188 column(const ibis::bord::part*, const ibis::column&, void *buf);
00189 column(const column& rhs);
00190 virtual ~column();
00191
00192 virtual ibis::fileManager::storage* getRawData() const;
00193
00194 virtual long evaluateRange(const ibis::qContinuousRange& cmp,
00195 const ibis::bitvector& mask,
00196 ibis::bitvector& res) const;
00197 virtual array_t<int32_t>* selectInts(const ibis::bitvector& mask) const;
00198 virtual array_t<uint32_t>* selectUInts(const ibis::bitvector& mask) const;
00199 virtual array_t<int64_t>* selectLongs(const ibis::bitvector& mask) const;
00200 virtual array_t<float>* selectFloats(const ibis::bitvector& mask) const;
00201 virtual array_t<double>* selectDoubles(const ibis::bitvector& mask) const;
00202
00203 virtual void computeMinMax() {
00204 computeMinMax(thePart->currentDataDir(), lower, upper);}
00205 virtual void computeMinMax(const char *dir) {
00206 computeMinMax(dir, lower, upper);}
00207 virtual void computeMinMax(const char *, double &min, double &max) const;
00208 virtual void getString(uint32_t i, std::string &val) const;
00209
00210 void reverseRows();
00211 int limit(uint32_t nr);
00212
00213 void* getArray() const {return buffer;}
00214 template <typename T> int getRawData(array_t<T> &vals) const;
00215 int dump(std::ostream& out, uint32_t i) const;
00216
00217 int restoreCategoriesAsStrings(const ibis::part&);
00218
00219 protected:
00222 void *buffer;
00223
00224 column& operator=(const column&);
00225 };
00226
00227 class ibis::bord::cursor : public ibis::table::cursor {
00228 public:
00229 cursor(const ibis::bord& t);
00230 virtual ~cursor() {};
00231
00232 virtual uint64_t nRows() const {return tab.nRows();}
00233 virtual uint32_t nColumns() const {return tab.nColumns();}
00234 virtual ibis::table::stringList columnNames() const {
00235 return tab.columnNames();}
00236 virtual ibis::table::typeList columnTypes() const {
00237 return tab.columnTypes();}
00238 virtual int fetch();
00239 virtual int fetch(uint64_t);
00240 virtual int fetch(ibis::table::row&);
00241 virtual int fetch(uint64_t, ibis::table::row&);
00242 virtual uint64_t getCurrentRowNumber() const {return curRow;}
00243 virtual int dump(std::ostream& out, const char* del) const;
00244
00245 virtual int getColumnAsByte(const char*, char&) const;
00246 virtual int getColumnAsUByte(const char*, unsigned char&) const;
00247 virtual int getColumnAsShort(const char*, int16_t&) const;
00248 virtual int getColumnAsUShort(const char*, uint16_t&) const;
00249 virtual int getColumnAsInt(const char*, int32_t&) const;
00250 virtual int getColumnAsUInt(const char*, uint32_t&) const;
00251 virtual int getColumnAsLong(const char*, int64_t&) const;
00252 virtual int getColumnAsULong(const char*, uint64_t&) const;
00253 virtual int getColumnAsFloat(const char*, float&) const;
00254 virtual int getColumnAsDouble(const char*, double&) const;
00255 virtual int getColumnAsString(const char*, std::string&) const;
00256
00257 virtual int getColumnAsByte(uint32_t, char&) const;
00258 virtual int getColumnAsUByte(uint32_t, unsigned char&) const;
00259 virtual int getColumnAsShort(uint32_t, int16_t&) const;
00260 virtual int getColumnAsUShort(uint32_t, uint16_t&) const;
00261 virtual int getColumnAsInt(uint32_t, int32_t&) const;
00262 virtual int getColumnAsUInt(uint32_t, uint32_t&) const;
00263 virtual int getColumnAsLong(uint32_t, int64_t&) const;
00264 virtual int getColumnAsULong(uint32_t, uint64_t&) const;
00265 virtual int getColumnAsFloat(uint32_t, float&) const;
00266 virtual int getColumnAsDouble(uint32_t, double&) const;
00267 virtual int getColumnAsString(uint32_t, std::string&) const;
00268
00269 protected:
00270 struct bufferElement {
00271 const char* cname;
00272 ibis::TYPE_T ctype;
00273 void* cval;
00274
00275 bufferElement() : cname(0), ctype(ibis::UNKNOWN_TYPE), cval(0) {}
00276 };
00277 typedef std::map<const char*, uint32_t, ibis::lessi> bufferMap;
00278 std::vector<bufferElement> buffer;
00279 bufferMap bufmap;
00280 const ibis::bord& tab;
00281 int64_t curRow;
00282
00283 void fillRow(ibis::table::row& res) const;
00284 int dumpIJ(std::ostream&, uint32_t, uint32_t) const;
00285
00286 private:
00287 cursor();
00288 cursor(const cursor&);
00289 cursor& operator=(const cursor&);
00290 };
00291
00292 inline void ibis::bord::describe(std::ostream &out) const {
00293 mypart.describe(out);
00294 }
00295
00296 inline void ibis::bord::dumpNames(std::ostream &out, const char* del) const {
00297 mypart.dumpNames(out, del);
00298 }
00299
00300 inline int ibis::bord::dump(std::ostream &out, const char* del) const {
00301 return mypart.dump(out, mypart.nRows(), del);
00302 }
00303
00304 inline int ibis::bord::dump(std::ostream &out, uint64_t nr,
00305 const char* del) const {
00306 return mypart.dump(out, static_cast<uint32_t>(nr), del);
00307 }
00308
00309 inline ibis::table* ibis::bord::groupby(const ibis::selectClause &sc) const {
00310 return mypart.groupby(sc);
00311 }
00312
00313 inline void ibis::bord::orderby(const ibis::table::stringList& keys) {
00314 mypart.reorder(keys);
00315 }
00316
00317 inline void ibis::bord::reverseRows() {
00318 mypart.reverseRows();
00319 }
00320
00321 inline ibis::table::cursor* ibis::bord::createCursor() const {
00322 return new ibis::bord::cursor(*this);
00323 }
00324
00326 inline int
00327 ibis::bord::restoreCategoriesAsStrings(const ibis::part& prt, const char* nm) {
00328 return mypart.restoreCategoriesAsStrings(prt, nm);
00329 }
00330
00332 inline int
00333 ibis::bord::part::restoreCategoriesAsStrings(const ibis::part& prt,
00334 const char* nm) {
00335 if (nm == 0 || *nm == 0)
00336 return -1;
00337 ibis::bord::column *col = static_cast<ibis::bord::column*>(getColumn(nm));
00338 if (col != 0)
00339 return col->restoreCategoriesAsStrings(prt);
00340 else
00341 return -2;
00342 }
00343
00348 template <typename T>
00349 inline int ibis::bord::column::getRawData(array_t<T> &vals) const {
00350 array_t<T> tmp(*static_cast<const array_t<T>*>(buffer));
00351 vals.swap(tmp);
00352 return 0;
00353 }
00354
00355 inline ibis::fileManager::storage*
00356 ibis::bord::column::getRawData() const {
00357 return 0;
00358 }
00359
00360 inline int ibis::bord::column::dump(std::ostream& out, uint32_t i) const {
00361 int ierr = -1;
00362 if (buffer == 0) {
00363 out << "(no data in memory)";
00364 return ierr;
00365 }
00366
00367 switch (m_type) {
00368 case ibis::BYTE: {
00369 const array_t<signed char>* vals =
00370 static_cast<const array_t<signed char>*>(buffer);
00371 out << (int)((*vals)[i]);
00372 ierr = 0;
00373 break;}
00374 case ibis::UBYTE: {
00375 const array_t<unsigned char>* vals =
00376 static_cast<const array_t<unsigned char>*>(buffer);
00377 out << (unsigned)((*vals)[i]);
00378 ierr = 0;
00379 break;}
00380 case ibis::SHORT: {
00381 const array_t<int16_t>* vals =
00382 static_cast<const array_t<int16_t>*>(buffer);
00383 out << (*vals)[i];
00384 ierr = 0;
00385 break;}
00386 case ibis::USHORT: {
00387 const array_t<uint16_t>* vals =
00388 static_cast<const array_t<uint16_t>*>(buffer);
00389 out << (*vals)[i];
00390 ierr = 0;
00391 break;}
00392 case ibis::INT: {
00393 const array_t<int32_t>* vals =
00394 static_cast<const array_t<int32_t>*>(buffer);
00395 out << (*vals)[i];
00396 ierr = 0;
00397 break;}
00398 case ibis::UINT: {
00399 const array_t<uint32_t>* vals =
00400 static_cast<const array_t<uint32_t>*>(buffer);
00401 out << (*vals)[i];
00402 ierr = 0;
00403 break;}
00404 case ibis::LONG: {
00405 const array_t<int64_t>* vals =
00406 static_cast<const array_t<int64_t>*>(buffer);
00407 out << (*vals)[i];
00408 ierr = 0;
00409 break;}
00410 case ibis::ULONG: {
00411 const array_t<uint64_t>* vals =
00412 static_cast<const array_t<uint64_t>*>(buffer);
00413 out << (*vals)[i];
00414 ierr = 0;
00415 break;}
00416 case ibis::FLOAT: {
00417 const array_t<float>* vals =
00418 static_cast<const array_t<float>*>(buffer);
00419 out << std::setprecision(7) << (*vals)[i];
00420 ierr = 0;
00421 break;}
00422 case ibis::DOUBLE: {
00423 const array_t<double>* vals =
00424 static_cast<const array_t<double>*>(buffer);
00425 out << std::setprecision(15) << (*vals)[i];
00426 ierr = 0;
00427 break;}
00428 case ibis::TEXT:
00429 case ibis::CATEGORY: {
00430 std::string tmp;
00431 getString(i, tmp);
00432 out << tmp;
00433 ierr = 0;
00434 break;}
00435 default: {
00436 ierr = -2;
00437 break;}
00438 }
00439 return ierr;
00440 }
00441
00442 inline int ibis::bord::cursor::fetch() {
00443 ++ curRow;
00444 return (0 - (curRow >= (int64_t) tab.nRows()));
00445 }
00446
00447 inline int ibis::bord::cursor::fetch(uint64_t irow) {
00448 if (irow < tab.nRows()) {
00449 curRow = static_cast<int64_t>(irow);
00450 return 0;
00451 }
00452 else {
00453 return -1;
00454 }
00455 }
00456
00457 inline int ibis::bord::cursor::fetch(ibis::table::row& res) {
00458 ++ curRow;
00459 if ((uint64_t) curRow < tab.nRows()) {
00460 fillRow(res);
00461 return 0;
00462 }
00463 else {
00464 return -1;
00465 }
00466 }
00467
00468 inline int ibis::bord::cursor::fetch(uint64_t irow, ibis::table::row& res) {
00469 if (irow < tab.nRows()) {
00470 curRow = static_cast<int64_t>(irow);
00471 fillRow(res);
00472 return 0;
00473 }
00474 else {
00475 return -1;
00476 }
00477 }
00478
00479 inline int
00480 ibis::bord::cursor::dumpIJ(std::ostream& out, uint32_t i,
00481 uint32_t j) const {
00482 if (buffer[j].cval == 0) return -1;
00483
00484 switch (buffer[j].ctype) {
00485 case ibis::BYTE: {
00486 const array_t<const signed char>* vals =
00487 static_cast<const array_t<const signed char>*>(buffer[j].cval);
00488 out << (int) ((*vals)[i]);
00489 break;}
00490 case ibis::UBYTE: {
00491 const array_t<const unsigned char>* vals =
00492 static_cast<const array_t<const unsigned char>*>(buffer[j].cval);
00493 out << (unsigned int) ((*vals)[i]);
00494 break;}
00495 case ibis::SHORT: {
00496 const array_t<const int16_t>* vals =
00497 static_cast<const array_t<const int16_t>*>(buffer[j].cval);
00498 out << (*vals)[i];
00499 break;}
00500 case ibis::USHORT: {
00501 const array_t<const uint16_t>* vals =
00502 static_cast<const array_t<const uint16_t>*>(buffer[j].cval);
00503 out << (*vals)[i];
00504 break;}
00505 case ibis::INT: {
00506 const array_t<const int32_t>* vals =
00507 static_cast<const array_t<const int32_t>*>(buffer[j].cval);
00508 out << (*vals)[i];
00509 break;}
00510 case ibis::UINT: {
00511 const array_t<const uint32_t>* vals =
00512 static_cast<const array_t<const uint32_t>*>(buffer[j].cval);
00513 out << (*vals)[i];
00514 break;}
00515 case ibis::LONG: {
00516 const array_t<const int64_t>* vals =
00517 static_cast<const array_t<const int64_t>*>(buffer[j].cval);
00518 out << (*vals)[i];
00519 break;}
00520 case ibis::ULONG: {
00521 const array_t<const uint64_t>* vals =
00522 static_cast<const array_t<const uint64_t>*>(buffer[j].cval);
00523 out << (*vals)[i];
00524 break;}
00525 case ibis::FLOAT: {
00526 const array_t<const float>* vals =
00527 static_cast<const array_t<const float>*>(buffer[j].cval);
00528 out << (*vals)[i];
00529 break;}
00530 case ibis::DOUBLE: {
00531 const array_t<const double>* vals =
00532 static_cast<const array_t<const double>*>(buffer[j].cval);
00533 out << (*vals)[i];
00534 break;}
00535 case ibis::TEXT:
00536 case ibis::CATEGORY: {
00537 const std::vector<std::string>* vals =
00538 static_cast<const std::vector<std::string>*>(buffer[j].cval);
00539 out << '"' << (*vals)[i] << '"';
00540 break;}
00541 default: {
00542 return -2;}
00543 }
00544 return 0;
00545 }
00546
00547 inline int
00548 ibis::bord::cursor::getColumnAsByte(const char* cn, char& val) const {
00549 if (curRow < 0 || curRow >= (int64_t) tab.nRows() || cn == 0 || *cn == 0)
00550 return -1;
00551 bufferMap::const_iterator it = bufmap.find(cn);
00552 if (it != bufmap.end())
00553 return getColumnAsByte((*it).second, val);
00554 else
00555 return -2;
00556 }
00557
00558 inline int
00559 ibis::bord::cursor::getColumnAsUByte(const char* cn,
00560 unsigned char& val) const {
00561 if (curRow < 0 || curRow >= (int64_t) tab.nRows() || cn == 0 || *cn == 0)
00562 return -1;
00563 bufferMap::const_iterator it = bufmap.find(cn);
00564 if (it != bufmap.end())
00565 return getColumnAsUByte((*it).second, val);
00566 else
00567 return -2;
00568 }
00569
00570 inline int
00571 ibis::bord::cursor::getColumnAsShort(const char* cn, int16_t& val) const {
00572 if (curRow < 0 || curRow >= (int64_t) tab.nRows() || cn == 0 || *cn == 0)
00573 return -1;
00574 bufferMap::const_iterator it = bufmap.find(cn);
00575 if (it != bufmap.end())
00576 return getColumnAsShort((*it).second, val);
00577 else
00578 return -2;
00579 }
00580
00581 inline int
00582 ibis::bord::cursor::getColumnAsUShort(const char* cn, uint16_t& val) const {
00583 if (curRow < 0 || curRow >= (int64_t) tab.nRows() || cn == 0 || *cn == 0)
00584 return -1;
00585 bufferMap::const_iterator it = bufmap.find(cn);
00586 if (it != bufmap.end())
00587 return getColumnAsUShort((*it).second, val);
00588 else
00589 return -2;
00590 }
00591
00592 inline int
00593 ibis::bord::cursor::getColumnAsInt(const char* cn, int32_t& val) const {
00594 if (curRow < 0 || curRow >= (int64_t) tab.nRows() || cn == 0 || *cn == 0)
00595 return -1;
00596 bufferMap::const_iterator it = bufmap.find(cn);
00597 if (it != bufmap.end())
00598 return getColumnAsInt((*it).second, val);
00599 else
00600 return -2;
00601 }
00602
00603 inline int
00604 ibis::bord::cursor::getColumnAsUInt(const char* cn, uint32_t& val) const {
00605 if (curRow < 0 || curRow >= (int64_t) tab.nRows() || cn == 0 || *cn == 0)
00606 return -1;
00607 bufferMap::const_iterator it = bufmap.find(cn);
00608 if (it != bufmap.end())
00609 return getColumnAsUInt((*it).second, val);
00610 else
00611 return -2;
00612 }
00613
00614 inline int
00615 ibis::bord::cursor::getColumnAsLong(const char* cn, int64_t& val) const {
00616 if (curRow < 0 || curRow >= (int64_t) tab.nRows() || cn == 0 || *cn == 0)
00617 return -1;
00618 bufferMap::const_iterator it = bufmap.find(cn);
00619 if (it != bufmap.end())
00620 return getColumnAsLong((*it).second, val);
00621 else
00622 return -2;
00623 }
00624
00625 inline int
00626 ibis::bord::cursor::getColumnAsULong(const char* cn, uint64_t& val) const {
00627 if (curRow < 0 || curRow >= (int64_t) tab.nRows() || cn == 0 || *cn == 0)
00628 return -1;
00629 bufferMap::const_iterator it = bufmap.find(cn);
00630 if (it != bufmap.end())
00631 return getColumnAsULong((*it).second, val);
00632 else
00633 return -2;
00634 }
00635
00636 inline int
00637 ibis::bord::cursor::getColumnAsFloat(const char* cn, float& val) const {
00638 if (curRow < 0 || curRow >= (int64_t) tab.nRows() || cn == 0 || *cn == 0)
00639 return -1;
00640 bufferMap::const_iterator it = bufmap.find(cn);
00641 if (it != bufmap.end())
00642 return getColumnAsFloat((*it).second, val);
00643 else
00644 return -2;
00645 }
00646
00647 inline int
00648 ibis::bord::cursor::getColumnAsDouble(const char* cn, double& val) const {
00649 if (curRow < 0 || curRow >= (int64_t) tab.nRows() || cn == 0 || *cn == 0)
00650 return -1;
00651 bufferMap::const_iterator it = bufmap.find(cn);
00652 if (it != bufmap.end())
00653 return getColumnAsDouble((*it).second, val);
00654 else
00655 return -2;
00656 }
00657
00658 inline int
00659 ibis::bord::cursor::getColumnAsString(const char* cn,
00660 std::string& val) const {
00661 if (curRow < 0 || curRow >= (int64_t) tab.nRows() || cn == 0 || *cn == 0)
00662 return -1;
00663 bufferMap::const_iterator it = bufmap.find(cn);
00664 if (it != bufmap.end())
00665 return getColumnAsString((*it).second, val);
00666 else
00667 return -2;
00668 }
00669 #endif // IBIS_BORD_H