diff options
Diffstat (limited to 'raslib')
107 files changed, 21226 insertions, 0 deletions
diff --git a/raslib/Makefile.am b/raslib/Makefile.am new file mode 100644 index 0000000..6760b08 --- /dev/null +++ b/raslib/Makefile.am @@ -0,0 +1,54 @@ +# -*-Makefile-*- (for Emacs) +# +# This file is part of rasdaman community. +# +# Rasdaman community is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Rasdaman community 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +# +# Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +# rasdaman GmbH. +# +# For more information please see <http://www.rasdaman.org> +# or contact Peter Baumann via <baumann@rasdaman.com>. +# +# MAKEFILE FOR: +# module raslib +# +# COMMENTS: +# +################################################################## + +AM_CXXFLAGS=@CLIENTCXXFLAGS@ +AM_LDFLAGS=@CLIENTLDFLAGS@ + +noinst_LIBRARIES=libraslib.a +libraslib_a_SOURCES= sinterval.hh dlist.hh point.hh minterval.hh error.hh \ + rmdebug.hh rminit.hh metaobject.hh type.hh marraytype.hh \ + basetype.hh primitivetype.hh sintervaltype.hh \ + collectiontype.hh property.hh attribute.hh mintervaltype.hh \ + pointtype.hh oidtype.hh structuretype.hh itertype.hh \ + oid.hh scalar.hh primitive.hh structure.hh miter.hh mddtypes.hh \ + miterd.hh mitera.hh memblockvec.hh parseparams.hh storageman.hh \ + endian.hh flatbasetype.hh complex.hh complextype.hh shhopt.h \ + sinterval.cc dlist.cc point.cc minterval.cc error.cc \ + rmdebug.cc rminit.cc metaobject.cc type.cc marraytype.cc \ + basetype.cc primitivetype.cc sintervaltype.cc \ + collectiontype.cc property.cc attribute.cc mintervaltype.cc \ + pointtype.cc oidtype.cc structuretype.cc itertype.cc \ + oid.cc scalar.cc primitive.cc structure.cc miter.cc mddtypes.cc \ + miterd.cc mitera.cc memblockvec.cc parseparams.cc storageman.cc \ + endian.cc flatbasetype.cc complex.cc complextype.cc shhopt.c \ + complex.icc complextype.icc error.icc minterval.icc miterd.icc miterf.icc \ + miter.icc oid.icc point.icc rmdebug.icc sinterval.icc \ + rmdebug.hh rm.hh odmgtypes.hh miterf.hh template_inst.hh + diff --git a/raslib/attribute.cc b/raslib/attribute.cc new file mode 100644 index 0000000..6456810 --- /dev/null +++ b/raslib/attribute.cc @@ -0,0 +1,257 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +static const char rcsid[] = "@(#) raslib, r_Attribute: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/attribute.cc,v 1.11 2003/12/27 23:01:21 rasdev Exp $"; + +#include "raslib/attribute.hh" +#include "raslib/basetype.hh" +#include "raslib/structuretype.hh" +#include "raslib/rminit.hh" +#include "raslib/error.hh" + +r_Attribute::r_Attribute() + : r_Property(), + localOffset(0), + globalOffset(0) + { + } + +r_Attribute::r_Attribute(const char* newTypeName, const r_Base_Type& newType) + : r_Property(newTypeName, newType), + localOffset(0), + globalOffset(0) + { + } + +r_Attribute::r_Attribute(const r_Attribute& oldObj) + : r_Property(oldObj) , + localOffset(oldObj.localOffset), + globalOffset(oldObj.globalOffset) + { + } + +const r_Attribute& +r_Attribute::operator=(const r_Attribute& oldObj) + { + // Gracefully handle self assignment + if (this != &oldObj) + { + r_Property::operator=(oldObj) ; + localOffset = oldObj.localOffset; + globalOffset = oldObj.globalOffset; + } + + return *this; + } + +r_Attribute::~r_Attribute() + { + } + +r_Bytes +r_Attribute::offset() const + { + return localOffset; + } + +void +r_Attribute::set_offset(r_Bytes newOffset) + { + localOffset = newOffset; + } + +r_Bytes +r_Attribute::global_offset() const + { + return globalOffset; + } + +void +r_Attribute::set_global_offset(r_Bytes newOffset) + { + globalOffset = newOffset; + } + +void +r_Attribute::print_status(std::ostream& s) const + { + type_of().print_status(s); + s << " " << name() << std::flush; + } + + + +r_Attribute +r_Attribute::operator[](unsigned int number) const throw(r_Error) + { + if (type_of().type_id() != r_Type::STRUCTURETYPE) + { + RMInit::logOut << "r_Attribute::operator[](" << number << ") not a struct type" << endl; + throw r_Error(r_Error::r_Error_TypeInvalid) ; + } + + const r_Structure_Type& structValue = (const r_Structure_Type&)type_of(); + + return structValue[number]; + } + + + +r_Boolean +r_Attribute::get_boolean(const char* cell) const throw(r_Error) + { + if (type_of().type_id() != r_Type::BOOL) + { + RMInit::logOut << "r_Attribute::get_boolean(data) not a boolean" << endl; + r_Error err(r_Error::r_Error_TypeInvalid) ; + throw(err) ; + } + + return *((r_Boolean*) (cell+globalOffset) ) ; + } + + + +r_Char +r_Attribute::get_char(const char* cell) const throw(r_Error) + { + if (type_of() .type_id() != r_Type::CHAR) + { + RMInit::logOut << "r_Attribute::get_char(data) not a char" << endl; + r_Error err(r_Error::r_Error_TypeInvalid) ; + throw(err) ; + } + + return *((r_Char*) (cell+globalOffset) ) ; + } + + + +r_Octet +r_Attribute::get_octet(const char* cell) const throw(r_Error) + { + if (type_of() .type_id() != r_Type::OCTET) + { + RMInit::logOut << "r_Attribute::get_octet(data) not a octet" << endl; + r_Error err(r_Error::r_Error_TypeInvalid) ; + throw(err) ; + } + + return *((r_Octet*) (cell+globalOffset) ) ; + } + + + +r_Short +r_Attribute::get_short(const char* cell) const throw(r_Error) + { + if (type_of() .type_id() != r_Type::SHORT) + { + RMInit::logOut << "r_Attribute::get_short(data) not a short" << endl; + r_Error err(r_Error::r_Error_TypeInvalid) ; + throw(err) ; + } + + return *((r_Short*) (cell+globalOffset) ) ; + } + + + +r_UShort +r_Attribute::get_ushort(const char* cell) const throw(r_Error) + { + if (type_of() .type_id() != r_Type::USHORT) + { + RMInit::logOut << "r_Attribute::get_ushort(data) not a ushort" << endl; + r_Error err(r_Error::r_Error_TypeInvalid) ; + throw(err) ; + } + + return *((r_UShort*) (cell+globalOffset) ) ; + } + + + +r_Long +r_Attribute::get_long(const char* cell) const throw(r_Error) + { + if (type_of() .type_id() != r_Type::LONG) + { + RMInit::logOut << "r_Attribute::get_long(data) not a long" << endl; + r_Error err(r_Error::r_Error_TypeInvalid) ; + throw(err) ; + } + + return *((r_Long*) (cell+globalOffset) ) ; + } + + + +r_ULong +r_Attribute::get_ulong(const char* cell) const throw(r_Error) + { + if (type_of() .type_id() != r_Type::ULONG) + { + RMInit::logOut << "r_Attribute::get_ulong(data) not a ulong" << endl; + r_Error err(r_Error::r_Error_TypeInvalid) ; + throw(err) ; + } + + return *((r_ULong*) (cell+globalOffset) ) ; + } + + + +r_Float +r_Attribute::get_float(const char* cell) const throw(r_Error) + { + if (type_of() .type_id() != r_Type::FLOAT) + { + RMInit::logOut << "r_Attribute::get_float(data) not a float" << endl; + r_Error err(r_Error::r_Error_TypeInvalid) ; + throw(err) ; + } + + return *((r_Float*) (cell+globalOffset) ) ; + } + + + +r_Double +r_Attribute::get_double(const char* cell) const throw(r_Error) + { + if (type_of() .type_id() != r_Type::DOUBLE) + { + RMInit::logOut << "r_Attribute::get_double(data) not a double" << endl; + r_Error err(r_Error::r_Error_TypeInvalid) ; + throw(err) ; + } + + return *((r_Double*) (cell+globalOffset) ) ; + } + +std::ostream &operator<<( std::ostream &str, const r_Attribute &type ) +{ + type.print_status(str); + return str; +} diff --git a/raslib/attribute.hh b/raslib/attribute.hh new file mode 100644 index 0000000..1bfed1c --- /dev/null +++ b/raslib/attribute.hh @@ -0,0 +1,134 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: attribute.hh + * + * MODULE: raslib + * CLASS: r_Attribute + * + * COMMENTS: + * None +*/ + +#ifndef _D_ATTRIBUTE_ +#define _D_ATTRIBUTE_ + +#include "raslib/property.hh" +#include "raslib/odmgtypes.hh" +#include "raslib/mddtypes.hh" + +class r_Base_Type; +class r_Type_Id; +class r_Error; + + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + This class represents attributes of structs in the ODMG + conformant representation of the RasDaMan type system. +*/ + + +class r_Attribute : public r_Property + { + public: + /// default constructor. + /// initialise important attributes to NULL + r_Attribute(); + + /// constructor getting name and type of attribute. + r_Attribute(const char* newTypeName, const r_Base_Type& newType); + + /// copy constructor. + r_Attribute(const r_Attribute& oldObj); + + /// assignment operator. + const r_Attribute& operator=(const r_Attribute& oldObj); + + /// destructor. + virtual ~r_Attribute(); + + /// retrieve (local) offset + r_Bytes offset() const; + + /// set (local) offset + void set_offset(r_Bytes newOffset); + + /// retrieve global offset + r_Bytes global_offset() const; + + /// set global offset + void set_global_offset(r_Bytes newOffset); + + /// writes state of object to specified stream + virtual void print_status(std::ostream& s = std::cout) const; + + /// subscript operator to access attributes of a structured attribute + /// throws error when type is not a struct type + r_Attribute operator[](unsigned int number) const throw(r_Error); + + //@Man: Type-safe value access methods. In case of type mismatch, an exception is raised. + //@{ + /// + r_Boolean get_boolean(const char* cell) const throw(r_Error); + + /// + r_Char get_char(const char* cell) const throw(r_Error); + + /// + r_Octet get_octet(const char* cell) const throw(r_Error); + + /// + r_Short get_short(const char* cell) const throw(r_Error); + + /// + r_UShort get_ushort(const char* cell) const throw(r_Error); + + /// + r_Long get_long(const char* cell) const throw(r_Error); + + /// + r_ULong get_ulong(const char* cell) const throw(r_Error); + + /// + r_Float get_float(const char* cell) const throw(r_Error); + + /// + r_Double get_double(const char* cell) const throw(r_Error); + + /// + //@} + + protected: + /// local offset + r_Bytes localOffset; + + /// global offset + r_Bytes globalOffset; + }; + +//@Doc: write the status of a attribute to a stream +extern std::ostream &operator<<( std::ostream &str, const r_Attribute &type ); + +#endif diff --git a/raslib/basetype.cc b/raslib/basetype.cc new file mode 100644 index 0000000..639073f --- /dev/null +++ b/raslib/basetype.cc @@ -0,0 +1,77 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +static const char rcsid[] = "@(#)raslib, r_Type: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/basetype.cc,v 1.4 2003/12/27 23:01:21 rasdev Exp $"; + +#include <ctype.h> // for isalpha() +#include <string.h> // for strncmp() + +#include "raslib/basetype.hh" +#include "raslib/attribute.hh" + +r_Base_Type::r_Base_Type() + : r_Type(), + typeSize(0) + { + } + +r_Base_Type::r_Base_Type(const char* newTypeName, r_Bytes newTypeSize) + : r_Type(newTypeName), + typeSize(newTypeSize) + { + } + +r_Base_Type::r_Base_Type(const r_Base_Type& oldObj) + : r_Type(oldObj), + typeSize(oldObj.typeSize) + { + } + +const r_Base_Type& +r_Base_Type::operator=(const r_Base_Type& oldObj) + { + // Gracefully handle self assignment + if (this == &oldObj) return *this; + + r_Type::operator=(oldObj); + typeSize = oldObj.typeSize; + + return *this; + } + +r_Base_Type::~r_Base_Type() + { + } + +bool +r_Base_Type::isBaseType() const + { + return true; + } + +r_Bytes +r_Base_Type::size() const + { + return typeSize; + } + diff --git a/raslib/basetype.hh b/raslib/basetype.hh new file mode 100644 index 0000000..45e7446 --- /dev/null +++ b/raslib/basetype.hh @@ -0,0 +1,80 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: basetype.hh + * + * MODULE: raslib + * CLASS: r_Base_Type + * + * COMMENTS: + * None +*/ + +#ifndef _D_BASETYPE_ +#define _D_BASETYPE_ + +#include "raslib/type.hh" + + + +//@ManMemo: Module: {\bf raslib} + +/** + This class is the superclass of the types r_Structure_Type and r_Primitive_Type in the + representation of the RasDaMan type system. +*/ + +class r_Base_Type : public r_Type + { + public: + /// default constructor. + r_Base_Type(); + + /// constructor getting name of basetype. + r_Base_Type(const char* newTypeName, r_Bytes newSize); + + /// copy constructor + r_Base_Type(const r_Base_Type& oldObj); + + /// assignment operator. + const r_Base_Type& operator=(const r_Base_Type& oldObj); + + /// destructor. + virtual ~r_Base_Type(); + + /// check, if type is a base type (primitive type or structure type). + virtual bool isBaseType() const; + + /// retrieve size of the type. + r_Bytes size() const; + + /// prints value of a primitive type or values of a structured type + virtual void print_value(const char* storage, std::ostream& s = std::cout) const = 0; + + protected: + /// storing size of type in bytes + r_Bytes typeSize; + + }; + +#endif diff --git a/raslib/collectiontype.cc b/raslib/collectiontype.cc new file mode 100644 index 0000000..035e201 --- /dev/null +++ b/raslib/collectiontype.cc @@ -0,0 +1,140 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +static const char rcsid[] = "@(#)raslib, r_Collection_Type: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/collectiontype.cc,v 1.6 2003/12/27 23:01:21 rasdev Exp $"; + +#include "raslib/collectiontype.hh" +#include "raslib/rminit.hh" +#include "raslib/error.hh" + + +r_Collection_Type::r_Collection_Type() + : r_Type(), + elementType(NULL) + { + } + +r_Collection_Type::r_Collection_Type(r_Type& newElementType) + : r_Type(), + elementType(newElementType.clone()) + { + } + +r_Collection_Type::r_Collection_Type(const r_Collection_Type& oldObj) throw (r_Error) + : r_Type(oldObj), + elementType(NULL) + { + if (oldObj.elementType) + elementType = oldObj.elementType->clone(); + else { + RMInit::logOut << "r_Collection_Type::r_Collection_Type( oldObj ) the element type is NULL." << endl; + throw r_Error(COLLECTIONTYPEHASNOELEMENTTYPE); + } + } + +bool +r_Collection_Type::isCollectionType() const + { + return true; + } + +const r_Collection_Type& +r_Collection_Type::operator=(const r_Collection_Type& oldObj) throw (r_Error) + { + // Gracefully handle self assignment + if (this == &oldObj) + return *this; + + r_Type::operator=(oldObj); + delete elementType; + elementType = NULL; + if (oldObj.elementType) + elementType = oldObj.elementType->clone(); + else { + RMInit::logOut << "r_Collection_Type::operator=( oldObj ) the element type is NULL." << endl; + throw r_Error(COLLECTIONTYPEHASNOELEMENTTYPE); + } + return *this; + } + +const r_Type& +r_Collection_Type::element_type() const throw (r_Error) + { + if (elementType == NULL) + { + RMInit::logOut << "r_Collection_Type::element_type() the element type is NULL." << endl; + throw r_Error(COLLECTIONTYPEHASNOELEMENTTYPE); + } + return *elementType; + } + +r_Type* +r_Collection_Type::clone() const + { + return new r_Collection_Type(*this); + } + +r_Collection_Type::r_Kind +r_Collection_Type::kind() const + { + return SET; + } + +r_Type::r_Type_Id +r_Collection_Type::type_id() const + { + return COLLECTIONTYPE; + } + +void +r_Collection_Type::convertToLittleEndian(char* cells, r_Area noCells) const + { + } + +void +r_Collection_Type::convertToBigEndian(char* cells, r_Area noCells) const + { + } + +void +r_Collection_Type::print_status(std::ostream& s) const + { + s << "set< "; + elementType->print_status(s); + s << " >"; + } + + + +r_Collection_Type::~r_Collection_Type() + { + if (elementType) + delete elementType; + elementType = NULL; + } + +std::ostream &operator<<( std::ostream &str, const r_Collection_Type &type ) +{ + type.print_status(str); + return str; +} diff --git a/raslib/collectiontype.hh b/raslib/collectiontype.hh new file mode 100644 index 0000000..9e33106 --- /dev/null +++ b/raslib/collectiontype.hh @@ -0,0 +1,108 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: collectiontype.hh + * + * MODULE: raslib + * CLASS: r_Collection_Type + * + * COMMENTS: + * None +*/ + +#ifndef _D_COLLECTION_TYPE_ +#define _D_COLLECTION_TYPE_ + +#include "raslib/type.hh" +class r_Error; + + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + This class represents the collection type in the ODMG conformant + representation of the RasDaMan type system. +*/ + + +class r_Collection_Type : public r_Type + { + public: + /// Set type in the only one needed right now. + typedef enum { SET } r_Kind; + + /// copy constructor + /// the exception is only raised when the element type of the copied type is NULL. + /// (this can not happen) + r_Collection_Type(const r_Collection_Type&) throw (r_Error); + + /// constructor getting element type + r_Collection_Type(r_Type& newType); + + /// returns identifier SET of enumeration r_Kind + r_Kind kind() const; + + /// assignment operator + /// the exception is only raised when the element type of the copied type is NULL. + /// (this can not happen) + const r_Collection_Type& operator=(const r_Collection_Type& oldObj) throw (r_Error); + + /// get element type + /// the exception is only raised when the element type of the copied type is NULL. + /// (this can not happen) + const r_Type& element_type() const throw (r_Error); + + /// clone operation + virtual r_Type* clone() const; + + /// retrieve id of the type. + virtual r_Type::r_Type_Id type_id() const; + + virtual bool isCollectionType() const; + + /// converts array of cells from NT byte order to Unix byte order. + virtual void convertToLittleEndian(char* cells, r_Area noCells) const; + + /// converts array of cells from Unix byte order to NT byte order. + virtual void convertToBigEndian(char* cells, r_Area noCells) const; + + /// writes state of object to specified stream + virtual void print_status(std::ostream& s = std::cout) const; + + /// destructor + ~r_Collection_Type(); + + protected: + /// default constructor + /// no one should use that + r_Collection_Type(); + + /// element type + r_Type* elementType; + }; + +//@Doc: write the status of a collection type to a stream +extern std::ostream &operator<<( std::ostream &str, const r_Collection_Type &type ); + +#endif + diff --git a/raslib/complex.cc b/raslib/complex.cc new file mode 100644 index 0000000..9b8ed2e --- /dev/null +++ b/raslib/complex.cc @@ -0,0 +1,110 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +#include "raslib/complex.hh" +#include "raslib/rminit.hh" +#include "raslib/error.hh" +#include "raslib/complextype.hh" + +r_Complex::r_Complex(const char* newBuffer, const r_Complex_Type* newType) + : r_Primitive(newBuffer, newType) + { + } + +r_Complex::r_Complex(const r_Complex& obj) + : r_Primitive(obj) + { + } + +r_Complex::~r_Complex() + { + } + +r_Scalar* +r_Complex::clone() const + { + return new r_Complex(*this); + } + +const r_Complex& +r_Complex::operator=(const r_Complex& obj) + { + r_Primitive::operator=(obj); + return *this; + } + +r_Double +r_Complex::get_re() const throw (r_Error) + { + if (!get_buffer() || !valueType || !valueType->isComplexType()) + { + RMInit::logOut << "r_Complex::get_re() value type is not a complex, not initialised or not buffered" << endl; + r_Error err(r_Error::r_Error_TypeInvalid); + throw err; + } + return ((r_Complex_Type *)valueType)->get_re(get_buffer()); + } + +r_Double +r_Complex::get_im() const throw (r_Error) + { + if(!get_buffer() || !valueType || !valueType->isComplexType()) + { + RMInit::logOut << "r_Complex::get_im() value type is not a complex, not initialised or not buffered" << endl; + r_Error err(r_Error::r_Error_TypeInvalid); + throw err; + } + return ((r_Complex_Type *)valueType)->get_im(get_buffer()); + } + +void +r_Complex::set_re(r_Double re) throw (r_Error) + { + if (!valueType || !valueType->isComplexType()) + { + RMInit::logOut << "r_Complex::set_re(" << re << ") value type is not a complex or not initialised" << endl; + r_Error err(r_Error::r_Error_TypeInvalid); + throw err; + } + ((r_Complex_Type *)valueType)->set_re((char*)get_buffer(), re); + } + +void +r_Complex::set_im(r_Double im) throw (r_Error) + { + if(!valueType || !valueType->isComplexType()) + { + RMInit::logOut << "r_Complex::get_im() value type is not a complex or not initialised" << endl; + r_Error err(r_Error::r_Error_TypeInvalid); + throw err; + } + ((r_Complex_Type *)valueType)->set_im((char*)get_buffer(), im); + } + + +bool +r_Complex::isComplex() const + { + return true; + } + diff --git a/raslib/complex.hh b/raslib/complex.hh new file mode 100644 index 0000000..c67da82 --- /dev/null +++ b/raslib/complex.hh @@ -0,0 +1,87 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: complex.hh + * + * MODULE: raslib + * CLASS: r_Complex + * + * COMMENTS: + * The class represents a complex type value. + * +*/ + +#ifndef _D_COMPLEX_ +#define _D_COMPLEX_ + +#include <iostream> +class r_Error; +class r_Complex_Type; + +#include "raslib/odmgtypes.hh" +#include "raslib/mddtypes.hh" +#include "raslib/primitive.hh" + + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + Class \Ref{r_Complex} represents a complex type value. + +*/ + + +class r_Complex: public r_Primitive + { + public: + + explicit + /// constructs a scalar type value + r_Complex(const char* newBuffer, const r_Complex_Type* newType); + + /// copy constructor + r_Complex(const r_Complex& obj); + + /// destructor + ~r_Complex(); + + virtual bool isComplex() const; + + /// clone operator + virtual r_Scalar* clone() const; + + /// operator for assigning a primitive + virtual const r_Complex& operator =(const r_Complex&); + + r_Double get_re() const throw(r_Error); + r_Double get_im() const throw(r_Error); + + void set_re(r_Double) throw(r_Error); + void set_im(r_Double) throw(r_Error); + + }; + + +#endif + diff --git a/raslib/complex.icc b/raslib/complex.icc new file mode 100644 index 0000000..bab562e --- /dev/null +++ b/raslib/complex.icc @@ -0,0 +1 @@ +//this is moved to complex.cc diff --git a/raslib/complextype.cc b/raslib/complextype.cc new file mode 100644 index 0000000..e2b59b3 --- /dev/null +++ b/raslib/complextype.cc @@ -0,0 +1,284 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +#include <iomanip> +#include <string> +#include <cstring> + +#include "raslib/complextype.hh" +#include "raslib/endian.hh" +#include "raslib/rmdebug.hh" +#include "raslib/error.hh" + +r_Complex_Type::r_Complex_Type() + : r_Primitive_Type(), + imOff(0) + { + } + +r_Complex_Type::r_Complex_Type(const char* newTypeName, const r_Type::r_Type_Id newTypeId) + : r_Primitive_Type(newTypeName, newTypeId) + { + imOff = 0; + switch (typeId) + { + case COMPLEXTYPE1: + imOff = sizeof(r_Float); + break; + case COMPLEXTYPE2: + imOff = sizeof(r_Double); + break; + default: + RMDBGONCE(3, RMDebug::module_raslib, "r_Complex_Type", "r_Complex_Type(...) bad typeId " << typeId); + break; + } + } + +r_Complex_Type::~r_Complex_Type() + { + } + +r_Complex_Type::r_Complex_Type(const r_Complex_Type& oldObj) + : r_Primitive_Type(oldObj), + imOff(oldObj.imOff) + { + } + +const r_Complex_Type& +r_Complex_Type::operator=(const r_Complex_Type& oldObj) + { + if (this == &oldObj) + return *this; + + r_Primitive_Type::operator =(oldObj); + imOff = oldObj.imOff; + return *this; + } + +r_Type* +r_Complex_Type::clone() const + { + return new r_Complex_Type(*this); + } + +r_Double + r_Complex_Type::get_re(const char* cell) const throw(r_Error) + { + double res = 0; + + if( (typeId != r_Type::COMPLEXTYPE1) && + (typeId != r_Type::COMPLEXTYPE2) ) + { + RMInit::logOut << "r_Complex_Type::get_re(cell) type not a complex1 or complex2" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + + switch (typeId) + { + case COMPLEXTYPE1: + res = *(r_Float*)cell; + break; + case COMPLEXTYPE2: + res = *(r_Double *)cell; + break; + default: + RMDBGONCE(3, RMDebug::module_raslib, "r_Complex_Type", "get_re(...) bad typeId " << typeId); + break; + } + return res; + } + +r_Double +r_Complex_Type::get_im(const char* cell) const throw(r_Error) + { + double res = 0; + + if( (typeId != r_Type::COMPLEXTYPE1) && + (typeId != r_Type::COMPLEXTYPE2) ) + { + RMInit::logOut << "r_Complex_Type::get_im(cell) type not a complex1 or complex2" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + switch (typeId) + { + case COMPLEXTYPE1: + res = *(r_Float*)(cell + imOff); + break; + case COMPLEXTYPE2: + res = *(r_Double*)(cell + imOff); + break; + default: + RMDBGONCE(3, RMDebug::module_raslib, "r_Complex_Type", "get_im(...) bad typeId " << typeId); + break; + } + return res; + } + + + + +void +r_Complex_Type::set_re(char* cell, r_Double re) throw(r_Error) + { + r_Float ref=0.; + if( (typeId != r_Type::COMPLEXTYPE1) && + (typeId != r_Type::COMPLEXTYPE2) ) + { + RMInit::logOut << "r_Complex_Type::set_re(cell, re) type not a complex1 or complex2" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + switch (typeId) + { + case COMPLEXTYPE1: + ref=re; + memmove(cell, &ref, imOff); + break; + case COMPLEXTYPE2: + memmove(cell, &re, imOff); + break; + default: + RMDBGONCE(3, RMDebug::module_raslib, "r_Complex_Type", "set_re(...) bad typeId " << typeId); + break; + } + } + +void +r_Complex_Type::set_im(char* cell, r_Double im) throw(r_Error) + { + r_Float imf= 0.; + + if( (typeId != r_Type::COMPLEXTYPE1) && + (typeId != r_Type::COMPLEXTYPE2) ) + { + RMInit::logOut << "r_Complex_Type::set_im(cell, im) type not a complex1 or complex2" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + switch (typeId) + { + case COMPLEXTYPE1: + imf=im; + memmove((cell + imOff), &imf, imOff); + break; + case COMPLEXTYPE2: + memmove((cell + imOff), &im, imOff); + break; + default: + RMDBGONCE(3, RMDebug::module_raslib, "r_Complex_Type", "set_im(...) bad typeId " << typeId); + break; + } + } + + +void +r_Complex_Type::print_status(std::ostream& s) const + { + switch (typeId) + { + case COMPLEXTYPE1: + s << "complex(float, float)"; + break; + case COMPLEXTYPE2: + s << "complex(double, double)"; + break; + default: + RMDBGONCE(3, RMDebug::module_raslib, "r_Complex_Type", "print_status(...) bad typeId " << typeId); + break; + } + } + +void +r_Complex_Type::print_value(const char* storage, std::ostream& s) const + { + s << "(" << get_re(storage) << ", " << get_im(storage) << ")"; + } + +void +r_Complex_Type::convertToLittleEndian(char* cells, r_Area noCells) const + { + switch (typeId) + { + case COMPLEXTYPE1: + for (r_Area i = 0; i < noCells; ++i) + { + *(r_Float*)(cells + i * typeSize) = r_Endian::swap((r_Float)get_re(cells + i * typeSize)); + *(r_Float*)(cells + i * typeSize + imOff) = r_Endian::swap((r_Float)get_im(cells + i * typeSize)); + } + break; + + case COMPLEXTYPE2: + for (r_Area i = 0; i < noCells; ++i) + { + *(r_Double*)(cells + i * typeSize) = r_Endian::swap(get_re(cells + i * typeSize)); + *(r_Double*)(cells + i * typeSize + imOff) = r_Endian::swap(get_im(cells + i * typeSize)); + } + break; + default: + RMDBGONCE(3, RMDebug::module_raslib, "r_Complex_Type", "convertToLittleEndian(...) bad typeId " << typeId); + break; + } + } + +void +r_Complex_Type::convertToBigEndian(char* cells, r_Area noCells) const + { + switch (typeId) + { + case COMPLEXTYPE1: + for (r_Area i = 0; i < noCells; ++i) + { + *(r_Float*)(cells + i * typeSize) = r_Endian::swap((r_Float)get_re(cells + i * typeSize)); + *(r_Float*)(cells + i * typeSize + imOff) = r_Endian::swap((r_Float)get_im(cells + i * typeSize)); + } + break; + case COMPLEXTYPE2: + for (r_Area i = 0; i < noCells; ++i) + { + *(r_Double*)(cells + i * typeSize) = r_Endian::swap(get_re(cells + i * typeSize)); + *(r_Double*)(cells + i * typeSize + imOff) = r_Endian::swap(get_im(cells + i * typeSize)); + } + break; + default: + RMDBGONCE(3, RMDebug::module_raslib, "r_Complex_Type", "convertToBigEndian(...) bad typeId " << typeId); + break; + } + } + +bool +r_Complex_Type::isComplexType() const + { + return true; + } + +std::ostream &operator<<( std::ostream &str, const r_Complex_Type &type ) +{ + type.print_status(str); + return str; +} diff --git a/raslib/complextype.hh b/raslib/complextype.hh new file mode 100644 index 0000000..a496384 --- /dev/null +++ b/raslib/complextype.hh @@ -0,0 +1,71 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: complextype.hh + * + * MODULE: raslib + * CLASS: r_Complex_Type + * + * COMMENTS: + * None +*/ + +#ifndef _D_COMPLEXTYPE_TYPE_ +#define _D_COMPLEXTYPE_TYPE_ + +#include "raslib/primitivetype.hh" +#include "raslib/odmgtypes.hh" +#include "raslib/mddtypes.hh" + +class r_Complex_Type : public r_Primitive_Type + { + public: + r_Complex_Type(); + r_Complex_Type(const char* newTypeName, const r_Type::r_Type_Id newTypeId); + r_Complex_Type(const r_Complex_Type& oldObj); + const r_Complex_Type& operator=(const r_Complex_Type& oldObj); + virtual ~r_Complex_Type(); + + virtual r_Type* clone() const; + virtual void print_status(std::ostream& s = std::cout) const; + virtual void print_value(const char* storage, std::ostream& s = std::cout) const; + + r_Double get_re(const char* cell) const throw(r_Error); + r_Double get_im(const char* cell) const throw(r_Error); + + void set_re(char* cell, r_Double re) throw(r_Error); + void set_im(char* cell, r_Double im) throw(r_Error); + + + virtual void convertToLittleEndian(char* cells, r_Area noCells) const; + virtual void convertToBigEndian(char* cells, r_Area noCells) const; + virtual bool isComplexType() const; + + private: + r_Bytes imOff; + }; + +//@Doc: write the status of a complex type to a stream +extern std::ostream &operator<<( std::ostream &str, const r_Complex_Type &type ); + +#endif diff --git a/raslib/complextype.icc b/raslib/complextype.icc new file mode 100644 index 0000000..9bbb3dd --- /dev/null +++ b/raslib/complextype.icc @@ -0,0 +1 @@ +//this is moved to complextype.cc diff --git a/raslib/dlist.cc b/raslib/dlist.cc new file mode 100644 index 0000000..9641580 --- /dev/null +++ b/raslib/dlist.cc @@ -0,0 +1,71 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +#include <iostream> +#include <vector> +#include "raslib/dlist.hh" +#include "raslib/minterval.hh" + +template <class T> +std::ostream& operator<< (std::ostream& os, const std::vector<T>& list) +{ + os << "[ "; + for (typename std::vector<T>::const_iterator it = list.begin(); it != list.end(); it++) + os << (*it) << " "; + os << "]"; + return os; +} + +template <class T> +std::ostream& operator<< (const std::vector<T>& list, std::ostream& os) +{ + os << "[ "; + for (typename std::vector<T>::const_iterator it = list.begin(); it != list.end(); it++) + os << (*it) << " "; + os << "]"; + return os; +} + +#if defined(SOLARIS) && ! defined(EARLY_TEMPLATE) +//this is here to get around a template instantiation problem on sun +template <> +std::ostream& operator<< (std::ostream& os, const std::vector<r_Minterval>& list) +{ + os << "[ "; + for (typename std::vector<r_Minterval>::const_iterator it = list.begin(); it != list.end(); it++) + os << (*it) << " "; + os << "]"; + return os; +} + +template <> +std::ostream& operator<< (const std::vector<r_Minterval>& list, std::ostream& os) +{ + os << "[ "; + for (typename std::vector<r_Minterval>::const_iterator it = list.begin(); it != list.end(); it++) + os << (*it) << " "; + os << "]"; + return os; +} + +#endif diff --git a/raslib/dlist.hh b/raslib/dlist.hh new file mode 100644 index 0000000..ea794e3 --- /dev/null +++ b/raslib/dlist.hh @@ -0,0 +1,42 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +#ifndef _DLIST_H_ +#define _DLIST_H_ +#include <iostream> +#include <vector> + +template <class T> +std::ostream& operator<< (std::ostream& os, const std::vector<T>& list); + +template <class T> +std::ostream& operator<< (const std::vector<T>& list, std::ostream& os); + +#ifdef EARLY_TEMPLATE +#ifdef __EXECUTABLE__ +#include "raslib/dlist.cc" +#endif +#endif + +#endif + diff --git a/raslib/endian.cc b/raslib/endian.cc new file mode 100644 index 0000000..45837a1 --- /dev/null +++ b/raslib/endian.cc @@ -0,0 +1,623 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: endian.cc + * + * MODULE: raslib + * CLASS: r_Endian + * + * COMMENTS: + * None +*/ + +#include <string.h> + + +#include "raslib/endian.hh" +#include "raslib/rmdebug.hh" +#include "raslib/minterval.hh" +#include "raslib/primitivetype.hh" +#include "raslib/structuretype.hh" +#include "raslib/miter.hh" + + + + +/* + * Inline code used in several places in the r_Endian class + */ + +static inline r_Octet eswap( r_Octet val ) +{ + return val; +} + +static inline void eswap( r_Octet val, void *dest ) +{ + r_Char *d = (r_Char *)dest; + *d = val; +} + +static inline r_Short eswap( r_Short val ) +{ + return (r_Short)(((val & 0xff) << 8) | ((val >> 8) & 0xff)); +} + +static inline r_UShort eswap( r_UShort val ) +{ + return (r_UShort)(((val & 0xff) << 8) | ((val >> 8) & 0xff)); +} + +static inline void eswap( r_Short val, void *dest ) +{ + r_Short *d = (r_Short *)dest; + *d = eswap(val); +} + +static inline void eswap( r_UShort val, void *dest ) +{ + r_UShort *d = (r_UShort *)dest; + *d = eswap(val); +} + +static inline r_Long eswap( r_Long val ) +{ + return (r_Long)(((val & 0xff) << 24) | ((val & 0xff00) << 8) | + ((val >> 8) & 0xff00) | ((val >> 24) & 0xff)); +} + +static inline r_ULong eswap( r_ULong val ) +{ + return (r_ULong)(((val & 0xff) << 24) | ((val & 0xff00) << 8) | + ((val >> 8) & 0xff00) | ((val >> 24) & 0xff)); +} + +static inline void eswap( r_Long val, void *dest ) +{ + r_Long *d = (r_Long *)dest; + *d = eswap(val); +} + +static inline void eswap( r_ULong val, void *dest ) +{ + r_ULong *d = (r_ULong *)dest; + *d = eswap(val); +} + +/* +these types are not supported +static inline long eswap( long val ) +{ + return (long)(((val & 0xff) << 24) | ((val & 0xff00) << 8) | + ((val >> 8) & 0xff00) | ((val >> 24) & 0xff)); +} + +static inline r_ULong eswap( r_ULong val ) +{ + return (r_ULong)(((val & 0xff) << 24) | ((val & 0xff00) << 8) | + ((val >> 8) & 0xff00) | ((val >> 24) & 0xff)); +} + +static inline void eswap( long val, void *dest ) +{ + long *d = (long *)dest; + *d = eswap(val); +} + +static inline void eswap( r_ULong val, void *dest ) +{ + r_ULong *d = (r_ULong *)dest; + *d = eswap(val); +} +*/ + +static inline r_Float eswap( r_Float val ) +{ + r_Long *ptr = (r_Long*)&val; + r_Float result; + + eswap(*ptr, &result); + + return result; +} + +static inline void eswap( r_Float val, void *dest ) +{ + r_Long *ptr = (r_Long*)&val; + + eswap(*ptr, dest); +} + + +#ifndef __GNUG__ +inline +#endif +static r_Double eswap( r_Double val ) +{ + r_Long *ptr = (r_Long*)&val; + r_Double result; + eswap(ptr[0], ((r_Octet*)&result)+sizeof(r_Long)); + eswap(ptr[1], (r_Octet*)&result); +/* +#ifndef DECALPHA + eswap(ptr[0], ((r_Octet*)&result)+sizeof(long)); + eswap(ptr[1], (r_Octet*)&result); +#else + eswap(*ptr, &result); +#endif +*/ + return result; +} + +#ifndef __GNUG__ +inline +#endif +static void eswap( r_Double val, void *dest ) +{ + r_Long *ptr = (r_Long*)&val; + eswap(ptr[0], ((r_Octet*)dest)+sizeof(r_Long)); + eswap(ptr[1], dest); +/* +#ifndef DECALPHA + eswap(ptr[0], ((r_Octet*)dest)+sizeof(long)); + eswap(ptr[1], dest); +#else + eswap(*ptr, dest); +#endif +*/ +} + + +/* + * Template functions used throughout the code + */ + +// template for special linear iteration +template<class T> +void swap_array_templ( r_Bytes size, T *dest, const T *src) +{ + const T *sptr = src; + T *dptr = dest; + r_Bytes ctr; + + for (ctr = 0; ctr < size; ctr += sizeof(T), sptr++, dptr++) + eswap(*sptr, dptr); +} + + +// template for identical domains for src and dest +template<class T> +void swap_array_templ(r_Miter &iter, T *destBase, const T *srcBase) +{ + while (!iter.isDone()) + { + const T *src = (const T*)iter.nextCell(); + eswap(*src, destBase + (src - srcBase)); + } +} + + +// template for generic iteration (src is just a dummy here) +template<class T> +void swap_array_templ(r_Miter &siter, r_Miter &diter, const T *srcBase) +{ + while (!siter.isDone()) + { + const T *src = (const T*)siter.nextCell(); + T *dest = (T*)diter.nextCell(); + eswap(*src, dest); + } +} + +// force the instantiations; we only need the templates r_Longernally anyway +template void swap_array_templ(r_Bytes, r_Short *, const r_Short *); +template void swap_array_templ(r_Bytes, r_UShort *, const r_UShort *); +template void swap_array_templ(r_Bytes, r_Long *, const r_Long *); +template void swap_array_templ(r_Bytes, r_ULong *, const r_ULong *); +/* +template void swap_array_templ(r_Bytes, long *, const long *); +template void swap_array_templ(r_Bytes, r_ULong *, const r_ULong *); +*/ +template void swap_array_templ(r_Bytes, r_Float *, const r_Float *); +template void swap_array_templ(r_Bytes, r_Double *, const r_Double *); +template void swap_array_templ(r_Miter &, r_Octet *, const r_Octet *); +template void swap_array_templ(r_Miter &, r_Short *, const r_Short *); +template void swap_array_templ(r_Miter &, r_Long *, const r_Long *); +template void swap_array_templ(r_Miter &, r_Float *, const r_Float *); +template void swap_array_templ(r_Miter &, r_Double *, const r_Double *); +template void swap_array_templ(r_Miter &, r_Miter &, const r_Octet *); +template void swap_array_templ(r_Miter &, r_Miter &, const r_Short *); +template void swap_array_templ(r_Miter &, r_Miter &, const r_Long *); +template void swap_array_templ(r_Miter &, r_Miter &, const r_Float *); +template void swap_array_templ(r_Miter &, r_Miter &, const r_Double *); + + + + + +/* + * r_Endian members + */ + +r_Short r_Endian::swap( r_Short val ) +{ + return eswap(val); +} + +r_UShort r_Endian::swap( r_UShort val ) +{ + return eswap(val); +} + +r_Long r_Endian::swap( r_Long val ) +{ + return eswap(val); +} + +r_ULong r_Endian::swap( r_ULong val ) +{ + return eswap(val); +} +/* +long r_Endian::swap( long val ) +{ + return eswap(val); +} + +r_ULong r_Endian::swap( r_ULong val ) +{ + return eswap(val); +} +*/ +r_Float r_Endian::swap( r_Float val ) +{ + return eswap(val); +} + +r_Double r_Endian::swap( r_Double val ) +{ + return eswap(val); +} + + +r_Endian::r_Endianness r_Endian::get_endianness( void ) +{ +#ifdef LITTLE_ENDIAN + return r_Endian_Little; +#else + return r_Endian_Big; +#endif +} + + + +/* + * Simplest array swapping: linear buffer filled with atomic type + */ + +void r_Endian::swap_array( const r_Primitive_Type *type, r_Bytes size, const void *src, void *dest ) +{ + switch (type->type_id()) + { + case r_Primitive_Type::BOOL: + case r_Primitive_Type::CHAR: + case r_Primitive_Type::OCTET: + if (src != (const void*)dest) + { + // change of endianness on 1 byte data is a NULL operation. + // if src and dest differ, we have to _copy_, though. + memcpy(dest, src, size); + } + break; + case r_Primitive_Type::SHORT: + swap_array_templ(size, (r_Short*)dest, (const r_Short*)src); + break; + case r_Primitive_Type::USHORT: + swap_array_templ(size, (r_UShort*)dest, (const r_UShort*)src); + break; + case r_Primitive_Type::LONG: + swap_array_templ(size, (r_Long*)dest, (const r_Long*)src); + break; + case r_Primitive_Type::ULONG: + swap_array_templ(size, (r_ULong*)dest, (const r_ULong*)src); + break; + case r_Primitive_Type::FLOAT: + case r_Primitive_Type::COMPLEXTYPE1: + swap_array_templ(size, (r_Float*)dest, (const r_Float*)src); + break; + case r_Primitive_Type::DOUBLE: + case r_Primitive_Type::COMPLEXTYPE2: + swap_array_templ(size, (r_Double*)dest, (const r_Double*)src); + break; + default: + RMDBGONCE(3, RMDebug::module_raslib, "r_Endian", "swap_array(type, size, src, dest) bad typeId " << type->type_id()); + break; + } +} + + +/* + * Same functionality as function above, but with the types given implicitly + * by the parameters + */ + +// Dummies, but useful when templates are used +void r_Endian::swap_array( r_Bytes size, const r_Octet *src, r_Octet *dest ) +{ +} + +void r_Endian::swap_array( r_Bytes size, const r_Char *src, r_Char *dest ) +{ +} + +// Here go the real ones... +void r_Endian::swap_array( r_Bytes size, const r_Short *src, r_Short *dest ) +{ + swap_array_templ(size, dest, src); +} + +void r_Endian::swap_array( r_Bytes size, const r_UShort *src, r_UShort *dest ) +{ + swap_array_templ(size, dest, src); +} + +void r_Endian::swap_array( r_Bytes size, const r_Long *src, r_Long *dest ) +{ + swap_array_templ(size, dest, src); +} + +void r_Endian::swap_array( r_Bytes size, const r_ULong *src, r_ULong *dest ) +{ + swap_array_templ(size, dest, src); +} +/* +void r_Endian::swap_array( r_Bytes size, const long *src, long *dest ) +{ + swap_array_templ(size, dest, src); +} + +void r_Endian::swap_array( r_Bytes size, const r_ULong *src, r_ULong *dest ) +{ + swap_array_templ(size, dest, src); +} +*/ +void r_Endian::swap_array( r_Bytes size, const r_Float *src, r_Float *dest ) +{ + swap_array_templ(size, dest, src); +} + +void r_Endian::swap_array( r_Bytes size, const r_Double *src, r_Double *dest ) +{ + swap_array_templ(size, dest, src); +} + + +/* + * Same functionality as above, but with the type size given as parameter + */ + +void r_Endian::swap_array( r_Bytes size, r_Bytes tsize, const void *src, void *dest ) +{ + switch (tsize) + { + case 2: + swap_array_templ(size, (r_Short*)dest, (const r_Short*)src); + break; + case 4: + swap_array_templ(size, (r_Long*)dest, (const r_Long*)src); + break; + case 8: + case 16: // complexd + swap_array_templ(size, (r_Double*)dest, (const r_Double*)src); + break; + default: + break; + } +} + + + +/* + * ``Half-generic'': array with arbitrary total domain and iteration + * domain, but same domains for src and dest + */ +void r_Endian::swap_array( const r_Primitive_Type *type, const r_Minterval &srcDom, const r_Minterval &srcIterDom, const void *src, void *dest, r_ULong step ) +{ + if ((srcDom == srcIterDom) && (step == type->size())) + { + r_ULong size = step * srcDom.cell_count(); + + swap_array(type, size, src, dest); + } + else + { + r_Miter iter(&srcIterDom, &srcDom, step, (const char*)src); + + switch (type->type_id()) + { + case r_Primitive_Type::BOOL: + case r_Primitive_Type::CHAR: + case r_Primitive_Type::OCTET: + if (src != (const void*)dest) + { + swap_array_templ(iter, (r_Octet*)dest, (const r_Octet*)src); + } + break; + case r_Primitive_Type::SHORT: + swap_array_templ(iter, (r_Short*)dest, (const r_Short*)src); + break; + case r_Primitive_Type::USHORT: + swap_array_templ(iter, (r_UShort*)dest, (const r_UShort*)src); + break; + case r_Primitive_Type::LONG: + swap_array_templ(iter, (r_Long*)dest, (const r_Long*)src); + break; + case r_Primitive_Type::ULONG: + swap_array_templ(iter, (r_ULong*)dest, (const r_ULong*)src); + break; + case r_Primitive_Type::FLOAT: + case r_Primitive_Type::COMPLEXTYPE1: + swap_array_templ(iter, (r_Float*)dest, (const r_Float*)src); + break; + case r_Primitive_Type::DOUBLE: + case r_Primitive_Type::COMPLEXTYPE2: + swap_array_templ(iter, (r_Double*)dest, (const r_Double*)src); + break; + default: + RMDBGONCE(3, RMDebug::module_raslib, "r_Endian", "swap_array(type, srcdom, srciterdom, src, dest, step) bad typeId " << type->type_id()); + break; + } + } +} + + +static void swap_array_struct( const r_Structure_Type *structType, const r_Minterval &srcDom, const r_Minterval &srcIterDom, const void *src, void *dest, r_ULong step ) +{ + r_Structure_Type::attribute_iterator iter(structType->defines_attribute_begin()); + + while (iter != structType->defines_attribute_end()) + { + r_Type *newType = (*iter).type_of().clone(); + const void *srcPtr = (const void*)(((const r_Octet*)src) + (*iter).offset()); + void *destPtr = (void*)(((r_Octet*)dest) + (*iter).offset()); + if (newType->isStructType()) + swap_array_struct((const r_Structure_Type*)newType, srcDom, srcIterDom, srcPtr, destPtr, step); + else + r_Endian::swap_array((const r_Primitive_Type*)newType, srcDom, srcIterDom, srcPtr, destPtr, step); + delete newType; + iter++; + } +} + + +void r_Endian::swap_array( const r_Base_Type *type, const r_Minterval &srcDom, const r_Minterval &srcIterDom, const void *src, void *dest ) +{ + if (type->isStructType()) + swap_array_struct((const r_Structure_Type*)type, srcDom, srcIterDom, src, dest, type->size()); + else + swap_array((const r_Primitive_Type*)type, srcDom, srcIterDom, src, dest, type->size()); +} + + + + +/* + * Fully generic: different total domain and iteration domain for both + * src and dest. Beware that the number of cells in the iteration domains + * for src and dest must be identical! + */ + +void r_Endian::swap_array( const r_Primitive_Type *type, const r_Minterval &srcDom, const r_Minterval &srcIterDom, const r_Minterval &destDom, const r_Minterval &destIterDom, const void *src, void *dest, r_ULong step ) +{ + /// check if the whole thing reduces to a linear scan + if ((srcDom == srcIterDom) && (step == type->size())) + { + r_ULong size = step * srcDom.cell_count(); + + swap_array(type, size, src, dest); + } + /// no, generic code... + else + { + r_Miter siter(&srcIterDom, &srcDom, (r_Long)step, (const char*)src); + r_Miter diter(&destIterDom, &destDom, (r_Long)step, (const char*)dest); + + switch (type->type_id()) + { + case r_Primitive_Type::BOOL: + case r_Primitive_Type::CHAR: + case r_Primitive_Type::OCTET: + if (src != (const void*)dest) + { + swap_array_templ(siter, diter, (const r_Octet*)src); + } + break; + case r_Primitive_Type::SHORT: + swap_array_templ(siter, diter, (const r_Short*)src); + break; + case r_Primitive_Type::USHORT: + swap_array_templ(siter, diter, (const r_UShort*)src); + break; + case r_Primitive_Type::LONG: + swap_array_templ(siter, diter, (const r_Long*)src); + break; + case r_Primitive_Type::ULONG: + swap_array_templ(siter, diter, (const r_ULong*)src); + break; + case r_Primitive_Type::FLOAT: + case r_Primitive_Type::COMPLEXTYPE1: + swap_array_templ(siter, diter, (const r_Float*)src); + break; + case r_Primitive_Type::DOUBLE: + case r_Primitive_Type::COMPLEXTYPE2: + swap_array_templ(siter, diter, (const r_Double*)src); + break; + default: + RMDBGONCE(3, RMDebug::module_raslib, "r_Endian", "swap_array(type, srcdom, srciterdom, destdom, destiterdom, src, dest, step) bad typeId " << type->type_id()); + break; + } + } +} + + +static void swap_array_struct( const r_Structure_Type *structType, const r_Minterval &srcDom, const r_Minterval &srcIterDom, const r_Minterval &destDom, const r_Minterval &destIterDom, const void *src, void *dest, r_ULong step) +{ + r_Structure_Type::attribute_iterator iter(structType->defines_attribute_begin()); + + while (iter != structType->defines_attribute_end()) + { + r_Type *newType = (*iter).type_of().clone(); + const void *srcPtr = (const void*)(((const r_Octet*)src) + (*iter).offset()); + void *destPtr = (void*)(((r_Octet*)dest) + (*iter).offset()); + if (newType->isStructType()) + swap_array_struct((const r_Structure_Type*)newType, srcDom, srcIterDom, destDom, destIterDom, srcPtr, destPtr, step); + else + r_Endian::swap_array((const r_Primitive_Type*)newType, srcDom, srcIterDom, destDom, destIterDom, srcPtr, destPtr, step); + delete newType; + iter++; + } +} + +void r_Endian::swap_array( const r_Base_Type *type, const r_Minterval &srcDom, const r_Minterval &srcIterDom, const r_Minterval &destDom, const r_Minterval &destIterDom, const void *src, void *dest ) +{ + if (type->isStructType()) + swap_array_struct((const r_Structure_Type*)type, srcDom, srcIterDom, destDom, destIterDom, src, dest, type->size()); + else + swap_array((const r_Primitive_Type*)type, srcDom, srcIterDom, destDom, destIterDom, src, dest, type->size()); +} + +std::ostream& operator<<(std::ostream& s, r_Endian::r_Endianness& e) +{ + switch(e) { + case r_Endian::r_Endian_Little: + s << "Little_Endian"; + break; + case r_Endian::r_Endian_Big: + s << "Big_Endian"; + break; + default: + s << "Unkown r_Endiannes"; + break; + } + return s; +} diff --git a/raslib/endian.hh b/raslib/endian.hh new file mode 100644 index 0000000..fb8e0ff --- /dev/null +++ b/raslib/endian.hh @@ -0,0 +1,118 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: endian.hh + * + * MODULE: raslib + * CLASS: r_Endian + * + * COMMENTS: + * None +*/ + +#ifndef _R_ENDIANTOOLS_HH_ +#define _R_ENDIANTOOLS_HH_ + +#include <iostream> + +class r_Minterval; +class r_Base_Type; +class r_Primitive_Type; +#include "raslib/odmgtypes.hh" +#include "raslib/mddtypes.hh" + +//@ManMemo: Module {\bf raslib} + +/*@Doc: + Class to check the endianness of the host machine and to + swap the endianness of types and arrays. Don't instantiate, + static members only. +*/ + +class r_Endian +{ + public: + /// endianness identifiers + enum r_Endianness { + r_Endian_Big, + r_Endian_Little + }; + + /// swap endianness of atomic types + static r_Short swap( r_Short val ); + static r_UShort swap( r_UShort val ); + static r_Long swap( r_Long val ); + static r_ULong swap( r_ULong val ); + static r_Float swap( r_Float val ); + static r_Double swap( r_Double val ); + + /// query host machine's endianness + static r_Endianness get_endianness( void ); + + /// change the endianness of a linear array of size <size> and type <type> + static void swap_array( const r_Primitive_Type *type, r_Bytes size, const void *src, void *dest ); + + /// change the endianness of a linear array of size <size>, type implicit + static void swap_array( r_Bytes size, const r_Octet *src, r_Octet *dest ); // dummy + static void swap_array( r_Bytes size, const r_Char *src, r_Char *dest ); // dummy + static void swap_array( r_Bytes size, const r_Short *src, r_Short *dest ); + static void swap_array( r_Bytes size, const r_UShort *src, r_UShort *dest ); + static void swap_array( r_Bytes size, const r_Long *src, r_Long *dest ); + static void swap_array( r_Bytes size, const r_ULong *src, r_ULong *dest ); + static void swap_array( r_Bytes size, const r_Float *src, r_Float *dest ); + static void swap_array( r_Bytes size, const r_Double *src, r_Double *dest ); + + /// change the endianness of a linear array of size <size> with type size <tsize> + static void swap_array( r_Bytes size, r_Bytes tsize, const void *src, void *dest); + + /// change the endianness of one type member of an array for identical domains + /// for src and dest; step is the increment between cells + static void swap_array( const r_Primitive_Type *type, const r_Minterval &srcDom, + const r_Minterval &srcIterDom, const void *src, void *dest, + r_ULong step ); + + /// change the endianness of the entire tile for identical domains for src and dest + static void swap_array( const r_Base_Type *type, const r_Minterval &srcDom, + const r_Minterval &srcIterDom, const void *src, void *dest ); + + /// change the endianness of one type member of an array for the generic case; + /// step is the increment between cells. + static void swap_array( const r_Primitive_Type *type, const r_Minterval &srcDom, + const r_Minterval &srcIterDom, const r_Minterval &destDom, + const r_Minterval &destIterDom, const void *src, void *dest, + r_ULong step ); + + /// change the endianness of the entire tile for the generic case + static void swap_array( const r_Base_Type *type, const r_Minterval &srcDom, + const r_Minterval &srcIterDom, const r_Minterval &destDom, + const r_Minterval &destIterDom, const void *src, void *dest ); +}; + +//@ManMemo: Module: {\bf raslib} +/** + Output stream operator for enum of type {\tt const} \Ref{r_Minterval}. + */ + extern std::ostream& operator<<( std::ostream& s, r_Endian::r_Endianness& e ); + + +#endif diff --git a/raslib/error.cc b/raslib/error.cc new file mode 100644 index 0000000..1ccc3cc --- /dev/null +++ b/raslib/error.cc @@ -0,0 +1,888 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/*** + * SOURCE: error.cc + * + * MODULE: raslib + * CLASS: r_Error + * + * COMMENTS: + * - in general, string should be used instead of dynamic char* mgmnt + * - r_Error specializations must not use int literals + * - freeTextTable() does not free strings -> mem leak +*/ + +static const char rcsid[] = "@(#)raslib, r_Error: $Id: error.cc,v 1.60 2005/09/03 20:35:12 rasdev Exp $"; + +using namespace std; + +using namespace std; + +#include "mymalloc/mymalloc.h" + +#include "raslib/error.hh" +#include "raslib/rmdebug.hh" +#include "debug.hh" + + +#include <string.h> +#ifdef __VISUALC__ +#include <strstrea.h> +#else +#include <strstream> +#endif + +#include <fstream> +#include <string> +#include <utility> +#include <list> +#include <stdlib.h> +#include <stdio.h> + + +using std::endl; +using std::ends; +using std::ios; +using std::ostrstream; + +r_Error::errorInfo* r_Error::textList = NULL; + +r_Error::r_Error() + : theKind(r_Error_General), + errorText(0), + errorNo(0) + { + resetErrorText(); + } + +r_Error::r_Error(const r_Error& err) + : errorText(0), + errorNo(err.errorNo), + theKind(err.theKind) + { + if (err.errorText) + { + errorText = new char[ strlen(err.errorText)+1 ]; + strcpy(errorText, err.errorText); + } + } + +r_Error::r_Error(kind the_kind, unsigned int newErrorNo) + : errorText(0), + theKind(the_kind), + errorNo(newErrorNo) + { + resetErrorText(); + } + +r_Error::~r_Error() throw() + { + if (errorText) + delete[] errorText; + } + + + +const char* +r_Error::what() const throw () + { + return (const char*)errorText; + } + + + +const r_Error& +r_Error::operator=(const r_Error& obj) + { + if (this != &obj) + { + if (errorText) + { + delete[] errorText; + errorText = NULL; + } + + theKind = obj.theKind; + errorNo = obj.errorNo; + + if (obj.errorText) + { + errorText = new char[ strlen(obj.errorText)+1 ]; + strcpy(errorText, obj.errorText); + } + } + + return *this; + } + +char* +r_Error::serialiseError() + { + // default implementation for errors not of kind r_Error_SerialisableException + char* retVal = NULL; + char buf[80]; // should be enough for two numbers + + sprintf(buf, "%d\t%d", theKind, errorNo); + retVal = (char*)mymalloc(strlen(buf) + 1); + strcpy(retVal, buf); + return retVal; + } + + +r_Error* +r_Error::getAnyError(char* serErr) +{ + r_Error* retVal = NULL; + char* currChar = NULL; + kind newTheKind; + unsigned int newErrNum = 0; + // first read the attributes of r_Error to find out which subclass it is + // (stored in errNum). + newTheKind = (r_Error::kind)strtol(serErr, &currChar, 10); + newErrNum = strtol(currChar+1, &currChar, 10); + + if (newTheKind != r_Error_SerialisableException) + { + retVal = new r_Error(newTheKind, newErrNum); + } + else + { + // add new serialisable errors to this case! + switch (newErrNum) + { + case 206: + retVal = new r_Ebase_dbms(newTheKind, newErrNum, currChar+1); + break; + } + } + return retVal; +} + +// +// --- error text file table maintenance --------------------------------- +// + +/* + * list of error codes, contining numerical error code, error flag char + * (warning or error), and error text. + * It is modelled as nested pairs to allow using standard classes. + * Filled from file. + */ +list<pair<pair<int,char>, char*> > errorTexts; + +/// has error text file been loaded, i.e., is table filled? +bool errorTextsLoaded = false; + +void +initTextTable() +{ + char errorFileName[FILENAME_MAX]; // error file path/name + std::ifstream errortexts; + string line; // current input line read from file + char errKind; + int errNo; + char errText[1000]; + unsigned int numOfEntries = 0; + int result; // sscanf() result + + // determine file name; use path if env var is set + strcpy( errorFileName, "" ); + const char* rmanHome = getenv( RASDAMAN_PATH_VARNAME ); + if (rmanHome) + { + strcat(errorFileName, rmanHome); + strcat(errorFileName, ERRORTEXXT_PATH ); + strcat(errorFileName, "/" ); + } else { + strcat(errorFileName, SHARE_DATA_DIR); + strcat(errorFileName, "/"); + } + strcat(errorFileName, ERRORTEXT_FILE ); + // RMInit::logOut << "using error text file: " << errorFileName << endl; + + // errortexts.open(errorFileName, ios::nocreate | ios::in); + errortexts.open(errorFileName, ios::in); + + // In case the file 'errtxts' can't be found +#ifdef __VISUALC__ + if (!errortexts.is_open()) +#else + if (!errortexts) +#endif + { + r_Error::textList = NULL; + RMInit::logOut << "No error texts file found at: " << errorFileName << endl; + } + else // File errtxts found + { + // read entries from file + numOfEntries = 0; // just for displaying, currently not used otherwise + while ( ! errortexts.eof() ) + { + getline( errortexts, line ); + char *errText = (char*) mymalloc( line.length() + 1 ); + if (errText == NULL) + { + RMInit::logOut << "Fatal error: cannot allocate error text table line #" << numOfEntries << endl; + throw r_Error( r_Error::r_Error_MemoryAllocation ); + } + // general line format is (aside of comments and empty lines): ddd^f^text... + result = sscanf( line.c_str(), "%d^%c^%[^\n]s\n", &errNo, &errKind, errText ); + if (result == 3) // consider only lines that match given structure + { + errorTexts.push_back( pair<pair<int,char>,char*> (pair<int,char>( errNo, errKind ), errText) ); + numOfEntries++; + } + } + // RMInit::logOut << "number of error texts loaded: " << numOfEntries << endl; + errorTextsLoaded = true; + } + errortexts.close(); +} + + + +void +freeTextTable() +{ + list<pair<pair<int,char>, char*> >::iterator iter = errorTexts.begin(); + list<pair<pair<int,char>, char*> >::iterator end = errorTexts.end(); + + if (errorTextsLoaded) // have we initialized the table previously? + { // yes -> free each string +#if 0 // doesn't work yet + while ( iter != NULL && iter != end ) + { + cout << "freeing " << iter->second << endl << flush; + free( iter->second ); + iter->second = NULL; + // delete[] iter->second; + } +#endif + errorTexts.clear(); // now clear list itself + } +} + + + +r_Error::r_Error(unsigned int errorno) + : errorText(NULL), + theKind(r_Error_General), + errorNo(errorno) +{ + resetErrorText(); +} + + + +void +r_Error::setErrorTextOnKind() + { + char buffer[256]; + + switch (theKind) + { + case r_Error_General : + strcpy(buffer, " ODMG General"); + break; + + case r_Error_DatabaseClassMismatch : + strcpy(buffer, "Database Class Mismatch"); + break; + + case r_Error_DatabaseClassUndefined : + strcpy(buffer, "Database Class Undefined"); + break; + + case r_Error_DatabaseClosed : + strcpy(buffer, "Database Closed"); + break; + + case r_Error_DatabaseOpen : + strcpy(buffer, "Database Open"); + break; + + case r_Error_DateInvalid : + strcpy(buffer, "Date Invalid"); + break; + + case r_Error_IteratorExhausted : + strcpy(buffer, "Iterator Exhausted"); + break; + + case r_Error_NameNotUnique : + strcpy(buffer, "Name Not Unique"); + break; + + case r_Error_QueryParameterCountInvalid : + strcpy(buffer, "Query Parameter Count Invalid"); + break; + + case r_Error_QueryParameterTypeInvalid : + strcpy(buffer, "Query Parameter Type Invalid"); + break; + + case r_Error_RefInvalid : + strcpy(buffer, "Ref Invalid"); + break; + + case r_Error_RefNull : + strcpy(buffer, "Ref Null"); + break; + + case r_Error_TimeInvalid : + strcpy(buffer, "Time Invalid"); + break; + + case r_Error_TimestampInvalid : + strcpy(buffer, "Timestamp Invalid"); + break; + + case r_Error_TransactionOpen : + strcpy(buffer, "Transaction Open"); + break; + + case r_Error_TransactionNotOpen : + strcpy(buffer, "Transaction Not Open"); + break; + + case r_Error_TypeInvalid : + strcpy(buffer, "Type Invalid"); + break; + + case r_Error_DatabaseUnknown : + strcpy(buffer, "Database Unknown"); + break; + + case r_Error_TransferFailed : + strcpy(buffer, "Transfer Failed"); + break; + + case r_Error_HostInvalid : + strcpy(buffer, "Host Invalid"); + break; + + case r_Error_ServerInvalid : + strcpy(buffer, "Server Invalid"); + break; + + case r_Error_ClientUnknown : + strcpy(buffer, "Client Unknown"); + break; + + case r_Error_ObjectUnknown : + strcpy(buffer, "Object Unknown"); + break; + + case r_Error_ObjectInvalid : + strcpy(buffer, "Object Invalid"); + break; + + case r_Error_QueryExecutionFailed : + strcpy(buffer, "Query Execution Failed"); + break; + + case r_Error_BaseDBMSFailed : + strcpy(buffer, "Base DBMS Failed"); + break; + + case r_Error_CollectionElementTypeMismatch : + strcpy(buffer, "Collection Element Type Mismatch"); + break; + + case r_Error_CreatingOIdFailed : + strcpy(buffer, "Creation of OID failed"); + break; + + case r_Error_TransactionReadOnly : + strcpy(buffer, "Transaction is read only"); + break; + + case r_Error_LimitsMismatch : + strcpy(buffer, "Limits reported to an object mismatch"); + break; + + case r_Error_NameInvalid : + strcpy(buffer, "Name Invalid"); + break; + + case r_Error_FeatureNotSupported : + strcpy(buffer, "Feature is not supported"); + break; + + case r_Error_AccesDenied: + strcpy(buffer, "Access denied"); + break; + + case r_Error_MemoryAllocation: + strcpy(buffer, "Memory allocation failed"); + break; + + default: + strcpy(buffer, "not specified"); + break; + } + + if (errorText) + delete[] errorText; + + char preText[] = "Exception: "; + + errorText = new char[strlen(preText) + strlen(buffer) + 1]; + strcpy(errorText, preText); + strcat(errorText, buffer); + } + + + +void +r_Error::setErrorTextOnNumber() +{ + char *result = NULL; // ptr to error text constructed + + // delete old error text, if any + if (errorText) + { + delete[] errorText; + errorText = 0; + } + + // has list been built earlier? + if (errorTextsLoaded) + { // yes, we have a list -> search + // search through list to find entry + list<pair<pair<int,char>, char*> >::iterator iter = errorTexts.begin(); + list<pair<pair<int,char>, char*> >::iterator end = errorTexts.end(); + bool found = false; + while ( iter != end && ! found ) + { + if (iter->first.first == errorNo) + found = true; + else + iter++; + } + + if (found) + result = iter->second; + else + result = "(no explanation text available for this error code.)"; + } + else // no, there is no spoon -err- list + result = "(no explanation text available - cannot find/load file with standard error messages.)"; + + errorText = new char[strlen(result) + 1]; + if (errorText == NULL) + { + RMInit::logOut << "Error: cannot allocate error text." << endl; + throw r_Error( r_Error::r_Error_MemoryAllocation ); + } + else + strcpy(errorText, result); + + return; +} + + + +void +r_Error::setTextParameter(const char* parameterName, int value) + { + // convert long value to string + char valueString[256]; + ostrstream valueStream(valueString, sizeof(valueString) ); + valueStream << value << ends; + + setTextParameter(parameterName, valueString); + } + + + +void +r_Error::setTextParameter(const char* parameterName, const char* value) + { + if (errorText) + { + // locate the next matching parameter in the query string + char* paramStart = strstr(errorText, parameterName); + + if (paramStart) + { + // allocate a new query string and fill it + char* paramEnd = NULL; + int paramLength = 0; + char* tmpText = NULL; + int newLength = 0; + + tmpText = errorText; + paramLength = strlen(parameterName); + paramEnd = paramStart + paramLength; + newLength = strlen(tmpText) - paramLength + strlen(value) + 1; + errorText = new char[newLength]; + + *paramStart = '\0'; + + ostrstream queryStream(errorText, newLength); + queryStream << tmpText << value << paramEnd << ends; + + delete[] tmpText; + } + } + } + + + +void +r_Error::resetErrorText() + { + // If no error number is specified use the error kind for the text. + if (errorNo) + setErrorTextOnNumber(); + else + setErrorTextOnKind(); + } + + + +r_Eno_interval::r_Eno_interval() + : r_Error(201) + { + TALK( "r_Error::resetErrorText() - code 201" ); + resetErrorText(); + } + + + +r_Eindex_violation::r_Eindex_violation(r_Range dlow, r_Range dhigh, r_Range dindex) + : r_Error(202), low(dlow), high(dhigh), index(dindex) + { + TALK( "r_Error::r_Eindex_violation() - code 202" ); + resetErrorText(); + } + + + +void +r_Eindex_violation::resetErrorText() + { + setErrorTextOnNumber(); + + setTextParameter("$low", low ); + setTextParameter("$high", high ); + setTextParameter("$index", index); + } + + + +r_Edim_mismatch::r_Edim_mismatch(r_Dimension pdim1, r_Dimension pdim2) + : r_Error(203), dim1(pdim1), dim2(pdim2) + { + TALK( "r_Error::r_Edim_mismatch() - code 203; dim1=" << pdim1 << ", dim2=" << pdim2 ); + resetErrorText(); + } + + + +void +r_Edim_mismatch::resetErrorText() + { + setErrorTextOnNumber(); + + setTextParameter("$dim1", dim1); + setTextParameter("$dim2", dim2); + } + + + +r_Einit_overflow::r_Einit_overflow() + : r_Error(204) + { + TALK( "r_Error::r_Einit_overflow() - code 204" ); + resetErrorText(); + } + + + +r_Eno_cell::r_Eno_cell() + : r_Error(205) + { + TALK( "r_Error::r_Eno_cell() - code 205" ); + resetErrorText(); + } + + + +r_Equery_execution_failed::r_Equery_execution_failed(unsigned int errorno, unsigned int lineno, unsigned int columnno, const char* initToken) + : r_Error(errorno), + lineNo(lineno), + columnNo(columnno) + { + TALK( "r_Error::r_Equery_execution_failed() - errorno=" << errorno ); + + token = new char[strlen(initToken)+1]; + strcpy(token, initToken); + + resetErrorText(); + } + + + +r_Equery_execution_failed::r_Equery_execution_failed(const r_Equery_execution_failed &err) + : r_Error(err), + lineNo(0), + columnNo(0) + { + TALK( "r_Error::r_Equery_execution_failed()" ); + + lineNo = err.lineNo; + columnNo = err.columnNo; + + token = new char[strlen(err.token)+1]; + strcpy(token, err.token); + } + + + +r_Equery_execution_failed::~r_Equery_execution_failed() throw() + { + if (token) + delete[] token; + } + + + +void +r_Equery_execution_failed::resetErrorText() + { + setErrorTextOnNumber(); + + setTextParameter("$errorNo", errorNo); + setTextParameter("$lineNo", lineNo); + setTextParameter("$columnNo", columnNo); + setTextParameter("$token", token); + } + + + +r_Elimits_mismatch::r_Elimits_mismatch(r_Range lim1, r_Range lim2) + : r_Error(r_Error_LimitsMismatch), i1(lim1), i2(lim2) + { + TALK( "r_Error::r_Elimits_mismatch() - lim1=" << lim1 << ", lim2=" << lim2 ); + resetErrorText(); + } + + + +void +r_Elimits_mismatch::resetErrorText() + { + setErrorTextOnNumber(); + + setTextParameter("$dim1", i1); + setTextParameter("$dim2", i2); + } + +/* ------------------------------------------------------------------ + class r_Ebase_dbms + ------------------------------------------------------------------ */ + +r_Ebase_dbms::r_Ebase_dbms(const long& newDbmsErrNum, const char* newDbmsErrTxt) + : r_Error(r_Error_SerialisableException, 206), + dbmsErrNum(newDbmsErrNum), + whatTxt(0) +{ + TALK( "r_Error::r_Ebase_dbms() code 206 - " << newDbmsErrTxt ); + baseDBMS = strdup("Error in base DBMS, error number: "); + dbmsErrTxt = strdup(newDbmsErrTxt); + buildWhat(); +} + +r_Ebase_dbms::r_Ebase_dbms(const r_Ebase_dbms& obj) + : r_Error(obj), + dbmsErrNum(0), + whatTxt(0) +{ + TALK( "r_Error::r_Ebase_dbms()" ); + + dbmsErrNum = obj.dbmsErrNum; + if (obj.baseDBMS) + { + baseDBMS = (char*)mymalloc(strlen(obj.baseDBMS) + 1); + strcpy(baseDBMS, obj.baseDBMS); + } + else + { + baseDBMS = 0; + } + if (obj.dbmsErrTxt) + { + dbmsErrTxt = (char*)mymalloc(strlen(obj.dbmsErrTxt) + 1); + strcpy(dbmsErrTxt, obj.dbmsErrTxt); + } + else + { + dbmsErrTxt = 0; + } + buildWhat(); +} + +// r_Ebase_dbms: constructor receiving kind, errno, and descriptive string +// NB: the string must have the format "<kind>\t<errno>\t<text>" +// (currently the only location where this is used is getAnyError() above) +r_Ebase_dbms::r_Ebase_dbms(kind newTheKind, unsigned long newErrNum, const char* myStr) + : r_Error(newTheKind, newErrNum), whatTxt(0) +{ + TALK( "r_Error::r_Ebase_dbms() - kind=" << newTheKind ); + + // as the const char* cannot be passed to strtol() - this was a bug anyway - + // we copy the string. Efficiency is not a concern here. -- PB 2005-jan-14 + // const char* currChar = myStr; + char* tmpBuf = NULL; // temp copy of myStr + char* currChar = NULL; // ptr iterating over tmpBuf + tmpBuf = strdup( myStr ); + currChar = tmpBuf; // initialize char ptr to begin of buffer + + // read the attributes of r_Ebase_dbms from the string already partially parsed by + // r_Error::getAnyError(char* serErr) + dbmsErrNum = strtol(currChar, &currChar, 10); + // of course \t is part of the string, so we trick a little + char* tmpPtr = strchr(((char*)currChar)+1, '\t'); + if (tmpPtr==NULL) // no trailing information found? + { + baseDBMS = strdup( "unknown" ); + dbmsErrTxt = strdup( "unknown" ); + } + else // yes -> analyse it + { + *tmpPtr = '\0'; // terminate item for strdup() + baseDBMS = strdup(currChar+1); // extract item (db name) from string + *tmpPtr = '\t'; // re-substitute EOS with tab + currChar = strchr(currChar+1, '\t'); // search for tab as item delimiter + dbmsErrTxt = strdup(currChar+1); // extract final item which is error text + } + buildWhat(); + + free( tmpBuf ); // allocated in strdup() -- PB 2005-jan-14 +} + +r_Ebase_dbms::~r_Ebase_dbms() throw() +{ + if (whatTxt) + free(whatTxt); + if (dbmsErrTxt) + free(dbmsErrTxt); + if (baseDBMS) + free(baseDBMS); +} + +const r_Ebase_dbms& +r_Ebase_dbms::operator=(const r_Ebase_dbms& obj) +{ + if (this != &obj) + { + dbmsErrNum = obj.dbmsErrNum; + + if (obj.baseDBMS) + { + if (baseDBMS) free(baseDBMS); + baseDBMS = (char*)mymalloc(strlen(obj.baseDBMS) + 1); + strcpy(baseDBMS, obj.baseDBMS); + } + else + { + baseDBMS = 0; + } + if (obj.dbmsErrTxt) + { + if (dbmsErrTxt) free(dbmsErrTxt); + dbmsErrTxt = (char*)mymalloc(strlen(obj.dbmsErrTxt) + 1); + strcpy(dbmsErrTxt, obj.dbmsErrTxt); + } + else + { + dbmsErrTxt = 0; + } + buildWhat(); + } + return *this; + } + +void +r_Ebase_dbms::buildWhat() +{ + // Ok, we have to build the error message for this class. The problem is that ressource + // allocation is involved here! + if(whatTxt) + free(whatTxt); + // assumes 10 digits for errNum + whatTxt = (char*)mymalloc(strlen(baseDBMS) + strlen(dbmsErrTxt) + 12); + strcpy(whatTxt, baseDBMS); + sprintf(whatTxt + strlen(whatTxt), "%d\n", dbmsErrNum); + strcat(whatTxt, dbmsErrTxt); +} + +const char* +r_Ebase_dbms::what() const throw() +{ + return whatTxt; +} + +char* +r_Ebase_dbms::serialiseError() +{ + char* tmpRes = r_Error::serialiseError(); + char buf[40]; + char* retVal; + + sprintf(buf, "\t%d\t", dbmsErrNum); + retVal = (char*)mymalloc(strlen(tmpRes) + strlen(buf) + strlen(baseDBMS) + strlen(dbmsErrTxt) + 2); + strcpy(retVal, tmpRes); + strcat(retVal, buf); + strcat(retVal, baseDBMS); + strcat(retVal, "\t"); + strcat(retVal, dbmsErrTxt); + + free(tmpRes); + return retVal; +} + +r_Eno_permission::r_Eno_permission() +:r_Error(r_Error_AccesDenied,NO_PERMISSION_FOR_OPERATION) +{ + TALK( "r_Error::r_Eno_permission()" ); + resetErrorText(); +} + + +r_Ememory_allocation::r_Ememory_allocation(): r_Error(r_Error_MemoryAllocation, 66) // 66 is: mem alloc failed +{ + TALK( "r_Error::r_Ememory_allocation() - code 66" ); + resetErrorText(); +} + +r_Ecapability_refused::r_Ecapability_refused() +:r_Error(r_Error_AccesDenied,CAPABILITY_REFUSED) +{ + TALK( "r_Error::r_Ecapability_refused()" ); + resetErrorText(); +} + diff --git a/raslib/error.hh b/raslib/error.hh new file mode 100644 index 0000000..074c37d --- /dev/null +++ b/raslib/error.hh @@ -0,0 +1,583 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: error.hh + * + * MODULE: raslib + * CLASS: r_Error + * + * COMMENTS: + * +*/ + +#ifndef _D_ERROR_ +#define _D_ERROR_ + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + This class implements partially the \Ref{r_Error} class of the + C++ binding of ODMG-93 v.1.2. It extends exception + handling through deriving special classes for MDD specific + errors. + + In future, \Ref{r_Error} should be derived from the class exception + defined in the C++ standard. + + The class allows the specification of an error number. The error number + is used as an index to a generic textual description of the error which + is read by {\tt setErrorTextOnNumber()}. Error text is loaded from a + text file by the friend method {\tt initTextTable()} which has to be + invoked at the beginning of the application. The table can be freed again + using {\tt freeTextTable()}. + The parameters in the generic text are substituted using {\tt setTextParameter()}. + + If no error number is specified, the error kind is used as error text. + + Attention: The content of an error object is not supposed to be changed after + creation because the error text is initialized only in the constructor. Therefore, + just read methods for error parameters are supported. + + A standard error text file is read by {\tt initTextTable()}. The location and file + name expected is defined here. Ideally all programs using this mechanism should + include error.hh to use the same settings. +*/ + +#ifdef __VISUALC__ +#pragma warning( disable : 4290 ) +#endif + +#include <exception> + +#include "raslib/mddtypes.hh" + +/* + * error text file ------------------ + */ + +/// name of variable which should contain path to rasdaman home dir +#define RASDAMAN_PATH_VARNAME "RMANHOME" + +/// relative path to error text file, starting from $RMANHOME +#define ERRORTEXXT_PATH "/bin" + +/// error text file name +#define ERRORTEXT_FILE "errtxts" + +/* end error text file ------------------ */ + +class r_Error : public std::exception +{ + public: + + /// error information + struct errorInfo { + int num; + char kind; + char* text; + }; + + /// error kinds + enum kind { r_Error_General, + r_Error_DatabaseClassMismatch, + r_Error_DatabaseClassUndefined, + r_Error_DatabaseClosed, + r_Error_DatabaseOpen, + r_Error_DateInvalid, + r_Error_IteratorExhausted, + r_Error_NameNotUnique, + r_Error_QueryParameterCountInvalid, + r_Error_QueryParameterTypeInvalid, + r_Error_RefInvalid, + r_Error_RefNull, + r_Error_TimeInvalid, + r_Error_TimestampInvalid, + r_Error_TransactionOpen, + r_Error_TransactionNotOpen, + r_Error_TypeInvalid, + + r_Error_OIdInvalid, + r_Error_OIdNotUnique, + + r_Error_DatabaseUnknown, + r_Error_TransferFailed, + r_Error_HostInvalid, + r_Error_ServerInvalid, + r_Error_RpcInterfaceIncompatible, + r_Error_ClientUnknown, + r_Error_ObjectUnknown, + r_Error_ObjectInvalid, + + r_Error_QueryExecutionFailed, + r_Error_BaseDBMSFailed, + r_Error_CollectionElementTypeMismatch, + r_Error_CreatingOIdFailed, + r_Error_TransactionReadOnly, + + r_Error_LimitsMismatch, + r_Error_NameInvalid, + r_Error_FeatureNotSupported, + // r_Error_SerialisableException is used for subclasses which can be serialised + // as strings for client / server transfer + r_Error_SerialisableException, + + r_Error_AccesDenied, + r_Error_SystemOverloaded, + + r_Error_MemoryAllocation + + }; + + /// default constructor + r_Error(); + + /// copy constructor + r_Error( const r_Error& ); + + /// constructor getting the kind + r_Error( kind the_kind, unsigned int newErrorNo = 0 ); + + /// constructor getting an error number + r_Error( unsigned int errorno ); + + /// destructor + virtual ~r_Error() throw(); + + /// get an error description + virtual const char* what() const throw(); + + /// assignment operator + const r_Error& operator=( const r_Error& obj ); + + //@Man: Read/Write methods: + //@{ + /// + inline kind get_kind() const; + /// + inline unsigned int get_errorno() const; + /// + //@} + + /// used to transfer exceptions of kind r_Error_SerialisableException to the client. + virtual char* serialiseError(); + /*@Doc: + The char* returned is allocated with malloc (for potential RPC transfer) and has + to be freed by the caller. + */ + + /// This function parses a serialised error. + static r_Error* getAnyError(char* serErr); + /*@Doc: + Useful results can only be expected for errors of kind r_Error_SerialisableException. + */ + + /// read error text file into text table + friend void initTextTable(); + + /// free the text table again + friend void freeTextTable(); + + /// replace the specified parameter by the integer value + void setTextParameter( const char* parameterName, int value ); + + /// replace the specified parameter by the string value + void setTextParameter( const char* parameterName, const char* value ); + + protected: + /// set error text according to the actual error kind + void setErrorTextOnKind(); + + /// set error text according to the actual error number + void setErrorTextOnNumber(); + + /// reset error text + virtual void resetErrorText(); + /** + The virtual method is redefined in each subclass which supports text parameters. + Usually it is invoked in the constructor of the subclass. + */ + + /// attribute storing the error description text + char* errorText; + + /// attribute storing the error kind + kind theKind; + + /// attribute storing the number of the error + unsigned int errorNo; + + private: + static errorInfo *textList; +}; + + +/* Modified by Constantin Jucovschi */ +/* Added the definition of the initTextTable() and freeTextTable()*/ + void initTextTable(); + void freeTextTable(); + + + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + This class represents an array object saying that the + result is no interval. + +*/ + +class r_Eno_interval : public r_Error +{ + public: + /// default constructor + r_Eno_interval(); +}; + + + + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + This class represents an array object saying that the + specified index is not within the bounds. + +*/ + +class r_Eindex_violation : public r_Error +{ + public: + /// constructor getting lower and upper bound, and the index + r_Eindex_violation( r_Range dlow, r_Range dhigh, r_Range dindex ); + + protected: + /// reset error text + virtual void resetErrorText(); + + private: + /// lower bound + r_Range low; + /// upper bound + r_Range high; + /// index which caused the error + r_Range index; +}; + + + + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + This class represents an array object saying that the + dimensionalies of two objects do not match. + +*/ + +class r_Edim_mismatch : public r_Error +{ + public: + /// constructor getting two dimensionalities + r_Edim_mismatch( r_Dimension pdim1, r_Dimension pdim2 ); + + protected: + /// reset error text + virtual void resetErrorText(); + + private: + /// first dimensionality + r_Dimension dim1; + /// second dimensionality + r_Dimension dim2; +}; + + + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + This class represents an error object saying that an + initialization overflow occured. This happens f.e. if the + stream input operator is invoked more often than the + object has dimensions. + +*/ + +class r_Einit_overflow : public r_Error +{ + public: + /// default constructor + r_Einit_overflow(); +}; + + + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + This class represents an error object saying that the + result is no cell. This happens f.e. if the cast operator + for casting to the base type of class \Ref{r_Marray} is invoked + on an object which is not 'zero-dimensional'. + +*/ + +class r_Eno_cell : public r_Error +{ + public: + /// default constructor + r_Eno_cell(); +}; + + + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + The class is used for errors occuring through query execution. In most cases, the position which + caused the error can be fixed. This position is specified by line number, column number, and + the token which is involved. + Additionally, the class is generic concerning the error type. Different error types can be specified + by stating the error number. + +*/ + +class r_Equery_execution_failed : public r_Error +{ + public: + /// default constructor + r_Equery_execution_failed( unsigned int errorno, unsigned int lineno, unsigned int columnno, const char* token ); + + /// copy constructor + r_Equery_execution_failed( const r_Equery_execution_failed &err ); + + /// destructor + ~r_Equery_execution_failed() throw(); + + //@Man: Read methods: + //@{ + /// + inline unsigned int get_lineno() const; + /// + inline unsigned int get_columnno() const; + /// + inline const char* get_token() const; + /// + //@} + + protected: + /// reset error text + virtual void resetErrorText(); + + private: + /// line number in which the error is caused + unsigned int lineNo; + + /// column number which caused the error or is near to the error position + unsigned int columnNo; + + /// token which caused the error or is near to the error position + char* token; +}; + + + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + This class represents an error when the limits reported on the same + object (array) by two sources do not match (at least in one end). +*/ + +class r_Elimits_mismatch : public r_Error +{ + public: + /// constructor getting two limits on the same interval + r_Elimits_mismatch( r_Range lim1, r_Range lim2 ); + + protected: + /// reset error text + virtual void resetErrorText(); + + private: + /// first interval + r_Range i1; + /// second interval + r_Range i2; +}; + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + This class represents an error in the base DBMS. It stores the error + number in the base DBMS and the error text of the base DBMS. The + interpretation of the error is specific for the base DBMS. The + errtxt mechanism of RasDaMan is not used, instead what() returns the + error of the base DBMS. Note that the const char* parameters of the + constructor are not copied, but the pointers are stored. They are + never freed (to enable use of constants). +*/ + +class r_Ebase_dbms : public r_Error +{ +public: + /// constructor. + r_Ebase_dbms( const long& newErrNum, const char* newErrTxt ); + + /// copy constructor + r_Ebase_dbms( const r_Ebase_dbms& oldErr ); + + /// constructor reading from a char* containing serialised representation. + r_Ebase_dbms( kind newTheKind, unsigned long newErrNum, const char* myStr ); + + /// destructor + ~r_Ebase_dbms() throw(); + + /// assignment operator + const r_Ebase_dbms& operator=( const r_Ebase_dbms& obj ); + + // overloads from r_Error + virtual const char* what() const throw(); + virtual char* serialiseError(); + +private: + + /// build what text + void buildWhat(); + /// the name of the base DBMS. + char* baseDBMS; + /// error number of the base DBMS. + long dbmsErrNum; + /// error text of the base DBMS. + char* dbmsErrTxt; + /// used as return value for what() + char* whatTxt; +}; + +class r_Eno_permission : public r_Error + { + public: + r_Eno_permission(); + + }; + +class r_Ecapability_refused : public r_Error + { + public: + r_Ecapability_refused(); + + }; + +class r_Ememory_allocation: public r_Error { +public: + r_Ememory_allocation(); +}; + +#define MEMMORYALLOCATIONERROR 66 +#define INTERNALDLPARSEERROR 100 +#define NOPOINT 200 +#define RASTYPEUNKNOWN 209 +#define BASETYPENOTSUPPORTED 210 +#define RPCCOMMUNICATIONFAILURE 212 +#define SYSTEM_COLLECTION_NOT_WRITABLE 216 +#define SYSTEM_COLLECTION_HAS_NO_OID 217 +#define CONVERSIONFORMATNOTSUPPORTED 218 +#define TILESIZETOOSMALL 219 +#define STORAGERLAYOUTINCOMPATIBLEWITHGMARRAY 220 +#define DOMAINUNINITIALISED 221 +#define NOTANMARRAYTYPE 222 +#define RCINDEXWITHINCOMPATIBLEMARRAYTYPE 223 +#define TILECONFIGMARRAYINCOMPATIBLE 224 +#define RCINDEXWITHOUTREGULARTILING 225 +#define UDFBODYTOOLARGE 226 +#define POLYGONWRONGPOINTDIMENSION 227 +#define POLYGONWRONGINITSTRING 228 +#define QUERYPARAMETERINVALID 229 +#define ILLEGALARGUMENT 230 +#define MARRAYHASNOBASETYPE 231 +#define INTERVALOPEN 232 +#define INTERVALSWITHDIFFERENTDIMENSION 233 +#define TILINGPARAMETERNOTCORRECT 234 +#define CONNECTIONCLOSED 235 +#define COMPRESSIONFAILED 236 +#define CLIENTCOMMUICATIONFAILURE 237 +#define BASETYPENOTSUPPORTEDBYOPERATION 238 +#define OVERLAYPATTERNTOOSMALL 239 +#define INSERTINTORCINDEX 240 +#define NOTILINGDEFINED 241 +#define UNSATIFIEDMDDCONSTANT 373 +#define DATABASE_EXISTS 708 +#define NO_PERMISSION_FOR_OPERATION 803 +#define CAPABILITY_REFUSED 804 +#define DATABASE_INCONSISTENT 1000 +#define DATABASE_INCOMPATIBLE 1001 +#define ZERO_LENGTH_BLOB 1002 +#define TILE_CONTAINER_NOT_FOUND 1003 +#define INDEX_OF_MDD_IS_NULL 1004 +#define STORAGE_OF_MDD_IS_NULL 1005 +#define UNKNOWN_INDEX_TYPE 1006 +#define ILLEGAL_INDEX_TYPE 1007 +#define COLLTYPE_NULL 1008 +#define MDD_NOT_VALID 1009 +#define MDDTYPE_NULL 1010 +#define ILLEGALSTATEREACHED 1011 +#define COLLECTIONTYPEISNULL 1012 +#define TYPENAMEISTOOLONG 1013 +#define INVALIDOBJECTNAME 1014 +#define DATABASE_OPEN 2000 +#define INVALID_OIDTYPE 2001 +#define STRUCTTYPE_ELEMENT_UNKNOWN 2002 +#define STRUCTTYPE_ELEMENT_OUT_OF_BOUNDS 2003 +#define TRANSIENT_INDEX_USED_AS_PERSISTENT 2004 +#define TILE_MULTIPLE_TIMES_RETRIEVED 2005 +#define TILE_NOT_INSERTED_INTO_INDEX 2006 +#define TRANSIENT_INDEX_OUT_OF_BOUNDS 2007 +#define MDD_EXISTS_MULTIPLE_TIMES 2008 +#define DATA_NOT_INSERTED_COMPLETELY 2009 +#define CONVERSION_RETURNED_WRONG_TYPE 2010 +#define COLLECTIONTYPEHASNOELEMENTTYPE 2011 +#define MARRAYTYPEHASNOELEMENTTYPE 2012 +#define PROPERTYTYPEHASNOELEMENTTYPE 2013 +#define SCALARWASPASSEDNULLTYPE 2014 +#define INDEXNOTFOUNDINPARENT 2015 +#define INDEXEXHAUSTEDAREA 2016 +#define LAYOUTALGORITHMPROBLEM 2017 +#define OBJECTDOESNOTSUPPORTSWAPING 2018 +#define ERRORDURINGSWAPING 2019 +#define BINARYEXPORTNOTSUPPORTEDFOROBJECT 2020 +#define BINARYIMPORTNOTSUPPORTEDFOROBJECT 2021 +#define OPERANDSRESULTTYPESNOMATCH 2022 +#define TRYINGTOINFERHOOKFROMNULLNODE 2023 +#define QTNODETYPEPARENTDOESNOTEXIST 2024 + +#include "raslib/error.icc" + +#endif diff --git a/raslib/error.icc b/raslib/error.icc new file mode 100644 index 0000000..20aaa4f --- /dev/null +++ b/raslib/error.icc @@ -0,0 +1,74 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INLINE SOURCE: error.icc + * + * MODULE: raslib + * CLASS: r_Error + * + * COMMENTS: + * +*/ + + +inline r_Error::kind +r_Error::get_kind() const +{ + return theKind; +} + + + +inline unsigned int +r_Error::get_errorno() const +{ + return errorNo; +} + + + +inline unsigned int +r_Equery_execution_failed::get_lineno() const +{ + return lineNo; +} + + + +inline unsigned int +r_Equery_execution_failed::get_columnno() const +{ + return columnNo; +} + + + +inline const char* +r_Equery_execution_failed::get_token() const +{ + return token; +} + + + + diff --git a/raslib/flatbasetype.cc b/raslib/flatbasetype.cc new file mode 100644 index 0000000..13adbd3 --- /dev/null +++ b/raslib/flatbasetype.cc @@ -0,0 +1,301 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: flatbasetype.cc + * + * MODULE: raslib + * CLASS: r_Flat_Base_Type + * + * COMMENTS: + * +*/ + +#include <iostream> +#include <stdio.h> + +#include "raslib/primitivetype.hh" +#include "raslib/structuretype.hh" +#include "raslib/flatbasetype.hh" +#include "raslib/error.hh" +#include "raslib/rminit.hh" + + +r_Flat_Base_Type::r_Flat_Base_Type( void ) +{ + init_shared(); +} + + +r_Flat_Base_Type::r_Flat_Base_Type( const r_Base_Type *type ) +{ + init_shared(); + process_type(type); +} + + +r_Flat_Base_Type::r_Flat_Base_Type( const r_Flat_Base_Type &src ) +{ + init_shared(); + copy_flat_type(src); +} + + +r_Flat_Base_Type::~r_Flat_Base_Type( void ) +{ + free_type_data(); +} + + +unsigned int r_Flat_Base_Type::get_num_types( void ) const +{ + return numPrimTypes; +} + + +const r_Primitive_Type *r_Flat_Base_Type::type( unsigned int num ) const throw (r_Eindex_violation) +{ + if (num < numPrimTypes) + { + return primTypes[num]; + } + else { + RMInit::logOut << "r_Flat_Base_Type::type(" << num << ") index out of bounds (" << numPrimTypes - 1 << ")" << endl; + throw r_Eindex_violation(0, numPrimTypes - 1, num); + } +} + + +const r_Primitive_Type *r_Flat_Base_Type::operator[]( unsigned int num ) const throw (r_Eindex_violation) +{ + if (num < numPrimTypes) + { + return primTypes[num]; + } + else { + RMInit::logOut << "r_Flat_Base_Type::operator[](" << num << ") index out of bounds (" << numPrimTypes - 1 << ")" << endl; + throw r_Eindex_violation(0, numPrimTypes - 1, num); + } +} + + +unsigned int r_Flat_Base_Type::offset( unsigned int num ) const throw (r_Eindex_violation) +{ + if (num < numPrimTypes) + { + return offsets[num]; + } + else { + RMInit::logOut << "r_Flat_Base_Type::offset(" << num << ") index out of bounds (" << numPrimTypes - 1 << ")" << endl; + throw r_Eindex_violation(0, numPrimTypes - 1, num); + } +} + + +r_Bytes r_Flat_Base_Type::size( void ) const +{ + return typeSize; +} + + +r_Flat_Base_Type &r_Flat_Base_Type::operator=( const r_Flat_Base_Type &src ) +{ + free_type_data(); + copy_flat_type(src); + return (*this); +} + + +r_Flat_Base_Type &r_Flat_Base_Type::operator=( const r_Base_Type *type ) +{ + free_type_data(); + process_type(type); + return (*this); +} + + +bool r_Flat_Base_Type::operator==( const r_Flat_Base_Type &src ) const +{ + if (numPrimTypes == src.numPrimTypes) + { + unsigned int i; + for (i=0; i<numPrimTypes; i++) + { + if (primTypes[i]->type_id() != src.primTypes[i]->type_id()) + break; + } + if (i >= numPrimTypes) + return true; + } + return false; +} + + +void r_Flat_Base_Type::init_shared( void ) +{ + typeSize = 0; + numPrimTypes = 0; + primTypes = NULL; + offsets = NULL; +} + + +void r_Flat_Base_Type::free_type_data( void ) +{ + if (primTypes != NULL) + { + for (unsigned int i=0; i<numPrimTypes; i++) + delete primTypes[i]; + delete [] primTypes; + primTypes = NULL; + } + + if (offsets != NULL) + { + delete [] offsets; + offsets = NULL; + } + numPrimTypes = 0; +} + + +void r_Flat_Base_Type::process_type( const r_Base_Type *type ) +{ + typeSize = type->size(); + + if (type->isStructType()) + { + const r_Structure_Type *stype = (const r_Structure_Type*)type; + numPrimTypes = parse_structure_type(stype, 0, 0); + primTypes = new r_Primitive_Type*[numPrimTypes]; + offsets = new unsigned int[numPrimTypes]; + parse_structure_type(stype, 0, 0); + } + else + { + numPrimTypes = 1; + primTypes = new r_Primitive_Type*[1]; + offsets = new unsigned int[1]; + parse_primitive_type((r_Primitive_Type*)(type->clone()), 0, 0); + } +} + + +void r_Flat_Base_Type::copy_flat_type( const r_Flat_Base_Type &src ) +{ + typeSize = src.typeSize; + + if (src.numPrimTypes == 0) + { + numPrimTypes = 0; + primTypes = NULL; + offsets = NULL; + } + else + { + numPrimTypes = src.numPrimTypes; + primTypes = new r_Primitive_Type*[numPrimTypes]; + offsets = new unsigned int[numPrimTypes]; + for (unsigned int i=0; i<numPrimTypes; i++) + { + primTypes[i] = (r_Primitive_Type*)(src.primTypes[i]->clone()); + offsets[i] = src.offsets[i]; + } + } +} + + +void r_Flat_Base_Type::parse_primitive_type( r_Primitive_Type *type, unsigned int num, unsigned int off ) +{ + if (primTypes == NULL) + { + delete type; + } + else + { + primTypes[num] = type; + offsets[num] = off; + //cout << "TYPE "; type->print_status(); cout << ", NUM " << num << ", OFF " << off << endl; + } +} + + +unsigned int r_Flat_Base_Type::parse_structure_type( const r_Structure_Type *type, unsigned int num, unsigned int off ) +{ + r_Structure_Type::attribute_iterator iter(type->defines_attribute_begin()); + unsigned int numPrim = 0; + + while (iter != type->defines_attribute_end()) + { + r_Type *newType = (*iter).type_of().clone(); + if (newType->isStructType()) + { + numPrim += parse_structure_type((const r_Structure_Type*)newType, num + numPrim, off + (*iter).offset()); + delete newType; + } + else + { + parse_primitive_type((r_Primitive_Type*)newType, num + numPrim, off + (*iter).offset()); + numPrim++; + } + iter++; + } + + return numPrim; +} + + +void r_Flat_Base_Type::print_status( std::ostream &str ) const +{ + if (numPrimTypes == 0) + { + str << "<nn>"; + } + else + { + str << typeSize << ':'; + if (numPrimTypes == 1) + { + primTypes[0]->print_status(str); + } + else + { + unsigned int i; + str << '{'; primTypes[0]->print_status(str); str << '(' << offsets[0] << ')'; + for (i=1; i<numPrimTypes; i++) + { + str << ", "; + primTypes[i]->print_status(str); + str << '(' << offsets[i] << ')'; + } + str << '}'; + } + } +} + + + +std::ostream &operator<<( std::ostream &str, const r_Flat_Base_Type &type ) +{ + type.print_status(str); + return str; +} diff --git a/raslib/flatbasetype.hh b/raslib/flatbasetype.hh new file mode 100644 index 0000000..c92b4b1 --- /dev/null +++ b/raslib/flatbasetype.hh @@ -0,0 +1,123 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: flatbasetype.hh + * + * MODULE: raslib + * CLASS: r_Flat_Base_Type + * + * COMMENTS: + * +*/ + +#ifndef _FLAT_BASE_TYPE_HH_ +#define _FLAT_BASE_TYPE_HH_ + +#include <iostream> + +#include "raslib/error.hh" + +class r_Base_Type; +class r_Primitive_Type; +class r_Structure_Type; + +//@ManMemo: Module {\bf raslib} + + +/*@Doc: + This class can be used to get a more convenient view on a structured + base type. It eliminates all hierarchies and gives you the primitive + types only which can be iterated over with a normal linear loop. Used + in e.g. the compression module. Note that this is not a regular member + of the r_Type hierarchy! +*/ + +class r_Flat_Base_Type +{ + public: + /// default constructor, shouldn't be used + r_Flat_Base_Type( void ); + /// constructor receiving the (hierarchical) base type + r_Flat_Base_Type( const r_Base_Type *type ); + /// copy constructor + r_Flat_Base_Type( const r_Flat_Base_Type &src ); + /// destructor + ~r_Flat_Base_Type( void ); + + /// return number of primitive types + unsigned int get_num_types( void ) const; + /// return pointer to primitive type num + /// index violation is thrown if higher index is requested than available + const r_Primitive_Type *type( unsigned int num ) const throw (r_Eindex_violation); + /// operator returns pointer to primitive type num or NULL if invalid + /// index violation is thrown if higher index is requested than available + const r_Primitive_Type *operator[]( unsigned int num ) const throw (r_Eindex_violation); + /// return offset of primitive type num + /// index violation is thrown if higher index is requested than available + unsigned int offset( unsigned int num ) const throw (r_Eindex_violation); + /// return size of entire type + r_Bytes size( void ) const; + /// assignment of another flat type + r_Flat_Base_Type &operator=( const r_Flat_Base_Type &src ); + /// assignment of a base type + r_Flat_Base_Type &operator=( const r_Base_Type *type ); + /// equality + bool operator==( const r_Flat_Base_Type &src ) const; + /// print status to a stream + void print_status( std::ostream &str ) const; + + + protected: + /// shared init code + void init_shared( void ); + /// process a base type + void process_type( const r_Base_Type *type ); + /// copy another flat type + void copy_flat_type( const r_Flat_Base_Type &type ); + /// free type-specific data (destructor, assignment) + void free_type_data( void ); + + /// parse a structure type and return number of primitive types contained therein + unsigned int parse_structure_type( const r_Structure_Type *type, unsigned int number, + unsigned int offset ); + /// parse a primitive type + void parse_primitive_type( r_Primitive_Type *type, unsigned int number, + unsigned int offset ); + + /// the number of primitive types + unsigned int numPrimTypes; + /// the total size of the entire type + r_Bytes typeSize; + /// the primitive types + r_Primitive_Type **primTypes; + /// the corresponding offsets + unsigned int *offsets; +}; + + +//@ManMemo: Module {\bf raslib} + +//@Doc: write the status of a flat base type to a stream +extern std::ostream &operator<<( std::ostream &str, const r_Flat_Base_Type &type ); + +#endif diff --git a/raslib/itertype.cc b/raslib/itertype.cc new file mode 100644 index 0000000..c277c24 --- /dev/null +++ b/raslib/itertype.cc @@ -0,0 +1,97 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +#include "raslib/itertype.hh" +#include <stdlib.h> + +template<class T> +r_IterType<T>::r_IterType() : lastElem(NULL), myElems(NULL), currPos(0) +{ +} + +template<class T> +r_IterType<T>::r_IterType(T* newLastElem, T* newElems) + : lastElem(newLastElem), myElems(newElems), currPos(newElems) +{ +} + +template<class T> +r_IterType<T>::r_IterType(T* newLastElem, T* newElems, T* newCurrPos) + : lastElem(newLastElem), myElems(newElems), currPos(newCurrPos) +{ +} + +template<class T> +r_IterType<T>::r_IterType( const r_IterType<T>& iter ) + : lastElem(iter.lastElem), myElems(iter.myElems), currPos(iter.currPos) +{ +} + +template<class T> +r_IterType<T>::~r_IterType() +{ + // nothing to do, memory management is done by r_Attribute. +} + +template<class T> r_IterType<T>& +r_IterType<T>::operator=( const r_IterType<T>& iter ) +{ + lastElem = iter.lastElem; + myElems = iter.myElems; + currPos = iter.currPos; + return *this; +} + +template<class T> bool +r_IterType<T>::operator==( const r_IterType<T>& otherIter ) +{ + return currPos == otherIter.currPos; +} + +template<class T> bool +r_IterType<T>::operator!=( const r_IterType<T>& otherIter ) +{ + return currPos != otherIter.currPos; +} + +template<class T> r_IterType<T>& +r_IterType<T>::operator++() +{ + currPos++; + return *this; +} + +template<class T> r_IterType<T> +r_IterType<T>::operator++( int ) +{ + r_IterType<T> result( *this ); + operator++(); + return result; +} + +template<class T> T +r_IterType<T>::operator*() +{ + return *currPos; +} + diff --git a/raslib/itertype.hh b/raslib/itertype.hh new file mode 100644 index 0000000..daabc0f --- /dev/null +++ b/raslib/itertype.hh @@ -0,0 +1,86 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: itertype.hh + * + * MODULE: raslib + * CLASS: r_IterType + * + * COMMENTS: + * +*/ + +#ifndef _D_ITER_TYPE_ +#define _D_ITER_TYPE_ + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + This class realizes the iterator used to access + single elements of \Ref{r_Structure_Type}. +*/ + +template <class T> +class r_IterType +{ +public: + /// default constructor + r_IterType(); + /// constructor used in r_Structure_Type + r_IterType( T* newLastElem, T* newElems ); + /// constructor used in r_Structure_Type + r_IterType( T* newLastElem, T* newElems, T* newCurrPos ); + /// copy constructor + r_IterType( const r_IterType<T>& iter ); + /// destructor + ~r_IterType(); + /// assignment operator + r_IterType<T>& operator=( const r_IterType<T>& iter ); + /// equal comparison: equal if they point to the same element. + bool operator==( const r_IterType<T>& otherIter ); + /// no equal comparison: not equal if they point to different elements + bool operator!=( const r_IterType<T>& otherIter ); + /// prefix incrementor + r_IterType<T>& operator++(); + /// postfix incrementor + r_IterType<T> operator++( int ); + /// the dereference operator gets the actual element + T operator*(); + +protected: + T* lastElem; + T* myElems; + T* currPos; +}; + +#ifdef EARLY_TEMPLATE +#ifdef __EXECUTABLE__ +#ifdef __VISUALC__ +#include "itertype.cpp" +#else +#include "itertype.cc" +#endif +#endif +#endif + +#endif diff --git a/raslib/marraytype.cc b/raslib/marraytype.cc new file mode 100644 index 0000000..ace70aa --- /dev/null +++ b/raslib/marraytype.cc @@ -0,0 +1,131 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +static const char rcsid[] = "@(#)raslib, r_Marray_Type: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/marraytype.cc,v 1.7 2003/12/27 23:01:21 rasdev Exp $"; + +#include "raslib/marraytype.hh" +#include "raslib/basetype.hh" +#include "raslib/error.hh" +#include "raslib/rminit.hh" + +r_Marray_Type::r_Marray_Type() + : r_Type(), + baseType(NULL) + { + } + +r_Marray_Type::r_Marray_Type(const r_Base_Type& newBaseType) + : r_Type(), + baseType((r_Base_Type*)newBaseType.clone()) + { + } + +r_Marray_Type::r_Marray_Type(const r_Marray_Type& oldObj) throw (r_Error) + : r_Type(oldObj) + { + if (oldObj.baseType) + baseType = (r_Base_Type*)oldObj.baseType->clone(); + else { + RMInit::logOut << "r_Marray_Type::r_Marray_Type( oldObj ) the element type is NULL." << endl; + throw r_Error(MARRAYTYPEHASNOELEMENTTYPE); + } + } + +const r_Marray_Type& +r_Marray_Type::operator=(const r_Marray_Type& oldObj) throw (r_Error) + { + // Gracefully handle self assignment + if (this == &oldObj) + return *this; + + r_Type::operator=(oldObj); + if (baseType) + { + delete baseType; + baseType = 0; + } + + if (oldObj.baseType) + baseType = (r_Base_Type*)oldObj.baseType->clone(); + else { + RMInit::logOut << "r_Marray_Type::operator=( oldObj ) the element type is NULL." << endl; + throw r_Error(MARRAYTYPEHASNOELEMENTTYPE); + } + + return *this; + } + +bool +r_Marray_Type::isMarrayType() const + { + return true; + } + +const r_Base_Type& +r_Marray_Type::base_type() const + { + return *baseType; + } + +r_Type* +r_Marray_Type::clone() const + { + return new r_Marray_Type(*this); + } + +r_Type::r_Type_Id +r_Marray_Type::type_id() const + { + return MARRAYTYPE; + } + +void +r_Marray_Type::convertToLittleEndian(char* cells, r_Area noCells) const + { + } + +void +r_Marray_Type::convertToBigEndian(char* cells, r_Area noCells) const + { + } + +void +r_Marray_Type::print_status(std::ostream& s) const + { + s << "marray< "; + baseType->print_status(s); + s << " >"; + } + +r_Marray_Type::~r_Marray_Type() + { + if (baseType) + delete baseType; + } + +std::ostream &operator<<( std::ostream &str, const r_Marray_Type &type ) +{ + type.print_status(str); + return str; +} +
\ No newline at end of file diff --git a/raslib/marraytype.hh b/raslib/marraytype.hh new file mode 100644 index 0000000..9876acf --- /dev/null +++ b/raslib/marraytype.hh @@ -0,0 +1,101 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: marraytype.hh + * + * MODULE: raslib + * CLASS: r_Marray_Type + * + * COMMENTS: + * +*/ + +#ifndef _D_MARRAY_TYPE_ +#define _D_MARRAY_TYPE_ + +#include "raslib/type.hh" + +class r_Base_Type; +class r_Error; + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + This class represents the marray type in the ODMG conformant + representation of the RasDaMan type system. +*/ + + +class r_Marray_Type : public r_Type + { + public: + /// constructor getting basetype + r_Marray_Type(const r_Base_Type&); + + /// copy constructor + /// if base type is NULL an exception will be raised. + /// this is possible + r_Marray_Type(const r_Marray_Type&) throw (r_Error); + + /// assignment operator + /// if base type is NULL an exception will be raised. + /// this is possible + const r_Marray_Type& operator=(const r_Marray_Type&) throw (r_Error); + + bool isMarrayType() const; + + /// get base type + const r_Base_Type& base_type() const; + + /// clone operation + virtual r_Type* clone() const; + + /// retrieve id of the type. + virtual r_Type::r_Type_Id type_id() const; + + /// converts array of cells from NT byte order to Unix byte order. + virtual void convertToLittleEndian(char* cells, r_Area noCells) const; + + /// converts array of cells from Unix byte order to NT byte order. + virtual void convertToBigEndian(char* cells, r_Area noCells) const; + + /// writes state of object to specified stream + virtual void print_status(std::ostream& s = std::cout) const; + + /// destructor + ~r_Marray_Type(); + + protected: + /// default constructor + /// should be used by noone + r_Marray_Type(); + + /// base type + r_Base_Type* baseType; + }; + +//@Doc: write the status of a marray type to a stream +extern std::ostream &operator<<( std::ostream &str, const r_Marray_Type &type ); + +#endif + diff --git a/raslib/mddtypes.cc b/raslib/mddtypes.cc new file mode 100644 index 0000000..4d7ec39 --- /dev/null +++ b/raslib/mddtypes.cc @@ -0,0 +1,416 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * SOURCE: mddtypes.cc + * + * MODULE: raslib + * CLASS: + * + * COMMENTS: + * +*/ + + +static const char rcsid[] = "@(#)raslib, mddtypes: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/mddtypes.cc,v 1.26 2005/09/03 20:33:10 rasdev Exp $"; + + + +#ifdef AIX + #include <strings.h> +#else + #include <string.h> +#endif + +#include "raslib/mddtypes.hh" +#include "raslib/rminit.hh" + + +/* + * The names of all data formats + */ +const char *format_name_array = "Array"; +const char *format_name_tiff = "TIFF"; +const char *format_name_jpeg = "JPEG"; +const char *format_name_hdf = "HDF"; +const char *format_name_cvs = "CVS"; +const char *format_name_png = "PNG"; +const char *format_name_zlib = "ZLib"; +const char *format_name_auto_compression = "AutoCompression"; +const char *format_name_bmp = "BMP"; +const char *format_name_ppm = "PPM"; +const char *format_name_rle = "RLE"; +const char *format_name_wavelet_haar = "HaarWavelet"; +const char *format_name_wavelet_daubechies = "DaubechiesWavelet"; +const char *format_name_sep_zlib = "SepZLib"; +const char *format_name_sep_rle = "SepRLE"; +const char *format_name_wavelet_daub6 = "Daubechies6Wavelet"; +const char *format_name_wavelet_daub8 = "Daubechies8Wavelet"; +const char *format_name_wavelet_daub10 = "Daubechies10Wavelet"; +const char *format_name_wavelet_daub12 = "Daubechies12Wavelet"; +const char *format_name_wavelet_daub14 = "Daubechies14Wavelet"; +const char *format_name_wavelet_daub16 = "Daubechies16Wavelet"; +const char *format_name_wavelet_daub18 = "Daubechies18Wavelet"; +const char *format_name_wavelet_daub20 = "Daubechies20Wavelet"; +const char *format_name_wavelet_least8 = "LeastAsym8Wavelet"; +const char *format_name_wavelet_least10 = "LeastAsym10Wavelet"; +const char *format_name_wavelet_least12 = "LeastAsym12Wavelet"; +const char *format_name_wavelet_least14 = "LeastAsym14Wavelet"; +const char *format_name_wavelet_least16 = "LeastAsym16Wavelet"; +const char *format_name_wavelet_least18 = "LeastAsym18Wavelet"; +const char *format_name_wavelet_least20 = "LeastAsym20Wavelet"; +const char *format_name_wavelet_coiflet6 = "Coiflet6Wavelet"; +const char *format_name_wavelet_coiflet12 = "Coiflet12Wavelet"; +const char *format_name_wavelet_coiflet18 = "Coiflet18Wavelet"; +const char *format_name_wavelet_coiflet24 = "Coiflet24Wavelet"; +const char *format_name_wavelet_coiflet30 = "Coiflet30Wavelet"; +const char *format_name_vff = "VFF"; +const char *format_name_wavelet_qhaar = "QHaarWavelet"; +const char *format_name_tor = "TOR"; +const char *format_name_dem = "DEM"; +const char *format_name_pack_bits = "PACKBITS"; +const char *format_name_ecw = "ECW"; +const char *format_name_tmc = "TMC"; +const char *format_name_ntf = "NTF"; + +const char *all_data_format_names[r_Data_Format_NUMBER] = { + format_name_array, + format_name_tiff, + format_name_jpeg, + format_name_cvs, + format_name_hdf, + format_name_png, + format_name_zlib, + format_name_auto_compression, + format_name_bmp, + format_name_rle, + format_name_wavelet_haar, + format_name_wavelet_daubechies, + format_name_sep_zlib, + format_name_sep_rle, + format_name_wavelet_daub6, + format_name_wavelet_daub8, + format_name_wavelet_daub10, + format_name_wavelet_daub12, + format_name_wavelet_daub14, + format_name_wavelet_daub16, + format_name_wavelet_daub18, + format_name_wavelet_daub20, + format_name_wavelet_least8, + format_name_wavelet_least10, + format_name_wavelet_least12, + format_name_wavelet_least14, + format_name_wavelet_least16, + format_name_wavelet_least18, + format_name_wavelet_least20, + format_name_wavelet_coiflet6, + format_name_wavelet_coiflet12, + format_name_wavelet_coiflet18, + format_name_wavelet_coiflet24, + format_name_wavelet_coiflet30, + format_name_vff, + format_name_wavelet_qhaar, + format_name_ppm, + format_name_tor, + format_name_dem, + format_name_pack_bits, + format_name_ecw, + format_name_tmc, + format_name_ntf +}; + + +const char *get_name_from_data_format( r_Data_Format fmt ) +{ + unsigned int idx = (unsigned int)fmt; + + if (idx >= (unsigned int)r_Data_Format_NUMBER) + return "???"; + + return all_data_format_names[idx]; +} + + +r_Data_Format get_data_format_from_name( const char *name ) +{ + if(!name) { + RMInit::logOut << "get_data_format_from_name(" << (name?name: "NULL") << ")" << endl; + return r_Data_Format_NUMBER; + } + + unsigned int i=r_Data_Format_NUMBER; + + for (i=0; i<(unsigned int)r_Data_Format_NUMBER; i++) + { + if (strcasecmp(name, all_data_format_names[i]) == 0) + break; + } + return (r_Data_Format)i; +} + + + +std::ostream& operator<<( std::ostream& s, r_Data_Format& d ) +{ + s << (const r_Data_Format)d; + return s; +} + +std::ostream& operator<<( std::ostream& s, const r_Data_Format& d ) +{ + s << get_name_from_data_format(d); + + return s; +} + +const char* scale_function_name_subsampling = "subsampling"; +const char* scale_function_name_bitaggregation = "bitaggregation"; + +const char* all_scale_function_names[r_Scale_Function_NUMBER] = { + scale_function_name_subsampling, + scale_function_name_bitaggregation + }; + +const char *get_name_from_scale_function(r_Scale_Function fmt) +{ + unsigned int idx = (unsigned int)fmt; + + if (idx >= (unsigned int)r_Scale_Function_NUMBER) + return "???"; + + return all_scale_function_names[idx]; +} + + +r_Scale_Function get_scale_function_from_name(const char *name) +{ + if(!name) { + RMInit::logOut << "get_scale_function_from_name(" << (name?name: "NULL") << ")" << endl; + return r_Scale_Function_NUMBER; + } + + unsigned int i=r_Scale_Function_NUMBER; + + for (i=0; i<(unsigned int)r_Scale_Function_NUMBER; i++) + { + if (strcasecmp(name, all_scale_function_names[i]) == 0) + break; + } + return (r_Scale_Function)i; +} + +std::ostream& operator<<( std::ostream& s, const r_Scale_Function& d ) +{ + s << get_name_from_scale_function(d); + + return s; +} + +/* + * The names of all index type + */ + +const char *index_name_auto="auto"; +const char *index_name_directory="dir"; +const char *index_name_regdirectory="rdir"; +const char *index_name_rplustree="nrp"; +const char *index_name_regrplustree="rnrp"; +const char *index_name_tilecontainer="tc"; +const char *index_name_regcomputed="rc"; + +const char *all_index_type_names[r_Index_Type_NUMBER] = { + index_name_auto, + index_name_directory, + index_name_regdirectory, + index_name_rplustree, + index_name_regrplustree, + index_name_tilecontainer, + index_name_regcomputed + }; + +const char *get_name_from_index_type( r_Index_Type it ) +{ + unsigned int idx = (unsigned int)it; + + if (idx >= (unsigned int)r_Index_Type_NUMBER) + return "UNKNOWN r_Index_Type"; + + if (idx == (unsigned int)r_Invalid_Index) + return "r_Invalid_Index"; + + return all_index_type_names[idx]; +} + +r_Index_Type get_index_type_from_name( const char *name ) +{ + if(!name) { + RMInit::logOut << "get_index_type_from_name(" << (name?name: "NULL") << ")" << endl; + return r_Index_Type_NUMBER; + } + + unsigned int i=r_Index_Type_NUMBER; + + for (i=0; i<(unsigned int)r_Index_Type_NUMBER; i++) + { + if (strcasecmp(name, all_index_type_names[i]) == 0) + break; + } + return (r_Index_Type)i; +} + + +std::ostream& operator<<( std::ostream& s, r_Index_Type d ) +{ + switch( d ) + { + case r_Invalid_Index: + s << "r_Invalid_Index"; + break; + case r_Auto_Index: + s << "r_Auto_Index"; + break; + case r_Directory_Index: + s << "r_Directory_Index"; + break; + case r_Reg_Directory_Index: + s << "r_Reg_Directory_Index"; + break; + case r_RPlus_Tree_Index: + s << "r_RPlus_Tree_Index"; + break; + case r_Reg_RPlus_Tree_Index: + s << "r_Reg_RPlus_Tree_Index"; + break; + case r_Tile_Container_Index: + s << "r_Tile_Container_Index"; + break; + case r_Reg_Computed_Index: + s << "r_Reg_Computed_Index"; + break; + default: + s << "UNKNOWN r_Index_Type " << d; + break; + } + + return s; +} + +/* + * The names of all tiling schemes + */ + +const char *tiling_name_notiling = "NoTiling"; +const char *tiling_name_regulartiling = "RegularTiling"; +const char *tiling_name_statisticaltiling = "StatisticalTiling"; +const char *tiling_name_interesttiling = "InterestTiling"; +const char *tiling_name_alignedtiling = "AlignedTiling"; +const char *tiling_name_directionaltiling = "DirectionalTiling"; +const char *tiling_name_sizetiling = "SizeTiling"; + +const char *all_tiling_scheme_names[r_Tiling_Scheme_NUMBER] = { + tiling_name_notiling, + tiling_name_regulartiling, + tiling_name_statisticaltiling, + tiling_name_interesttiling, + tiling_name_alignedtiling, + tiling_name_directionaltiling, + tiling_name_sizetiling + }; + +const char *get_name_from_tiling_scheme( r_Tiling_Scheme ts ) +{ + unsigned int idx = (unsigned int)ts; + + if (idx >= (unsigned int)r_Tiling_Scheme_NUMBER) + return "UNKNOWN r_Tiling_Scheme"; + + return all_tiling_scheme_names[idx]; +} + +r_Tiling_Scheme get_tiling_scheme_from_name( const char *name ) +{ + if(!name) { + RMInit::logOut << "get_tiling_scheme_from_name(" << (name?name: "NULL") << ")" << endl; + return r_Tiling_Scheme_NUMBER; + } + + unsigned int i=r_Tiling_Scheme_NUMBER; + + for (i=0; i<(unsigned int)r_Tiling_Scheme_NUMBER; i++) + { + if (strcasecmp(name, all_tiling_scheme_names[i]) == 0) + break; + } + return (r_Tiling_Scheme)i; +} + +std::ostream& operator<<(std::ostream& s, r_Tiling_Scheme d) +{ + s << get_name_from_tiling_scheme(d); + return s; +} + +std::ostream& operator<<( std::ostream& s, const r_Clustering_Scheme d ) +{ + switch( d ) + { + case r_Insertion_Order_Clustering: + s << "r_Insertion_Order_Clustering"; + break; + case r_Coords_Order_Clustering: + s << "r_Coords_Order_Clustering"; + break; + case r_Index_Cluster_Clustering: + s << "r_Index_Cluster_Clustering"; + break; + case r_Based_Cluster_Stat_Clustering: + s << "r_Based_Cluster_Stat_Clustering"; + break; + default: + s << "UNKNOWN r_Clustering_Scheme " << d; + break; + } + + return s; +} + + +#ifdef __VISUALC__ +#include <ctype.h> +int strcasecmp(const char *s1, const char *s2) +{ + const char *b, *d; + + b = s1; d = s2; + while ((*b != '\0') && (*d != '\0')) + { + if (tolower((unsigned int)*b) != tolower((unsigned int)*d)) + break; + b++; d++; + } + if ((*b == '\0') && (*d == '\0')) + return 0; + if (tolower((unsigned int)*b) < tolower((unsigned int)*d)) + return -1; + return 1; +} +#endif diff --git a/raslib/mddtypes.hh b/raslib/mddtypes.hh new file mode 100644 index 0000000..f8fb310 --- /dev/null +++ b/raslib/mddtypes.hh @@ -0,0 +1,491 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: mddtypes.hh + * + * MODULE: raslib + * + * PURPOSE: + * The file cotains MDD type definitions. + * + * COMMENTS: + * - always append new data formats to remain compatible with earlier compiled code + * +*/ + +#ifndef _D_MDDTYPES_ +#define _D_MDDTYPES_ + + +#ifdef __VISUALC__ +#include <strstrea.h> +#else +#include <sstream> +#endif + +//typedef unsigned int uint32; +//typedef int int32; + +//@Man: r_Bytes +//@Type: typedef +//@Args: as unsigned int +//@Memo: Module: {\bf raslib}. + +typedef unsigned int r_Bytes; + +/** + {\tt typedef unsigned int r_Bytes;} + + The typedef \Ref{r_Bytes} is used as type for the number of bytes in an tile or mdd or type. +*/ + +//@Man: r_Ptr +//@Type: typedef +//@Args: as unsigned long +//@Memo: Module: {\bf raslib}. + +typedef unsigned long r_Ptr; + +/** + {\tt typedef unsigned long r_Ptr;} + + The typedef \Ref{r_Ptr} was introduced to handle correctly convertions from + pointers to integer variables on 64bit architectures. +*/ + + + +//@Man: r_Area +//@Type: typedef +//@Args: as unsigned int +//@Memo: Module: {\bf raslib}. + +typedef unsigned int r_Area; + +/** + {\tt typedef unsigned int r_Area;} + + The typedef \Ref{r_Area} is used as type for the number of cells in an mdd object or tile. +*/ + + + +//@Man: r_Range +//@Type: typedef +//@Args: as int +//@Memo: Module: {\bf raslib}. + +typedef int r_Range; + +/** + {\tt typedef int r_Range;} + + The typedef \Ref{r_Range} is used as type for the point set + of one dimension of a spatial domain. This means that lower + and upper bounds of \Ref{r_Sinterval}, the projection value, + and the cooridnate values of \Ref{r_Point} are of this type. +*/ + + + +//@Man: r_Dimension +//@Type: typedef +//@Args: as unsigned int +//@Memo: Module: {\bf raslib}. + +typedef unsigned int r_Dimension; + +/** + {\tt typedef unsigned int r_Dimension;} + + This is used as type for the number of dimensions in + \Ref{r_Point} and \Ref{r_Minterval}. +*/ + + +//@Man: r_Data_Format +//@Type: enum +//@Args: +//@Memo: Module: {\bf raslib}. + +enum r_Data_Format +{ + r_Array, + r_TIFF, + r_JPEG, + r_HDF, + r_CSV, + r_PNG, + r_ZLib, + r_Auto_Compression, + r_BMP, + r_RLE, + r_Wavelet_Haar, + r_Wavelet_Daubechies, // = Daubechies 4 tap + r_Sep_ZLib, + r_Sep_RLE, + r_Wavelet_Daub6, + r_Wavelet_Daub8, + r_Wavelet_Daub10, + r_Wavelet_Daub12, + r_Wavelet_Daub14, + r_Wavelet_Daub16, + r_Wavelet_Daub18, + r_Wavelet_Daub20, + r_Wavelet_Least8, + r_Wavelet_Least10, + r_Wavelet_Least12, + r_Wavelet_Least14, + r_Wavelet_Least16, + r_Wavelet_Least18, + r_Wavelet_Least20, + r_Wavelet_Coiflet6, + r_Wavelet_Coiflet12, + r_Wavelet_Coiflet18, + r_Wavelet_Coiflet24, + r_Wavelet_Coiflet30, + r_VFF, + r_Wavelet_QHaar, + r_PPM, + r_TOR, + r_DEM, + r_Pack_Bits, + r_ECW, + r_TMC, + r_NTF, + r_Data_Format_NUMBER +}; + +/** + {\tt enum r_Data_Format} + + \begin{tabular}{lll} + {\ttr_Array} && no compression, row-major memory representation\\ + + {\ttr_TIFF} && TIFF format (see \Ref{r_Conv_TIFF})\\ + {\ttr_JPEG} && JPEG format (see \Ref{r_Conv_JPEG})\\ + {\ttr_HDF} && HDF format (see \Ref{r_Conv_HDF})\\ + {\ttr_PNG} && PNG format (see \Ref{r_Conv_PNG})\\ + {\ttr_BMP} && BMP format (see \Ref{r_Conv_BMP})\\ + {\ttr_VFF} && VFF format (see \Ref{r_Conv_VFF})\\ + {\ttr_PPM} && PPM format (see \Ref{r_Conv_PPM})\\ + {\ttr_TOR} && TOR format (see \Ref{r_Conv_TOR})\\ + {\ttr_DEM} && DEM format (see \Ref{r_Conv_DEM})\\ + {\ttr_ECW} && ECW format (see \Ref{r_Conv_ECW})\\ + {\ttr_NTF} && NITF format (see \Ref{r_Conv_NTF})\\ + + {\ttr_Auto_Compression} && automatic compression\\ + {\ttr_ZLib} && ZLIB compresion (see \Ref{r_Tile_Comp_RLE})\\ + {\ttr_Pack_Bits} && Packbits rle compresion (see \Ref{r_Tile_Comp_Packbits})\\ + {\ttr RLE} && RLE compression (see \Ref{r_Tile_Comp_RLE})\\ + {\ttr_Wavelet_Haar} && Haar Wavelet compression (see \Ref{r_Haar_Wavelet_Compression})\\ + {\ttr_Wavelet_Daubechies} && Daubechies 4-tap Wavelet compression (see \Ref{r_Daubechies_Wavelet_Compression})\\ + {\ttr_Sep_ZLib} && ZLIB compression, compress base types separately (see \Ref{r_Tile_Separate_ZLIB})\\ + {\ttr_Sep_RLE} && RLE compression, compress base types separately (see \Ref{r_Tile_Separate_RLE})\\ + {\ttr_Wavelet_Daub<n>} && Daubechies n-tap Wavelet compression, n=6,8,...,18,20 (see \Ref{r_Ortho_Wavelet_Factory})\\ + {\ttr_Wavelet_Least<n>} && Least asymmetric n-tap Wavelet comp., n=8,10,...,18,20 (see \Ref{r_Ortho_Wavelet_Factory})\\ + {\ttr_Wavelet_Coiflet<n>} && Coiflet n-tap Wavelet compression, n=6,12,18,24,30 (see \Ref{r_Ortho_Wavelet_Factory})\\ + {\ttr_Wavelet_QHaar} && Lossy Haar Wavelet compression (see \Ref{r_Haar_QWavelet_Compression})\\ + + \end{tabular} +*/ + +//@ManMemo: Module: {\bf raslib} +/** + The names of all data types, to avoid redundant storage and inconsistencies. + The variable name convention is the prefix format_name_ followed by the name + of the data format in lower case without the r_ prefix, i.e. for r_Wavelet_Haar + format_name_wavelet_haar. + In addition there's an array of names all_data_format_names where the data format + can be used as index to get the name. +*/ + +extern const char *format_name_array; +extern const char *format_name_tiff; +extern const char *format_name_jpeg; +extern const char *format_name_hdf; +extern const char *format_name_png; +extern const char *format_name_zlib; +extern const char *format_name_auto_compression; +extern const char *format_name_bmp; +extern const char *format_name_ppm; +extern const char *format_name_rle; +extern const char *format_name_wavelet_haar; +extern const char *format_name_wavelet_daubechies; +extern const char *format_name_sep_zlib; +extern const char *format_name_sep_rle; +extern const char *format_name_wavelet_daub6; +extern const char *format_name_wavelet_daub8; +extern const char *format_name_wavelet_daub10; +extern const char *format_name_wavelet_daub12; +extern const char *format_name_wavelet_daub14; +extern const char *format_name_wavelet_daub16; +extern const char *format_name_wavelet_daub18; +extern const char *format_name_wavelet_daub20; +extern const char *format_name_wavelet_least8; +extern const char *format_name_wavelet_least10; +extern const char *format_name_wavelet_least12; +extern const char *format_name_wavelet_least14; +extern const char *format_name_wavelet_least16; +extern const char *format_name_wavelet_least18; +extern const char *format_name_wavelet_least20; +extern const char *format_name_wavelet_coiflet6; +extern const char *format_name_wavelet_coiflet12; +extern const char *format_name_wavelet_coiflet18; +extern const char *format_name_wavelet_coiflet24; +extern const char *format_name_wavelet_coiflet30; +extern const char *format_name_vff; +extern const char *format_name_tor; +extern const char *format_name_dem; +extern const char *format_name_pack_bits; +extern const char *format_name_wavelet_qhaar; +extern const char *format_name_tmc; +extern const char *format_name_ntf; + +extern const char *all_data_format_names[r_Data_Format_NUMBER]; + +//@ManMemo: Module: {\bf raslib} +/** + Get a data format name for a data format +*/ +const char *get_name_from_data_format( r_Data_Format fmt ); + +//@ManMemo: Module: {\bf raslib} +/** + Get a data format for a data format name +*/ +r_Data_Format get_data_format_from_name ( const char *name ); + + +//@ManMemo: Module: {\bf raslib} +/** + Output stream operator for objects of type {\tt const} \Ref{r_Data_Format}. +*/ +extern std::ostream& operator<<( std::ostream& s, const r_Data_Format& d ); + + + +//@ManMemo: Module: {\bf raslib} +/** + Output stream operator for objects of type \Ref{r_Data_Format}. +*/ +extern std::ostream& operator<<( std::ostream& s, r_Data_Format& d ); + +//@Man: r_Scale_Function +//@Type: enum +//@Args: +//@Memo: Module: {\bf raslib}. + +enum r_Scale_Function { + r_SubSampling, + r_BitAggregation, + r_Scale_Function_NUMBER + }; + +extern const char *scale_function_name_subsampling; +extern const char *scale_function_name_bitaggregation; + +extern const char *all_scale_function_names[r_Scale_Function_NUMBER]; + +//@ManMemo: Module: {\bf raslib} +/** + Get a scale function name for a scale function +*/ +const char *get_name_from_scale_function(r_Scale_Function func); + +//@ManMemo: Module: {\bf raslib} +/** + Get a scale function from a scale function name +*/ +r_Scale_Function get_scale_function_from_name(const char *name); + + +//@ManMemo: Module: {\bf raslib} +/** + Output stream operator for objects of type {\tt const} \Ref{r_Scale_Function}. +*/ +extern std::ostream& operator<<( std::ostream& s, const r_Scale_Function& d ); + + +//@Man: r_Index_Type +//@Type: enum +//@Args: +//@Memo: Module: {\bf raslib}. + +enum r_Index_Type + { + r_Invalid_Index = -1, + r_Auto_Index = 0, + r_Directory_Index = 1, + r_Reg_Directory_Index = 2, + r_RPlus_Tree_Index = 3, + r_Reg_RPlus_Tree_Index = 4, + r_Tile_Container_Index = 5, + r_Reg_Computed_Index = 6, + r_Index_Type_NUMBER = 7 + }; + +extern std::ostream& operator<<(std::ostream& in, r_Index_Type type); + +//@ManMemo: Module: {\bf raslib} +/** + The names of all index type, to avoid redundant storage and inconsistencies. + The variable name convention is the prefix index_name_ followed by the name + of the index type in lower case without the r_ prefix, i.e. for r_Auto_Index + index_name_auto. + In addition there's an array of names all_index_type_names where the index type + can be used as index to get the name. +*/ + +extern const char *index_name_auto; +extern const char *index_name_directory; +extern const char *index_name_regdirectory; +extern const char *index_name_rplustree; +extern const char *index_name_regrplustree; +extern const char *index_name_tilecontainer; +extern const char *index_name_regcomputed; + +extern const char *all_index_type_names[r_Index_Type_NUMBER]; + +//@ManMemo: Module: {\bf raslib} +/** + Get a index type name for a index type +*/ +const char *get_name_from_index_type( r_Index_Type it ); + +//@ManMemo: Module: {\bf raslib} +/** + Get a index type for a index type name +*/ +r_Index_Type get_index_type_from_name ( const char *name ); + +//@Man: r_Tiling_Scheme +//@Type: enum +//@Args: +//@Memo: Module: {\bf raslib}. + +enum r_Tiling_Scheme + { + r_NoTiling = 0, + r_RegularTiling = 1, + r_StatisticalTiling = 2, + r_InterestTiling = 3, + r_AlignedTiling = 4, + r_DirectionalTiling = 5, + r_SizeTiling = 6, + r_Tiling_Scheme_NUMBER = 7 + }; +/** + Tiling of the object: + + \begin{tabular}{lll} + NoTiling && no tiling is done unless the object is too big; + in that case, tiling is done along the first direction only; + for objects which are to be accessed always as a whole \\ + {\bf Aligned} && aligned tiling, needs tileConfig \\ + LowVariationAreas && according to areas of low cell value variation \\ + BasedTilesStat && based on statistics regarding access to this MDD object + \end{tabular} + + In addition, it is possible to have a tiling according to areas of + interest, {\bf AreasInterest} mode. + The {\tt AreasInterest} mode is indicated by a non - null value of the + {\tt areasInterestPath} attribute. + This mode is not an alternative mode in {\tt TilingScheme} because it is + compatible with the other modes. For instance, an aligned tiling may be + adopted outside the areas of interest. + */ + +//@ManMemo: Module: {\bf raslib} +/** + The names of all tiling schems, to avoid redundant storage and inconsistencies. + The variable name convention is the prefix tiling_name_ followed by the name + of the tiling scheme in lower case without the r_ prefix, i.e. for r_SizeTiling + tiling_name_sizetiling. + In addition there's an array of names all_tiling_scheme_names where the tile scheme + can be used as index to get the name. +*/ + +extern const char *tiling_name_notiling; +extern const char *tiling_name_regulartiling; +extern const char *tiling_name_statisticaltiling; +extern const char *tiling_name_interesttiling; +extern const char *tiling_name_alignedtiling; +extern const char *tiling_name_directionaltiling; +extern const char *tiling_name_sizetiling; + +extern const char *all_tiling_scheme_names[r_Tiling_Scheme_NUMBER]; + +//@ManMemo: Module: {\bf raslib} +/** + Get a tiling scheme name for a tiling scheme +*/ +const char *get_name_from_tiling_scheme( r_Tiling_Scheme ts ); + +//@ManMemo: Module: {\bf raslib} +/** + Get a tiling scheme for a tiling scheme name +*/ +r_Tiling_Scheme get_tiling_scheme_from_name ( const char *name ); + +//@ManMemo: Module: {\bf raslib} +/** + Output stream operator for objects of type {\tt const} \Ref{r_Tiling_Scheme}. +*/ +extern std::ostream& operator<<(std::ostream& in, r_Tiling_Scheme type); + +//@Man: r_Clustering_Scheme +//@Type: enum +//@Args: +//@Memo: Module: {\bf raslib}. +enum r_Clustering_Scheme + { + r_Insertion_Order_Clustering = 1, + r_Coords_Order_Clustering = 2, + r_Index_Cluster_Clustering = 3, + r_Based_Cluster_Stat_Clustering = 4 + }; + /** + Clustering of the Tiles according to: + + \begin{tabular}{lll} + {\bf InsertionOrder } && the order of insertion of the tiles \\ + CoordsOrder && the coordinates of the tiles \\ + IndexCluster && the index structure \\ + BasedClusterStat && statistics about access to the object + \end{tabular} + + There is the additional {\bf PathCluster} mode, where clustering is + done according to a path of access to areas of interest. + The {\tt PathCluster} mode is indicated by setting the {\tt pathCluster} + attribute and a non - null value of the {\tt areasInterest}. + This mode is not an alternative mode in {\tt ClusteringScheme} because + it is compatible with the other modes. + */ +extern std::ostream& operator<<(std::ostream& in, r_Clustering_Scheme type); + +#ifdef __VISUALC__ +extern int strcasecmp( const char *str1, const char *str2 ); +#endif + +#endif diff --git a/raslib/memblockvec.cc b/raslib/memblockvec.cc new file mode 100644 index 0000000..9cffc51 --- /dev/null +++ b/raslib/memblockvec.cc @@ -0,0 +1,107 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: memblockvec.cc + * + * MODULE: raslib + * CLASS: r_Memory_Block_Vector + * + * COMMENTS: + * +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "raslib/memblockvec.hh" + + +r_Memory_Block_Vector::r_Memory_Block_Vector( r_Bytes bsize, unsigned int gran ) +{ + blockSize = bsize; + granularity = gran; + + numBlocks = 0; maxBlocks = granularity; + blocks = new void*[granularity]; +} + +r_Memory_Block_Vector::~r_Memory_Block_Vector( void ) +{ + free_data(); + delete [] blocks; +} + +void* r_Memory_Block_Vector::operator[]( unsigned int idx ) const +{ + if (idx >= numBlocks) + return NULL; + + return blocks[idx]; +} + +void* r_Memory_Block_Vector::add( void ) +{ + if (numBlocks >= maxBlocks) + { + void** newBlocks = new void*[maxBlocks + granularity]; + memcpy(newBlocks, blocks, numBlocks * sizeof(void*)); + delete [] blocks; blocks = newBlocks; + maxBlocks += granularity; + } + blocks[numBlocks++] = (void*)(new char[blockSize]); + return blocks[numBlocks-1]; +} + +void r_Memory_Block_Vector::free_data( void ) +{ + unsigned int i; + + for (i=0; i<numBlocks; i++) + { + delete [] blocks[i]; + blocks[i] = NULL; + } + numBlocks = 0; +} + +r_Bytes r_Memory_Block_Vector::get_size( r_Bytes lastFill ) const +{ + return (numBlocks == 0) ? 0 : (numBlocks-1)*blockSize + lastFill; +} + +void r_Memory_Block_Vector::copy_data( void* dest, r_Bytes lastFill ) const +{ + unsigned int i; + void* destPtr = dest; + + if (numBlocks == 0) return; + + for (i=0; i<numBlocks-1; i++) + { + memcpy(destPtr, blocks[i], blockSize); + destPtr = (void*)(((char*)destPtr) + blockSize); + } + memcpy(destPtr, blocks[numBlocks-1], lastFill); +} diff --git a/raslib/memblockvec.hh b/raslib/memblockvec.hh new file mode 100644 index 0000000..c026614 --- /dev/null +++ b/raslib/memblockvec.hh @@ -0,0 +1,84 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: memblockvec.hh + * + * MODULE: raslib + * CLASS: r_Memory_Block_Vector + * + * COMMENTS: + * +*/ + +#ifndef _MEMORY_BLOCK_VECTOR_H_ +#define _MEMORY_BLOCK_VECTOR_H_ + +#include "raslib/mddtypes.hh" + + +//@ManMemo: Module {\bf raslib} + +/*@Doc: + Auxiliary class, realizes a set of memory blocks of equal size that can + be extended to any size. Used by some children of r_LinCompStream. +*/ + +class r_Memory_Block_Vector +{ +public: + /// constructor, receiving the size of each memory block and the granularity + /// for extending the number of blocks. + r_Memory_Block_Vector( r_Bytes bsize=4096, unsigned int gran=8 ); + /// destructor + ~r_Memory_Block_Vector( void ); + /// return number of blocks + inline unsigned int get_number( void ) const {return numBlocks;} + /// return block size + inline r_Bytes get_block_size( void ) const {return blockSize;} + /// return granularity + inline unsigned int get_granularity( void ) const {return granularity;} + /// get a block + void* operator[]( unsigned int idx ) const; + /// add a new block and return a pointer to it + void* add( void ); + /// free all blocks (but not the vector, call the destructor for that) + void free_data( void ); + /// get number of bytes stored. lastFill is the number of bytes used + /// in the last block + r_Bytes get_size( r_Bytes lastFill ) const; + /// Copy the data stored in blocks into linear memory. lastFill is the + /// number of bytes in the last block + void copy_data( void* dest, r_Bytes lastFill ) const; + +protected: + /// the array of memory block pointers + void** blocks; + unsigned int numBlocks; + unsigned int maxBlocks; + /// the size of the blocks + r_Bytes blockSize; + /// the granularity + unsigned int granularity; +}; + +#endif diff --git a/raslib/metaobject.cc b/raslib/metaobject.cc new file mode 100644 index 0000000..844aa48 --- /dev/null +++ b/raslib/metaobject.cc @@ -0,0 +1,81 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +#include "mymalloc/mymalloc.h" +static const char rcsid[] = "@(#)raslib, r_Meta_Object: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/metaobject.cc,v 1.7 2003/12/27 23:01:21 rasdev Exp $"; + +#include "raslib/metaobject.hh" + +#include <stdlib.h> // OSF1 has the definition for malloc here +#include <malloc.h> +#include <string.h> + +r_Meta_Object::r_Meta_Object() + : typeName(NULL) +{ +} + +r_Meta_Object::r_Meta_Object( const char* newTypeName ) +{ + typeName = (char*)mymalloc(strlen(newTypeName) + 1); + strcpy(typeName, newTypeName); +} + +r_Meta_Object::r_Meta_Object( const r_Meta_Object& oldObj ) + : typeName(NULL) +{ + if( oldObj.typeName ) + { + typeName = (char*)mymalloc(strlen(oldObj.typeName) + 1); + strcpy(typeName, oldObj.typeName); + } +} + +const r_Meta_Object& +r_Meta_Object::operator=( const r_Meta_Object& oldObj ) +{ + // Gracefully handle self assignment + if (this == &oldObj) return *this; + + free(typeName); + typeName = NULL; + if( oldObj.typeName ) + { + typeName = (char*)mymalloc(strlen(oldObj.typeName) + 1); + strcpy(typeName, oldObj.typeName); + } + + return *this; +} + +r_Meta_Object::~r_Meta_Object() +{ + if(typeName) + free(typeName); +} + +const char* +r_Meta_Object::name() const +{ + return typeName; +} diff --git a/raslib/metaobject.hh b/raslib/metaobject.hh new file mode 100644 index 0000000..634ea98 --- /dev/null +++ b/raslib/metaobject.hh @@ -0,0 +1,77 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: metaobject.hh + * + * MODULE: raslib + * CLASS: r_Meta_Object + * + * COMMENTS: + * +*/ + +#ifndef _D_META_OBJECT_ +#define _D_META_OBJECT_ + +#include <iostream> + +#ifdef __VISUALC__ +#include <strstrea.h> +#else +#include <sstream> // for istrstream +#endif + +#include "raslib/error.hh" + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + This class the superclass for all classes in the ODMG conformant + representation of the RasDaMan type system. +*/ + +class r_Meta_Object +{ +public: + /// default constructor. + r_Meta_Object(); + /// constructor getting name of type. + r_Meta_Object( const char* newTypeName ); + /// copy constructor + r_Meta_Object( const r_Meta_Object& oldObj ); + /// assignment operator. + const r_Meta_Object& operator=( const r_Meta_Object& oldObj ); + /// destructor. + virtual ~r_Meta_Object(); + + /// retrieve name of the type. + const char* name() const; + + /// writes state of object to specified stream + virtual void print_status( std::ostream& s = std::cout ) const = 0; + +protected: + char* typeName; +}; + +#endif diff --git a/raslib/minterval.cc b/raslib/minterval.cc new file mode 100644 index 0000000..311c8e9 --- /dev/null +++ b/raslib/minterval.cc @@ -0,0 +1,1055 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * SOURCE: Minterval.cc + * + * MODULE: raslib + * CLASS: r_Minterval + * + * COMMENTS: + * +*/ + +static const char rcsid[] = "@(#)raslib, r_Minterval: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/minterval.cc,v 1.54 2005/09/03 20:31:22 rasdev Exp $"; + +using namespace std; + +using namespace std; + +#include "raslib/rmdebug.hh" +#include "raslib/minterval.hh" +#include "raslib/odmgtypes.hh" +#include "raslib/dlist.hh" +#include "mymalloc/mymalloc.h" + +#include <math.h> +#include <string.h> +#include <stdlib.h> +#ifdef __VISUALC__ +#include <strstrea.h> +#else +#include <strstream> +#endif + +r_Minterval::r_Minterval(r_Dimension dim) + : dimensionality(dim), + streamInitCnt(0), + intervals(NULL) + { + RMDBGONCE(20, RMDebug::module_raslib, "r_Minterval", "r_Minterval(r_Dimension), this=" << (long)this) + intervals = new r_Sinterval[ dimensionality ]; + } + +void +r_Minterval::constructorinit(char* mIntStr) throw(r_Eno_interval) +{ + + if(!mIntStr) + { + RMInit::logOut << "r_Minterval::r_Minterval(" << (mIntStr?mIntStr:"NULL") << ")" << endl; + throw r_Eno_interval(); + } + + char* p = NULL; // for counting ',' + // for parsing the string + std::istrstream str(mIntStr, strlen(mIntStr) + 1); + char c = 0; + r_Sinterval sint; + r_Range b = 0; // bound for Sinterval + + if (intervals != NULL) + { + delete intervals; + intervals = NULL; + } + + // calculate dimensionality + p = mIntStr; + while(p = strchr(++p, ',')) + dimensionality++; + + // allocate space for intervals + intervals = new r_Sinterval[ dimensionality ]; + + // check for left bracket '[' + str >> c; + if (c != '[') + { + // error, should perhaps raise exception + dimensionality = 0; + delete[] intervals; + intervals = NULL; + RMInit::logOut << "r_Minterval::r_Minterval(" << mIntStr << "): the string doesn't have pattern [a:b,c:d]" << endl; + throw r_Eno_interval(); + } + + // for each dimension: get sinterval + for (r_Dimension i=0; i<dimensionality; i++) + { + // --- evaluate lower bound ------------------------------ + str >> c; // test read first char + if (c == '*') // low bound is '*' + sint.set_low('*'); + else // low bound must be a number + { + str.putback(c); + str >> b; // read type r_Range + if ( ! str ) // check for proper int recognition + { + RMInit::logOut << "minterval constructor failed on dim " << i << ", lo" << endl << flush; + throw r_Eno_interval(); + } + sint.set_low(b); // store lo bound + } + + // --- check for ':' between lower and upper bound ------- + str >> c; + if (c != ':') + { + // error + dimensionality = 0; + delete[] intervals; + intervals = NULL; + RMInit::logOut << "r_Minterval::r_Minterval(" << mIntStr << "): missing ':', string not like [a:b,c:d]" << endl; + throw r_Eno_interval(); + } + + // --- evaluate upper bound ------------------------------ + str >> c; + if (c == '*') + sint.set_high('*'); + else + { + str.putback(c); + str >> b; + if ( ! str ) + { + RMInit::logOut << "minterval constructor failed on dim " << i << ", hi" << endl << flush; + throw r_Eno_interval(); + } + sint.set_high(b); + } + str >> c; + + // --- next dimension needs either ',' separator or ']' end tag + if (i != dimensionality-1 && c != ',' || i == dimensionality-1 && c != ']') + { + dimensionality = 0; + delete[] intervals; + intervals = NULL; + RMInit::logOut << "r_Minterval::r_Minterval(" << mIntStr << "): missing ',' or ']', string not like [a:b,c:d]" << endl; + throw r_Eno_interval(); + } + + intervals[i] = sint; + + sint.set_interval('*','*'); + } +} + +r_Minterval::r_Minterval(char* mIntStr) throw(r_Eno_interval) + : dimensionality(1), + streamInitCnt(0), + intervals(NULL) + { + RMDBGONCE(20, RMDebug::module_raslib, "r_Minterval", "r_Minterval(char*), this=" << (long)this) + constructorinit(mIntStr); + } + +r_Minterval::r_Minterval(const char* mIntStr) throw(r_Eno_interval) + : dimensionality(1), + streamInitCnt(0), + intervals(NULL) + { + RMDBGONCE(20, RMDebug::module_raslib, "r_Minterval", "r_Minterval(char*), this=" << (long)this) + char* temp = (char*)mymalloc((1 + strlen(mIntStr)) * sizeof(char)); + strcpy(temp, mIntStr); + + try + { + constructorinit(temp); + free(temp); + } + catch(r_Error err) + { + free(temp); + throw; + } + + temp = 0; + } + +r_Minterval& +r_Minterval::operator<<(const r_Sinterval& newInterval) throw(r_Einit_overflow) + { + if (streamInitCnt >= dimensionality) + { + RMInit::logOut << "r_Minterval::operator<<(" << newInterval << ") domain is already full" << endl; + throw r_Einit_overflow(); + } + + intervals[streamInitCnt++] = newInterval; + return *this; + } + +r_Minterval& +r_Minterval::operator<<(r_Range p) throw(r_Einit_overflow) + { + if (streamInitCnt >= dimensionality) + { + RMInit::logOut << "r_Minterval::operator<<(" << p << ") domain is already full" << endl; + throw r_Einit_overflow(); + } + + intervals[streamInitCnt++] = r_Sinterval(p, p); + return *this; + } + +r_Minterval::r_Minterval() + : dimensionality(0), + streamInitCnt(0), + intervals(NULL) + { + RMDBGONCE(20, RMDebug::module_raslib, "r_Minterval", "r_Minterval(), this=" << this) + } + +//cannot use the initialise function because it will crash +r_Minterval::r_Minterval(const r_Minterval& minterval) + : dimensionality(0), + streamInitCnt(0), + intervals(NULL) + { + RMDBGONCE(20, RMDebug::module_raslib, "r_Minterval", "r_Minterval(const r_Minterval&), this=" << this) + dimensionality = minterval.dimensionality; + streamInitCnt = minterval.streamInitCnt; + if(minterval.intervals) + { + intervals = new r_Sinterval[dimensionality]; + for (r_Dimension i=0; i<dimensionality; i++) + intervals[i] = minterval[i]; + } + } + +r_Minterval::~r_Minterval() + { + RMDBGONCE(20, RMDebug::module_raslib, "r_Minterval", "~r_Minterval(), this=" << this) + r_deactivate(); + } + +void +r_Minterval::r_deactivate() + { + if (intervals) + { + delete[] intervals; + intervals = NULL; + } + } + +bool +r_Minterval::intersects_with(const r_Minterval& minterval) const + { + bool result = true; + + if (dimensionality != minterval.dimension()) + { + RMInit::logOut << "r_Minterval::intersects_with(" << minterval << ") do not share the same dimension" << endl; + return false; + } + + // none of the interval pairs are allowed to be disjoint + for (r_Dimension i=0; i<dimensionality && result; i++) + { + if (!intervals[i].intersects_with(minterval[i])) + { + result = false; + break; + } + } + + return result; + } + +#ifndef OPT_INLINE +r_Sinterval +r_Minterval::operator[](r_Dimension i) const + { + if (i < 0 || i >= dimensionality) + { + RMInit::logOut << "r_Minterval:::operator[](" << i << ") const index out of bounds (" << dimensionality << ")" << endl; + throw r_Eindex_violation(0, dimensionality-1, i); + } + + return intervals[i]; + } + +r_Sinterval& +r_Minterval::operator[](r_Dimension i) + { + if (i < 0 || i >= dimensionality) + { + RMInit::logOut << "r_Minterval:::operator[](" << i << ") index out of bounds (" << dimensionality << ")" << endl; + throw r_Eindex_violation(0, dimensionality-1, i); + } + + return intervals[i]; + } +#endif + +const r_Minterval& +r_Minterval::operator=(const r_Minterval& minterval) + { + if (this != &minterval) + { + if (intervals && dimensionality != minterval.dimension()) + { + delete[] intervals; + intervals = NULL; + } + + dimensionality = minterval.dimension(); + streamInitCnt = minterval.streamInitCnt; + + if(minterval.intervals) + { + if (!intervals) + intervals = new r_Sinterval[ dimensionality ]; + + for (r_Dimension i=0; i<dimensionality; i++) + intervals[i] = minterval[i]; + } + } + + return *this; + } + +bool +r_Minterval::operator==(const r_Minterval& mint) const + { + bool returnValue = false; + + if (dimensionality == mint.dimensionality) + { + returnValue = true; + + for (r_Dimension i=0; i<dimensionality && returnValue ; i++) + { + if (intervals[i] != mint[i]) + { + returnValue = false; + break; + } + } + } + + return returnValue; + } + +bool +r_Minterval::operator!=(const r_Minterval& mint) const + { + return !operator==(mint); + } + +r_Point +r_Minterval::get_origin() const throw(r_Error) + { + r_Point pt(dimensionality); + + if(!is_origin_fixed()) + { + RMInit::logOut << "r_Minterval::get_origin() " << *this << " is opened" << endl; + throw r_Error(INTERVALOPEN); + } + + for (r_Dimension i=0; i<dimensionality; i++) + pt[i]=intervals[i].low(); + + return pt; + } + +r_Point +r_Minterval::get_high() const throw(r_Error) + { + r_Point pt(dimensionality); + + if(!is_high_fixed()) + { + RMInit::logOut << "r_Minterval::get_high() " << *this << " is opened" << endl; + throw r_Error(INTERVALOPEN); + } + + for (r_Dimension i=0; i<dimensionality; i++) + pt[i] = intervals[i].high(); + + return pt; + } + +r_Point +r_Minterval::get_extent() const throw(r_Error) + { + r_Point pt(dimensionality); + + if(!is_origin_fixed() || !is_high_fixed()) + { + RMInit::logOut << "r_Minterval::get_high() " << *this << " is opened" << endl; + throw r_Error(INTERVALOPEN); + } + + for (r_Dimension i=0; i<dimensionality; i++) + pt[i] = intervals[i].get_extent(); + + return pt; + } + +r_Minterval& +r_Minterval::reverse_translate(const r_Point& t) throw(r_Error, r_Edim_mismatch, r_Eno_interval) + { + if (dimensionality != t.dimension()) + { + RMInit::logOut << "r_Minterval::reverse_translate(" << t << ") dimensions (" << dimensionality << ") do not match" << endl; + throw(r_Edim_mismatch( dimensionality, t.dimension())); + } + + if (!is_origin_fixed() || !is_high_fixed()) + { + RMInit::logOut << "r_Minterval::reverse_translate(" << t << ") " << *this << " is opened" << endl; + throw r_Error(INTERVALOPEN); + } + + for (r_Dimension i=0; i<dimensionality; i++) + intervals[i].set_interval(intervals[i].low() - t[i], intervals[i].high() - t[i]); + + return *this; + } + +r_Minterval& +r_Minterval::translate(const r_Point& t) throw(r_Error, r_Edim_mismatch, r_Eno_interval) + { + if (dimensionality != t.dimension()) + { + RMInit::logOut << "r_Minterval::translate(" << t << ") dimensions (" << dimensionality << ") do not match" << endl; + throw(r_Edim_mismatch( dimensionality, t.dimension())); + } + + if (!is_origin_fixed() || !is_high_fixed()) + { + RMInit::logOut << "r_Minterval::translate(" << t << ") " << *this << " is opened" << endl; + throw r_Error(INTERVALOPEN); + } + + for (r_Dimension i=0; i<dimensionality; i++) + intervals[i].set_interval(intervals[i].low() + t[i], intervals[i].high() + t[i]); + + return *this; + } + +r_Minterval +r_Minterval::create_reverse_translation(const r_Point& t) const throw(r_Error, r_Edim_mismatch, r_Eno_interval) + { + r_Minterval result(*this); + + result.reverse_translate(t); + + return result; + } + +r_Minterval +r_Minterval::create_translation(const r_Point& t) const throw(r_Error, r_Edim_mismatch, r_Eno_interval) + { + r_Minterval result(*this); + + result.translate(t); + + return result; + } + +r_Minterval& +r_Minterval::scale(const double& d) throw(r_Eno_interval) + { + vector<double> scaleVec; + + //create scale vector + for (r_Dimension i = 0; i < dimensionality; i++){ + scaleVec.push_back(d); + } + + scale(scaleVec); + + return *this; + } + +r_Minterval& +r_Minterval::scale(const vector<double>& scaleVec) throw(r_Eno_interval) + { + double high = 0., low = 0.; + + RMDBGENTER(1, RMDebug::module_raslib, "r_Minterval", "scale(" << scaleVec << ") before " << *this ); + + // if the size of scale vector is different from dimensionality, undefined behaviour + if(scaleVec.size() != dimensionality) { + RMDBGEXIT(1, RMDebug::module_raslib, "r_Minterval", "scale(" << scaleVec << ") scaleVec has wrong size " << *this ); + throw r_Edim_mismatch(scaleVec.size(), dimensionality); + } + + for (r_Dimension i = 0; i < dimensionality; i++) + { + // do explicit rounding, because the cast down in set_interval doesn't do the good rounding for negative values -- PB 2005-jun-19 + low = floor( scaleVec[i] * intervals[i].low() ); + + //correction by 1e-6 to avoid the strage bug when high was a + //integer value and floor return value-1(e.g. query 47.ql) + high = floor(scaleVec[i] * (intervals[i].high() +1) + 0.000001) - 1; + +// FIXME BUG it was not forseen to be able to scale [a:a] with a very low factor f +// to [af, af] +// if((r_Range)high != (r_Range)low) +// high--; // substract 1 which was added to high() + + intervals[i].set_interval((r_Range)low, (r_Range)high); + } + + RMDBGEXIT(1, RMDebug::module_raslib, "r_Minterval", "scale(" << scaleVec << ") after " << *this ); + + return *this; + } + +r_Minterval +r_Minterval::create_scale(const double& d) const throw(r_Eno_interval) + { + r_Minterval result(*this); + + result.scale(d); + + return result; + } + + +r_Minterval +r_Minterval::create_scale(const vector<double>& scaleVec) const throw(r_Eno_interval) + { + r_Minterval result(*this); + + result.scale(scaleVec); + + return result; + } + + + +r_Minterval& +r_Minterval::union_of(const r_Minterval& mint1, const r_Minterval& mint2) throw(r_Edim_mismatch, r_Eno_interval) + { + if (mint1.dimension() != mint2.dimension()) + { + RMInit::logOut << "r_Minterval::union_of(" << mint1 << ", " << mint2 << ") dimensions do not match" << endl; + throw(r_Edim_mismatch( mint1.dimension(), mint2.dimension())); + } + + // cleanup + initializing of this + if (dimensionality != mint1.dimension()) + { + if (intervals) + delete[] intervals; + dimensionality = mint1.dimension(); + streamInitCnt = dimensionality; + intervals = new r_Sinterval[ dimensionality ]; + } + for (r_Dimension i=0; i<dimensionality; i++) + intervals[i].union_of(mint1[i], mint2[i]); + + return *this; + } + +r_Minterval& +r_Minterval::union_with(const r_Minterval& mint) throw(r_Edim_mismatch, r_Eno_interval) + { + if (dimensionality != mint.dimension()) + { + RMInit::logOut << "r_Minterval::union_with(" << mint << ") dimensions (" << dimensionality << ") do not match" << endl; + throw(r_Edim_mismatch( dimensionality, mint.dimension())); + } + + for (r_Dimension i=0; i<dimensionality; i++) + intervals[i].union_with(mint[i]); + + return *this; + } + +r_Minterval& +r_Minterval::operator+=(const r_Minterval& mint) throw(r_Edim_mismatch, r_Eno_interval) + { + return union_with(mint); + } + +r_Minterval +r_Minterval::create_union(const r_Minterval& mint) const throw(r_Edim_mismatch, r_Eno_interval) + { + if (dimensionality != mint.dimension()) + { + RMInit::logOut << "r_Minterval::create_union(" << mint << ") dimensions (" << dimensionality << ") do not match" << endl; + throw(r_Edim_mismatch( dimensionality, mint.dimension())); + } + + r_Minterval result(dimensionality); + + for (r_Dimension i=0; i<dimensionality; i++) + result << intervals[i].create_union(mint[i]); + + return result; + } + +r_Minterval +r_Minterval::operator+(const r_Minterval& mint) const throw(r_Edim_mismatch, r_Eno_interval) + { + return create_union(mint); + } + +r_Minterval& +r_Minterval::difference_of(const r_Minterval& mint1, const r_Minterval& mint2) throw(r_Edim_mismatch, r_Eno_interval) + { + if (mint1.dimension() != mint2.dimension()) + { + RMInit::logOut << "r_Minterval::difference_of(" << mint1 << ", " << mint2 << ") dimensions do not match" << endl; + throw(r_Edim_mismatch( mint1.dimension(), mint2.dimension())); + } + + if (dimensionality != mint1.dimension()) + { + // cleanup + initializing of this + if (intervals) + delete[] intervals; + + dimensionality = mint1.dimension(); + streamInitCnt = dimensionality; + intervals = new r_Sinterval[ dimensionality ]; + } + + for (r_Dimension i=0; i<dimensionality; i++) + intervals[i].difference_of(mint1[i], mint2[i]); + + return *this; + } + +r_Minterval& +r_Minterval::difference_with(const r_Minterval& mint) throw(r_Edim_mismatch, r_Eno_interval) + { + if (dimensionality != mint.dimension()) + { + RMInit::logOut << "r_Minterval::difference_with(" << mint << ") dimensions (" << dimensionality << ") do not match" << endl; + throw(r_Edim_mismatch( dimensionality, mint.dimension())); + } + + for (r_Dimension i=0; i<dimensionality; i++) + intervals[i].difference_with(mint[i]); + + return *this; + } + +r_Minterval& +r_Minterval::operator-=(const r_Minterval& mint) throw(r_Edim_mismatch, r_Eno_interval) + { + return difference_with(mint); + } + +r_Minterval +r_Minterval::create_difference(const r_Minterval& mint) const throw(r_Edim_mismatch, r_Eno_interval) + { + if (dimensionality != mint.dimension()) + { + RMInit::logOut << "r_Minterval::create_difference(" << mint << ") dimensions (" << dimensionality << ") do not match" << endl; + throw(r_Edim_mismatch( dimensionality, mint.dimension())); + } + + r_Minterval result(dimensionality); + + for (r_Dimension i=0; i<dimensionality; i++) + result << intervals[i].create_difference(mint[i]); + + return result; + } + +r_Minterval +r_Minterval::operator-(const r_Minterval& mint) const throw(r_Edim_mismatch, r_Eno_interval) + { + return create_difference(mint); + } + +r_Minterval& +r_Minterval::intersection_of(const r_Minterval& mint1, const r_Minterval& mint2) throw(r_Edim_mismatch, r_Eno_interval) + { + if (mint1.dimension() != mint2.dimension()) + { + RMInit::logOut << "r_Minterval::intersection_of(" << mint1 << ", " << mint2 << ") dimensions do not match" << endl; + throw(r_Edim_mismatch( mint1.dimension(), mint2.dimension())); + } + if (dimensionality != mint1.dimension()) + { + // cleanup + initializing of this + if (intervals) + delete[] intervals; + + dimensionality = mint1.dimension(); + streamInitCnt = dimensionality; + intervals = new r_Sinterval[ dimensionality ]; + } + + for (r_Dimension i=0; i<dimensionality; i++) + intervals[i].intersection_of(mint1[i], mint2[i]); + return *this; + } + +r_Minterval& +r_Minterval::intersection_with(const r_Minterval& mint) throw(r_Edim_mismatch, r_Eno_interval) + { + if (dimensionality != mint.dimension()) + { + RMInit::logOut << "r_Minterval::intersection_with(" << mint << ") dimensions (" << dimensionality << ") do not match" << endl; + throw(r_Edim_mismatch( dimensionality, mint.dimension())); + } + + for (r_Dimension i=0; i<dimensionality; i++) + intervals[i].intersection_with(mint[i]); + + return *this; + } + +r_Minterval& +r_Minterval::operator*=(const r_Minterval& mint) throw(r_Edim_mismatch, r_Eno_interval) + { + return intersection_with(mint); + } + +r_Minterval +r_Minterval::create_intersection(const r_Minterval& mint) const throw(r_Edim_mismatch, r_Eno_interval) + { + if (dimensionality != mint.dimension()) + { + RMInit::logOut << "r_Minterval::create_intersection(" << mint << ") dimensions (" << dimensionality << ") do not match" << endl; + throw(r_Edim_mismatch( dimensionality, mint.dimension())); + } + + r_Minterval result(dimensionality); + + for (r_Dimension i=0; i<dimensionality; i++) + result << intervals[i].create_intersection(mint[i]); + + return result; + } + +r_Minterval +r_Minterval::operator*(const r_Minterval& mint) const throw(r_Edim_mismatch, r_Eno_interval) + { + return create_intersection(mint); + } + +r_Minterval& +r_Minterval::closure_of(const r_Minterval& mint1, const r_Minterval& mint2) throw(r_Edim_mismatch, r_Eno_interval) + { + if (mint1.dimension() != mint2.dimension()) + { + RMInit::logOut << "r_Minterval::closure_of(" << mint1 << ", " << mint2 << ") dimensions do not match" << endl; + throw(r_Edim_mismatch( mint1.dimension(), mint2.dimension())); + } + if (mint1.dimension() != dimensionality) + { + // cleanup + initializing of this + if (intervals) + delete[] intervals; + + dimensionality = mint1.dimension(); + streamInitCnt = dimensionality; + intervals = new r_Sinterval[ dimensionality ]; + } + + for (r_Dimension i=0; i<dimensionality; i++) + intervals[i].closure_of(mint1[i], mint2[i]); + + return *this; + } + +r_Minterval& +r_Minterval::closure_with(const r_Minterval& mint) throw(r_Edim_mismatch, r_Eno_interval) + { + if (dimensionality != mint.dimension()) + { + RMInit::logOut << "r_Minterval::closure_with(" << mint << ") dimensions (" << dimensionality << ") do not match" << endl; + throw(r_Edim_mismatch( dimensionality, mint.dimension())); + } + + for (r_Dimension i=0; i<dimensionality; i++) + intervals[i].closure_with(mint[i]); + + return *this; + } + +r_Minterval +r_Minterval::create_closure(const r_Minterval& mint) const throw(r_Edim_mismatch, r_Eno_interval) + { + if (dimensionality != mint.dimension()) + { + RMInit::logOut << "r_Minterval::create_closure(" << mint << ") dimensions (" << dimensionality << ") do not match" << endl; + throw(r_Edim_mismatch( dimensionality, mint.dimension())); + } + + r_Minterval result(dimensionality); + + for (r_Dimension i=0; i<dimensionality; i++) + result << intervals[i].create_closure(mint[i]); + + return result; + } + +void +r_Minterval::print_status(std::ostream& s) const + { + s << "["; + + if (dimensionality > 0) + { + for (r_Dimension i=0; i<dimensionality-1; i++) + s << intervals[i] << ","; + + s << intervals[dimensionality-1]; + } + + s << "]"; + } + +char* +r_Minterval::get_string_representation() const + { + unsigned int bufferSize = dimensionality*25+3; // should be enough + + // allocate buffer and initialize string stream + char* buffer = new char[bufferSize]; + std::ostrstream domainStream(buffer, bufferSize); + + // write into string stream + domainStream << (*this) << std::ends; + + // allocate memory taking the final string + char* returnString = strdup(buffer); + + // delete buffer + delete[] buffer; + + return returnString; + } + +r_Area +r_Minterval::cell_count() const throw(r_Error) + { + r_Area cellCount = 1; + r_Point ptExt=get_extent(); + + for (r_Dimension i=0; i<dimensionality; i++) + cellCount *= ptExt[i]; + + return cellCount; + } + +// offset in cells for linear access of the data element referred by point in the data memory area +// Lower dimensions are higher valued which means that the highest dimension is stored in a sequence. +r_Area +r_Minterval::cell_offset(const r_Point& point) const throw(r_Eindex_violation, r_Error) + { + r_Dimension i = 0; + r_Area offset = 0; + r_Point ptExt; + + if (dimensionality != point.dimension()) + { + RMInit::logOut << "r_Minterval::cell_offset(" << point << ") dimension of domain (" << dimensionality << ") does not match dimension of argument (" << point.dimension() << ")" << endl; + throw r_Edim_mismatch(point.dimension(), dimensionality); + } + + ptExt=get_extent(); + + // calculate offset + for (i = 0; i < dimensionality - 1; i++) + { + if (point[i] < intervals[i].low() || point[i] > intervals[i].high()) + { + RMInit::logOut << "r_Minterval::cell_offset(" << point << ") point is out of range (" << *this << ")" << endl; + throw(r_Eindex_violation(point[i], intervals[i].low(), intervals[i].high())); + } + + offset = (offset + point[i] - intervals[i].low()) * ptExt[i+1]; + } + + // now i = dimensionality - 1 + if (point[i] < intervals[i].low() || point[i] > intervals[i].high()) + { + RMInit::logOut << "r_Minterval::cell_offset(" << point << ") point is out of range (" << *this << ")" << endl; + throw(r_Eindex_violation(point[i], intervals[i].low(), intervals[i].high())); + } + offset += point[i] - intervals[i].low(); + + return offset; + } + +// Arguments.....: linear offset +// Return value..: point object which corresponds to the linear offset of the argument +// Description...: The method calucaltes the spatial domain coordinates as a point out of an offset specification. Lower dimensions are higher valued which means that the highest dimension is stored in a sequence. +r_Point +r_Minterval::cell_point(r_Area offset) const throw(r_Eno_cell, r_Error) + { + r_Dimension i; + unsigned int factor=1; + r_Point pt(dimensionality), ptExt; + + if (offset >= cell_count()) + { + RMInit::logOut << "r_Minterval::cell_point(" << offset << ") offset is out of range (" << cell_count() << ")" << endl; + throw r_Eno_cell(); + } + + ptExt=get_extent(); + + for (i=0; i<dimensionality; i++) + factor *= ptExt[i]; + + for (i=0; i<dimensionality; i++) + { + factor /= ptExt[i]; + pt[i] = intervals[i].low() + (offset - (offset%factor))/factor; + offset %= factor; + } + + return pt; + } + +void +r_Minterval::delete_dimension(r_Dimension dim) throw(r_Eindex_violation) + { + if (dim < 0 || dim >= dimensionality) + { + RMInit::logOut << "r_Minterval::delete_dimension(" << dim << ") dimension is out of range (" << dimensionality << ")" << endl; + throw r_Eindex_violation(0, dimensionality-1, dim); + } + + dimensionality -= 1; + streamInitCnt = dimensionality; + r_Sinterval* newIntervals = new r_Sinterval[ dimensionality ]; + + for (r_Dimension i=0, j=0; i<dimensionality; i++, j++) + { + if (i==dim) j++; + newIntervals[i] = intervals[j]; + } + + delete[] intervals; + + intervals = newIntervals; + } + +r_Bytes +r_Minterval::get_storage_size() const + { + r_Bytes sz = sizeof(r_Sinterval*) + 2 * sizeof(r_Dimension); + + if (dimensionality > 0) + sz += dimensionality * intervals->get_storage_size(); + + return sz; + } + +bool +r_Minterval::is_mergeable(const r_Minterval& b) const + { + bool is_merg = true; + // An alias to this object + const r_Minterval& a = *this; + + // The blocks must have the same dimensionality to be mergeable + if (a.dimensionality != b.dimensionality) + { + is_merg = false; + } + else { + + // Count the number of adjacent frontiers + int ones_differences = 0; + + // For all dimensions + for (r_Dimension i=0; i<dimensionality; i++) + { + // Diferente origins + if (a[i].low() != b[i].low()) + { + if ((a[i].low() == b[i].high()+1) || (b[i].low() == a[i].high()+1)) + // If borders are adjacent + { + // Update counter + ++ones_differences; + } + else { + // Else non-mergeable blocks + is_merg = false; + break; + } + } + else { + // Check ending + if (a[i].high() != b[i].high()) + { + is_merg = false; + // Not the same, can't be + break; + // mergeable + } + } + } + + // Only one adjacent borded + if (is_merg && (ones_differences!=1)) + is_merg = false; + // allowed + } + return is_merg; + } + +std::ostream& operator<<(std::ostream& s, const r_Minterval& d) + { + d.print_status(s); + return s; + } + +std::ostream& operator<<(std::ostream& s, const vector<double>& doubleVec) + { + vector<double>::const_iterator iter, iterEnd; + + iter=doubleVec.begin(); + iterEnd=doubleVec.end(); + s << "{"; + while(iter != iterEnd){ + s << *iter; + ++iter; + if(iter != iterEnd) + s << ", "; + } + s << "}"; + + return s; + } diff --git a/raslib/minterval.hh b/raslib/minterval.hh new file mode 100644 index 0000000..a9b596d --- /dev/null +++ b/raslib/minterval.hh @@ -0,0 +1,567 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: minterval.hh + * + * MODULE: raslib + * CLASS: r_Minterval + * + * COMMENTS: + * +*/ + +#ifndef _D_MINTERVAL_ +#define _D_MINTERVAL_ + +#include <iostream> +#include <vector> +using std::endl; +using std::vector; + +#ifdef __VISUALC__ +// Diable warning for exception specification. +#pragma warning( disable : 4290 ) +#include <strstrea.h> +#else +#include <sstream> // for istrstream +#endif + +class r_Edim_mismatch; +class r_Error; +class r_Einit_overflow; +class r_Eno_interval; +class r_Eno_cell; +class r_Error; + + +#include "raslib/sinterval.hh" +#include "raslib/point.hh" + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + The spatial domain of an MDD is represented by an object + of class \Ref{r_Minterval}. It specifies lower and upper bound + of the point set for each dimension of an MDD. Internally, + the class is realized through an array of intervals of type + \Ref{r_Sinterval}. + + For the operations union, difference, and intersection the + dimensionalties of the operands must be equal, otherwise an + exception is raised. The semantics of the operations are + defined as follows for each dimension: + + | ... fixed bound \\ + * ... open bound + + \begin{verbatim} + + class orientation union difference intersection + ----------------------------------------------------------- + 1 |-a-| |-b-| error a error + + 2 |-a-| [a1,b2] [a1,b1] [b1,a2] + |-b-| + + 3 |--a--| a error b + |-b-| + + 4 |-b-| [b1,a2] [b2,a2] [a1,b2] + |-a-| + + 5 |--b--| b error a + |-a-| + + 6 |-b-| |-a-| error a error + + 7 |-a-|-b-| [a1,b2] a [a2,a2] + + 8 |-b-|-a-| [b1,a2] a [b2,b2] + + 9 |--a--| a [a1,b1] b + |-b-| + + 10 |--a--| a [b2,a2] b + |-b-| + + 11 |-a-| a error a + |-b-| + + 12 |--b--| b error a + |-a-| + + 13 |--b--| b error a + |-a-| + + ----------------------------------------------------- + + 14 |--a--* a error b + |-b-| + + 15 |--a--* a [b2,a2] b + |-b-| + + 16 |-b-| |-a-* error a error + + 17 |-b-|-a-* [b1,a2] a [b2,b2] + + 18 |--a--* [b1,a2] [b2,a2] [a1,b2] + |-b-| + + ----------------------------------------------------- + + 19 *--a--| a error b + |-b-| + + 20 *--a--| a [a1,b1] b + |-b-| + + 21 *-a-| |-b-| error a error + + 22 *-a-|-b-| [a1,b2] a [a2,a2] + + 23 *--a--| [a1,b2] [a1,b1] [b1,a2] + |-b-| + + ----------------------------------------------------- + + 24 |--b--* b error a + |-a-| + + 25 |--b--* b error a + |-a-| + + 26 |-a-| |-b-* error a error + + 27 |-a-|-b-* [a1,b2] a [a2,a2] + + 28 |--b--* [a1,b2] [a1,b1] [b1,a2] + |-a-| + + ----------------------------------------------------- + + 29 *--b--| b error a + |-a-| + + 30 *--b--| b error a + |-a-| + + 31 *-b-| |-a-| error a error + + 32 *-b-|-a-| [b1,a2] a [b2,b2] + + 33 *--b--| [b1,a2] [b2,a2] [a1,b2] + |-a-| + + ----------------------------------------------------- + + 34 *-a-| |-b-* error a error + + 35 *-a-|-b-* [a1,b2] a [a2,a2] + + 36 *-a-| [a1,b2] [a1,b1] [b1,a2] + |-b-* + + ----------------------------------------------------- + + 37 *-b-| |-a-* error a error + + 38 *-b-|-a-* [b1,a2] a [b2,b2] + + 39 *-b-| [b1,a2] [a1,b1] [a1,b2] + |-a-* + + ----------------------------------------------------- + + 40 *-a-| b error a + *-b-| + + 41 *-a-| a error a + *-b-| + + 42 *-b-| a [b2,a2] b + *-a-| + + ----------------------------------------------------- + + 43 |-a-* a [a1,b1] b + |-b-* + + 44 |-a-* a error a + |-b-* + + 45 |-b-* b error a + |-a-* + + ----------------------------------------------------- + 46 *-a-* |-b-| a error b + + 47 *-b-* |-a-| b error b + + 48 *-a-* a [b2,a2] b + *-b-| + + 49 *-a-* a [a1,b1] b + |-b-* + + 50 *-b-* b error a + *-a-| + + 51 *-b-* b error a + |-a-* + + 52 *-a-* a error a + *-b-* + + \end{verbatim} + + Attention: The difference operation has to be reconsidered in future + concerning a discrete interpretation of the intervals. + + The closure operation defines an interval which is the smallest + interval containing the two operands. + The method {\tt intersects_with()} returns 0 in the error cases of the + intersection operation and 1 otherwise. + +*/ + +class r_Minterval +{ + public: + /// constructor getting dimensionality for stream initializing + r_Minterval( r_Dimension ); + /// constructor taking string representation (e.g. [ 1:255, *:200, *:* ]) + r_Minterval( const char* ) throw(r_Eno_interval); + /// constructor taking string representation (e.g. [ 1:255, *:200, *:* ]) + r_Minterval( char* ) throw(r_Eno_interval); + /// for stream initializing with intervals + r_Minterval& operator<<( const r_Sinterval& ) + throw( r_Einit_overflow ); + /// for stream initializing with point intervals + r_Minterval& operator<<( r_Range ) + throw( r_Einit_overflow ); + + /// default constructor + r_Minterval(); + /// copy constructor + r_Minterval( const r_Minterval& ); + /// destructor: cleanup dynamic memory + ~r_Minterval(); + + /// it is called when an object leaves transient memory + void r_deactivate(); + + /// determines if the self minterval intersects with the delivered one + bool intersects_with( const r_Minterval& ) const; + +#ifdef OPT_INLINE + inline +#endif + /// read access the i-th interval + r_Sinterval operator[]( r_Dimension ) const; +#ifdef OPT_INLINE + inline +#endif + /// write access the i-th interval + r_Sinterval& operator[]( r_Dimension ); + + /// assignment: cleanup + copy + const r_Minterval& operator= ( const r_Minterval& ); + + /// equal operator + bool operator==( const r_Minterval& ) const; + + /** + Two domains are equal if they have the same number of dimensions and + each dimension has the same lower and upper bounds. + */ + + /// non equal operator - negation of equal operator + bool operator!=( const r_Minterval& ) const; + + /// does this interval cover the given point + inline const bool covers( const r_Point& pnt ) const; + /** + throws r_Edim_mismatch when dimensions do not match + */ + + /// does this interval cover the given interval + inline const bool covers( const r_Minterval& inter ) const; + /** + throws r_Edim_mismatch when dimensions do not match + */ + + /// get dimensionality + inline r_Dimension dimension() const; + + /// checks if all lower bounds are fixed + inline const bool is_origin_fixed() const; + /*@Doc: + Returns true if all lower bounds are fixed, otherwise false. + */ + + /// get lower left corner of minterval. + r_Point get_origin() const throw(r_Error); + /*@Doc: + Returns a point with the minimum coordinates in all dimensions. + This is operation is only legal if all lower bounds are fixed! + */ + + /// checks if all upper bounds are fixed + inline const bool is_high_fixed() const; + /*@Doc: + Returns true if all upper bounds are fixed, otherwise false. + */ + + /// get highest corner of tile. + r_Point get_high() const throw(r_Error); + /*@Doc: + Returns a point with the maximum coordinates in all dimensions. + This is operation is only legal if all upper bounds are fixed! + */ + + /// get size of minterval as point. + r_Point get_extent() const throw(r_Error); + /*@Doc: + Returns a point with high() - low() + 1 of this in each + dimension when all bounds are fixed + */ + + /// Checks if this block is mergeable with another block (interval) + bool is_mergeable(const r_Minterval& other) const; + /** + This method checks if two r_Mintervals are "mergeable" side by side. + For this to be possible, they have to have the same low() and high() + values in all dimensions except in one where they differ by one point, + this is, a.low()==b.high()+1 or b.low()==a.high()+1. For instance, the + following two blocks are mergeable: + + +-------------+---------------------------------------+ + | A | B | + +-------------|---------------------------------------| + + and the following two are not: + + +-------------+-------------------------+ + | | B | + | A +-------------------------+ + +-------------+ + */ + + //@Man: Methods for translation: + //@{ + /// translates this by a point. + r_Minterval& reverse_translate( const r_Point& ) + throw( r_Error, r_Edim_mismatch, r_Eno_interval ); + /*@Doc: + Subtracts respective coordinate of a point to the lower bounds of an + interval. This operation is only legal if all bounds are + fixed! + */ + /// returns new interval as translation of this by a point. + r_Minterval create_reverse_translation( const r_Point& ) const + throw( r_Error, r_Edim_mismatch, r_Eno_interval ); + /*@Doc: + Subtracts respective coordinate of a point to the lower bounds of an + interval. This operation is only legal if all bounds are + fixed! + */ + /// translates this by a point. + r_Minterval& translate( const r_Point& ) + throw( r_Error, r_Edim_mismatch, r_Eno_interval ); + /*@Doc: + Adds respective coordinate of a point to the lower bounds of an + interval. This operation is only legal if all bounds are + fixed! + */ + /// returns new interval as translation of this by a point. + r_Minterval create_translation( const r_Point& ) const + throw( r_Error, r_Edim_mismatch, r_Eno_interval ); + /*@Doc: + Adds respective coordinate of a point to the lower bounds of an + interval. This operation is only legal if all lower bounds are + fixed! + */ + /// + //@} + + //***************************************** + + //@Man: Methods for scaling: + //@{ + /// scales this by a factor. + r_Minterval& scale( const double& ) throw ( r_Eno_interval ); + /*@Doc: + Scales respective extents by factor. + */ + /// scales this by a factor. + r_Minterval& scale( const vector<double>& ) throw ( r_Eno_interval ); + /*@Doc: + Scales respective extents by vector of factors. + */ + /// returns new interval as scaled from this by a point. + r_Minterval create_scale( const double& ) const throw ( r_Eno_interval ); + /*@Doc: + Scales respective extents by factor. + */ + /// returns new interval as scaled from this by a point. + r_Minterval create_scale( const vector<double>& ) const throw ( r_Eno_interval ); + /*@Doc: + Scales respective extents by vector of factors. + */ + //@} + + //***************************************** + + + + + + //@Man: Methods/Operators for the union operation: + //@{ + /// + r_Minterval& union_of ( const r_Minterval&, const r_Minterval& ) + throw( r_Edim_mismatch, r_Eno_interval ); + /// + r_Minterval& union_with ( const r_Minterval& ) + throw( r_Edim_mismatch, r_Eno_interval ); + /// + r_Minterval& operator+= ( const r_Minterval& ) + throw( r_Edim_mismatch, r_Eno_interval ); + /// + r_Minterval create_union ( const r_Minterval& ) const + throw( r_Edim_mismatch, r_Eno_interval ); + /// + r_Minterval operator+ ( const r_Minterval& ) const + throw( r_Edim_mismatch, r_Eno_interval ); + /// + //@} + + //@Man: Methods/Operators for the difference operation: + //@{ + /// + r_Minterval& difference_of ( const r_Minterval&, const r_Minterval& ) + throw( r_Edim_mismatch, r_Eno_interval ); + /// + r_Minterval& difference_with ( const r_Minterval& ) + throw( r_Edim_mismatch, r_Eno_interval ); + /// + r_Minterval& operator-= ( const r_Minterval& ) + throw( r_Edim_mismatch, r_Eno_interval ); + /// + r_Minterval create_difference ( const r_Minterval& ) const + throw( r_Edim_mismatch, r_Eno_interval ); + /// + r_Minterval operator- ( const r_Minterval& ) const + throw( r_Edim_mismatch, r_Eno_interval ); + /// + //@} + + //@Man: Methods/Operators for the intersection operation: + //@{ + /// + r_Minterval& intersection_of ( const r_Minterval&, const r_Minterval& ) + throw( r_Edim_mismatch, r_Eno_interval ); + /// + r_Minterval& intersection_with ( const r_Minterval& ) + throw( r_Edim_mismatch, r_Eno_interval ); + /// + r_Minterval& operator*= ( const r_Minterval&) + throw( r_Edim_mismatch, r_Eno_interval); + /// + r_Minterval create_intersection ( const r_Minterval& ) const + throw( r_Edim_mismatch, r_Eno_interval ); + /// + r_Minterval operator* ( const r_Minterval& ) const + throw( r_Edim_mismatch, r_Eno_interval ); + /// + //@} + + //@Man: Methods/Operators for the closure operation: + //@{ + /// + r_Minterval& closure_of ( const r_Minterval&, const r_Minterval& ) + throw( r_Edim_mismatch, r_Eno_interval ); + /// + r_Minterval& closure_with ( const r_Minterval& ) + throw( r_Edim_mismatch, r_Eno_interval ); + /// + r_Minterval create_closure ( const r_Minterval& ) const + throw( r_Edim_mismatch, r_Eno_interval ); + /// + //@} + + /// writes the state of the object to the specified stream + void print_status( std::ostream& s = std::cout ) const; + + /// gives back the string representation + char* get_string_representation() const; + /** + The string representation delivered by this method is allocated using {\tt malloc()} and + has to be free unsing {\tt free()} in the end. It can be used to construct a {\tt r_Minterval} + again with a special constructor provided. The string representation is build using + {\tt print_status()}. + */ + + //@Man: Methods for internal use only: + //@{ + /// calculate number of cells + r_Area cell_count() const throw(r_Error); + /// calculate offset in cells for one dimensional access (dimension ordering is high first) + r_Area cell_offset( const r_Point& ) const throw( r_Eindex_violation, r_Error ); + /// calculate point index out of offset + r_Point cell_point( r_Area ) const throw( r_Eno_cell, r_Error ); + /// delete the specified dimension + void delete_dimension( r_Dimension ) throw( r_Eindex_violation ); + /// calculate the size of the storage space occupied + r_Bytes get_storage_size( ) const; + /// + //@} + + protected: + /// array for storing the intervals + r_Sinterval* intervals; + + /// dimensionality of the domain + r_Dimension dimensionality; + + /// number of components initialized already + r_Dimension streamInitCnt; + + /// initialization for constructors which take chars + void constructorinit(char* ) throw(r_Eno_interval); +}; + + + + +//@ManMemo: Module: {\bf raslib} +/** + Output stream operator for objects of type {\tt const} \Ref{r_Minterval}. +*/ +extern std::ostream& operator<<( std::ostream& s, const r_Minterval& d ); + +#include "raslib/minterval.icc" + +#endif diff --git a/raslib/minterval.icc b/raslib/minterval.icc new file mode 100644 index 0000000..aec847f --- /dev/null +++ b/raslib/minterval.icc @@ -0,0 +1,138 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INLINE SOURCE: minterval.icc + * + * MODULE: raslib + * CLASS: r_Minterval + * + * COMMENTS: + * +*/ + +// -*-C++-*- (for Emacs) +#include "raslib/rminit.hh" +#include "raslib/error.hh" + +inline r_Dimension +r_Minterval::dimension() const +{ + return dimensionality; +} + +inline const bool +r_Minterval::is_origin_fixed() const +{ + bool retval=true; + + if(!dimensionality) + { + retval=false; + } + else + { + for(r_Dimension i=0; i < dimensionality; i++) + retval &= intervals[i].is_low_fixed(); + } + + return retval; +} + +inline const bool +r_Minterval::is_high_fixed() const +{ + bool retval=true; + + if(!dimensionality) + { + //we have an uninitialized interval + retval=false; + } + else + { + for(r_Dimension i=0; i < dimensionality; i++) + retval &= intervals[i].is_high_fixed(); + } + + return retval; +} + + + +inline const bool +r_Minterval::covers( const r_Point& pnt ) const + { + bool retval = true; + if (dimensionality == pnt.dimension()) + { + for (r_Dimension i = 0; i < pnt.dimension(); i++) + { + if ((intervals[i].is_low_fixed() && pnt[i] < intervals[i].low()) || (intervals[i].is_high_fixed() && pnt[i] > intervals[i].high())) + { + retval = false; + break; + } + } + } + else { + RMInit::logOut << "r_Minterval::covers(" << pnt << ") dimensions do not match" << endl; + retval=false; + } + + return retval; + } + + +inline const bool +r_Minterval::covers( const r_Minterval& inter2 ) const + { + bool retval = true; + if (dimensionality == inter2.dimension()) + { + for (r_Dimension i = 0; i < dimensionality ; i++) + { + // first check if i am low fixed and the other isn't: false + // both are low fixed + // check if i am smaller than the other: false + // second check if i am high fixed and the other isn't: false + // both are high fixed + // check if i am smaller than the other: false + if ( + (intervals[i].is_low_fixed() && (!(inter2[i].is_low_fixed()) || intervals[i].low() > inter2[i].low())) + || + (intervals[i].is_high_fixed() && (!(inter2[i].is_high_fixed()) || intervals[i].high() < inter2[i].high())) + ) + { + retval = false; + break; + } + } + } + else { + RMInit::logOut << "r_Minterval::covers(" << inter2 << ") dimensions do not match" << endl; + retval=false; + } + + return retval; + } + diff --git a/raslib/mintervaltype.cc b/raslib/mintervaltype.cc new file mode 100644 index 0000000..beff527 --- /dev/null +++ b/raslib/mintervaltype.cc @@ -0,0 +1,80 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +static const char rcsid[] = "@(#)raslib, r_Minterval_Type: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/mintervaltype.cc,v 1.6 2003/12/27 23:01:21 rasdev Exp $"; + +#include "raslib/mintervaltype.hh" + +r_Minterval_Type::r_Minterval_Type() + : r_Type() +{ +} + +r_Minterval_Type::r_Minterval_Type( const r_Minterval_Type& oldObj ) + : r_Type(oldObj) +{ +} + +bool +r_Minterval_Type::isMintervalType() const + { + return true; + } + +r_Type* +r_Minterval_Type::clone() const +{ + return new r_Minterval_Type( *this ); +} + +r_Type::r_Type_Id +r_Minterval_Type::type_id() const +{ + return MINTERVALTYPE; +} + +void +r_Minterval_Type::convertToLittleEndian(char* cells, r_Area noCells) const +{ +} + +void +r_Minterval_Type::convertToBigEndian(char* cells, r_Area noCells) const +{ +} + +void +r_Minterval_Type::print_status( std::ostream& s ) const +{ + s << "minterval"; +} + +r_Minterval_Type::~r_Minterval_Type() +{ +} + +std::ostream &operator<<( std::ostream &str, const r_Minterval_Type &type ) +{ + type.print_status(str); + return str; +} diff --git a/raslib/mintervaltype.hh b/raslib/mintervaltype.hh new file mode 100644 index 0000000..9f3f620 --- /dev/null +++ b/raslib/mintervaltype.hh @@ -0,0 +1,79 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: mintervaltype.hh + * + * MODULE: raslib + * CLASS: r_Minterval_Type + * + * COMMENTS: + * +*/ + +#ifndef _D_MINTERVAL_TYPE_ +#define _D_MINTERVAL_TYPE_ + +#include "raslib/type.hh" + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + This class represents the multidimensional interval type in the ODMG conformant + representation of the RasDaMan type system. +*/ + +class r_Minterval_Type : public r_Type +{ +public: + /// default constructor + r_Minterval_Type(); + + /// copy constructor + r_Minterval_Type( const r_Minterval_Type& oldObj ); + + /// clone operation + virtual r_Type* clone() const; + + /// retrieve id of the type. + virtual r_Type::r_Type_Id type_id() const; + + /// converts array of cells from NT byte order to Unix byte order. + virtual void convertToLittleEndian(char* cells, r_Area noCells) const; + + /// converts array of cells from Unix byte order to NT byte order. + virtual void convertToBigEndian(char* cells, r_Area noCells) const; + + /// writes state of object to specified stream + virtual void print_status( std::ostream& s = std::cout ) const; + + virtual bool isMintervalType() const; + + /// destructor + ~r_Minterval_Type(); +}; + +//@Doc: write the status of a minterval type to a stream +extern std::ostream &operator<<( std::ostream &str, const r_Minterval_Type &type ); + +#endif + diff --git a/raslib/miter.cc b/raslib/miter.cc new file mode 100644 index 0000000..35acb54 --- /dev/null +++ b/raslib/miter.cc @@ -0,0 +1,33 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * SOURCE: miter.cc + * + * MODULE: raslib + * CLASS: r_Miter + * +*/ + +static const char rcsid[] = "@(#)raslib, r_Miter: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/miter.cc,v 1.5 2003/12/27 23:01:21 rasdev Exp $"; + +// moved everything to miter.icc diff --git a/raslib/miter.hh b/raslib/miter.hh new file mode 100644 index 0000000..98ee03c --- /dev/null +++ b/raslib/miter.hh @@ -0,0 +1,99 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: miter.hh + * + * MODULE: raslib + * CLASS: r_Miter + * +*/ + +#ifndef _D_MITER_ +#define _D_MITER_ + +class r_Minterval; + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + r_Miter is used for iterating through parts of + multidimensional intervals. It is given the domain of + the object to be iterated through, the size of the base + base type, the address of the first cell in the Tile and + an Minterval specifying the area to be iterated through. + + Going to the next cell is done with nextCell() which + returns the adress of the next cell. Test for the end + is done with isDone(). The iterator can be reset with + reset(). +*/ + +class r_Miter +{ +public: + /// constructor. + inline r_Miter( const r_Minterval* newAreaIter, + const r_Minterval* newAreaTile, r_Bytes newCellSize, + const char* newFirstCell ); + /** + The pointers are stored, do not delete the objects as long + as the iterator is used! + */ + + /// destructor. + inline ~r_Miter(); + /// resets iterator to first cell. + inline void reset(); + /// returns current cell and sets iterator to next cell. + inline char* nextCell(); + /// returns TRUE if iteration is finished. + inline bool isDone(); +protected: + // structure storing information on iteration for each dimension + // (perhaps add dimension for reordering later) + typedef struct { + int repeat; // total number of repeats + int inc; // increment per repeat + int curr; // current repeat + } incArrElem; + /// area to be iterated through + const r_Minterval* areaIter; + /// area of tile. + const r_Minterval* areaTile; + /// size of base type. + r_Bytes cellSize; + /// offset of first cell in tile. + const char* firstCell; + /// array with increments + incArrElem* incArrIter; + /// flag set if iteration is finished. + bool done; + /// current cell for iteration; + char* currCell; + /// counter for position in lowest dimension. + int lowCount; +}; + +#include "miter.icc" + +#endif diff --git a/raslib/miter.icc b/raslib/miter.icc new file mode 100644 index 0000000..f4578d2 --- /dev/null +++ b/raslib/miter.icc @@ -0,0 +1,144 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * SOURCE: miter.cc + * + * MODULE: raslib + * CLASS: r_Miter + * +*/ + +#include "raslib/miter.hh" +#include "raslib/minterval.hh" +#include "raslib/rmdebug.hh" + +inline +r_Miter::r_Miter( const r_Minterval* newAreaIter, + const r_Minterval* newAreaTile, + r_Bytes newCellSize, const char* newFirstCell ) + : areaIter(newAreaIter), areaTile(newAreaTile), cellSize(newCellSize), + firstCell(newFirstCell), done(false) +{ + RMDBGENTER(1, RMDebug::module_raslib, "r_Miter", "r_Miter()"); + // the following initializes incArrIter and calculates the first offset + int tIncIter = 1; // total increment for current dimension + int prevTIncIter = 1; // total increment for previous dimension + r_Bytes incIter = cellSize; // current increment + r_Dimension i; + int firstOff = 0; + + RMDBGMIDDLE(2, RMDebug::module_raslib, "r_Miter", "area for iteration: " << *newAreaIter); + RMDBGMIDDLE(2, RMDebug::module_raslib, "r_Miter", "whole area: " << *newAreaTile); + + // dimensionality of both areaIter and areaTile + r_Dimension dim = areaIter->dimension(); + // stores the increments + incArrIter = new incArrElem[dim]; + + for( i=0; i<dim; i++ ) { + // in RasDaMan the order of dimensions is the other way round! + int r = dim - i - 1; + // used for counting in iteration, initialize with 0 + incArrIter[i].curr = 0; + // how often is the increment added? + incArrIter[i].repeat = (*areaIter)[r].high() - (*areaIter)[r].low() + 1; + RMDBGMIDDLE(4, RMDebug::module_raslib, "r_Miter", "repeat dim " << i << ": " << incArrIter[i].repeat ); + // the increment for the result tile (higher dimensions calculated + // further down) + incArrIter[i].inc = incIter; + RMDBGMIDDLE(4, RMDebug::module_raslib, "r_Miter", "incIter dim " << i << ": " << incIter ); + + // calculate starting offset and increments for higher dimensions + // firstOff is the offset in chars of the first cell + firstOff += ((*areaIter)[r].low()-(*areaTile)[r].low()) * prevTIncIter * cellSize; + // tInc is the increment if the dimension would be skipped + tIncIter = ((*areaTile)[r].high()-(*areaTile)[r].low()+1) * prevTIncIter; + // inc is the real increment, after some cells in the dimensions + // have been iterated through. + incIter = (tIncIter - incArrIter[i].repeat*prevTIncIter) * cellSize; + // remember total increment of last dimension + prevTIncIter = tIncIter; + } + firstCell += firstOff; + reset(); + RMDBGEXIT(1, RMDebug::module_raslib, "r_Miter", "r_Miter()"); +} + +inline +r_Miter::~r_Miter() +{ + delete [] incArrIter; +} + +inline void +r_Miter::reset() +{ + currCell = (char*)firstCell; + done = false; + lowCount = 0; + for( r_Dimension i=0; i<areaIter->dimension(); i++ ) { + incArrIter[i].curr = 0; + } +} + +inline char* +r_Miter::nextCell() +{ + // return the current cell + char* retVal = currCell; + r_Dimension i = 0; + + if(done) + return retVal; + + // increment adresses + currCell += incArrIter[0].inc; + lowCount++; + if(lowCount == incArrIter[0].repeat) { + lowCount = 0; + // increment other dimensions + for(i=1; i < areaIter->dimension(); i++) { + incArrIter[i].curr++; + currCell += incArrIter[i].inc; + if(incArrIter[i].curr < incArrIter[i].repeat) { + // no overflow in this dimension + break; + } else { + // overflow in this dimension + incArrIter[i].curr = 0; + } + } + if( i == areaIter->dimension() ) { + // overflow in last dimension + done = true; + currCell = retVal; + } + } + return retVal; +} + +bool +r_Miter::isDone() +{ + return done; +} diff --git a/raslib/mitera.cc b/raslib/mitera.cc new file mode 100644 index 0000000..b92cb72 --- /dev/null +++ b/raslib/mitera.cc @@ -0,0 +1,141 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * SOURCE: mitera.cc + * + * MODULE: raslib + * CLASS: r_MiterArea + * +*/ + +#include "raslib/mitera.hh" +#include "raslib/minterval.hh" +#include "raslib/rmdebug.hh" + +r_MiterArea::r_MiterArea( const r_Minterval* newIterDom, + const r_Minterval* newImgDom ) throw(r_Error) + : iterDom(newIterDom), imgDom(newImgDom), done(false) +{ + RMDBGENTER( 1, RMDebug::module_raslib, "r_MiterArea", "r_MiterArea()"); + + if (imgDom->dimension() != iterDom->dimension()) + { + //in this case we have an undefined situation + RMInit::logOut << "r_MiterArea::rMiterArea(" << iterDom << ", " << imgDom << ") dimension mismatch" << endl; + throw r_Error(INTERVALSWITHDIFFERENTDIMENSION); + } + + if(!imgDom->is_origin_fixed() || + !imgDom->is_high_fixed()) + { + //in this case we have an undefined situation + RMInit::logOut << "r_MiterArea::rMiterArea(" << iterDom << ", " << imgDom << ") imgDom is opened" << endl; + throw r_Error(INTERVALOPEN); + } + + if(!iterDom->is_origin_fixed() || + !iterDom->is_high_fixed()) + { + //in this case we have an undefined situation + RMInit::logOut << "r_MiterArea::rMiterArea(" << iterDom << ", " << imgDom << ") iterDom is opened" << endl; + throw r_Error(INTERVALOPEN); + } + + + // dimensionality of both iterDom and imgDom + r_Dimension dim = imgDom->dimension(); + // stores the increments + incArrIter = new incArrElem[dim]; + + for(r_Dimension i=0; i<dim; i++ ) { + // used for counting in iteration, initialize with 0 + incArrIter[i].curr = 0; + // how often is the iterDom moved inside the imgDom + incArrIter[i].repeat = (imgDom->get_extent()[i] / iterDom->get_extent()[i]) + + ( imgDom->get_extent()[i] % iterDom->get_extent()[i] != 0 ); + + RMDBGMIDDLE( 4, RMDebug::module_raslib, "r_MiterArea", "repeat dim " << i << ": " << incArrIter[i].repeat ); + } + reset(); + RMDBGEXIT( 1, RMDebug::module_raslib, "r_MiterArea", "r_MiterArea()" ); +} + + +r_MiterArea::~r_MiterArea() +{ + delete [] incArrIter; +} + +void +r_MiterArea::reset() +{ + done = false; + for( int i=0; i<iterDom->dimension(); i++ ) { + incArrIter[i].curr = 0; + } +} + +r_Minterval +r_MiterArea::nextArea() +{ + r_Dimension i = 0; + + if(done) + return retVal; + + r_Minterval currDom(iterDom->dimension()); + + // calculate new result domain here + if(!done) { + for(i=0; i < iterDom->dimension(); i++) { + currDom << r_Sinterval( (*imgDom)[i].low() + incArrIter[i].curr*iterDom->get_extent()[i], + (*imgDom)[i].low() + (incArrIter[i].curr+1)*iterDom->get_extent()[i] + - 1 ); + } + } + retVal = currDom.intersection_with((*imgDom)); + + // increment dimensions + for(i=0; i < iterDom->dimension(); i++) { + incArrIter[i].curr++; + if(incArrIter[i].curr < incArrIter[i].repeat) { + // no overflow in this dimension + break; + } else { + // overflow in this dimension + incArrIter[i].curr = 0; + } + } + if( i == iterDom->dimension() ) { + // overflow in last dimension + done = true; + } + + return retVal; +} + +bool +r_MiterArea::isDone() +{ + return done; +} diff --git a/raslib/mitera.hh b/raslib/mitera.hh new file mode 100644 index 0000000..3784e44 --- /dev/null +++ b/raslib/mitera.hh @@ -0,0 +1,92 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: mitera.hh + * + * MODULE: raslib + * CLASS: r_MiterArea + * +*/ + +#ifndef _D_MITERA_ +#define _D_MITERA_ + +#include "raslib/minterval.hh" + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + r_MiterArea is used for iterating r_Mintervals through larger + r_Mintervals. It is given the domain to be iterated through and + an Minterval specifying the shape of area to be iterated with. + + + Going to the next area is done with nextArea() which returns an + r_Minterval. Test for the end is done with isDone(). The + iterator can be reset with reset(). Iteration starts at the + lowest border in all dimensions. Note that if the shape of + r_Minterval iterated does not completely fit into the + r_Minterval iterated through the results at the border may have + a different (smaller) shape. +*/ + +class r_MiterArea +{ +public: + /// constructor. + /// An exception is thrown if newIterDom and newImgDom have different dimension + r_MiterArea( const r_Minterval* newIterDom, + const r_Minterval* newImgDom ) throw(r_Error); + /** + The pointers are stored, do not delete the objects as long + as the iterator is used! + */ + + /// destructor. + ~r_MiterArea(); + /// resets iterator to beginning. + void reset(); + /// returns current cell and sets iterator to next cell. + r_Minterval nextArea(); + /// returns TRUE if iteration is finished. + bool isDone(); +protected: + // structure storing information on iteration for each dimension + // (perhaps add dimension for reordering later) + typedef struct { + int repeat; // total number of repeats + int curr; // current repeat + } incArrElem; + /// area to be iterated through + const r_Minterval* iterDom; + /// area of tile. + const r_Minterval* imgDom; + /// array with increments + incArrElem* incArrIter; + /// flag set if iteration is finished. + bool done; + /// This is used for the return value in nextArea() + r_Minterval retVal; +}; + +#endif diff --git a/raslib/miterd.cc b/raslib/miterd.cc new file mode 100644 index 0000000..d50c50a --- /dev/null +++ b/raslib/miterd.cc @@ -0,0 +1,117 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * SOURCE: miterd.cc + * + * MODULE: raslib + * CLASS: r_Miter + * +*/ + +#include <iostream> + +#include "raslib/miterd.hh" +#include "raslib/minterval.hh" + + + +r_MiterDirect::r_MiterDirect(void *data, const r_Minterval &total, const r_Minterval &iter, unsigned int tlen, unsigned int step) + : done(false), + dim(total.dimension()), + length(step), + id(NULL), + baseAddress(data) +{ + int i = 0; + r_Range s = tlen; + r_Range offset = 0; + + id=new r_miter_direct_data[dim]; + + for (i=(int)dim-1; i>=0; i--) + { + id[i].low = iter[i].low(); + id[i].high = iter[i].high(); + id[i].pos = id[i].low; + id[i].origin = total[i].low(); + id[i].extent = (total[i].high() - total[i].low() + 1); + id[i].baseStep = s; + id[i].step = s * step; + offset += s * (id[i].pos - id[i].origin); + s *= id[i].extent; + } + for (i=0; i<(int)dim; i++) + { + id[i].data = (void*)(((r_Octet*)data) + offset); + } +} + +r_MiterDirect::~r_MiterDirect(void) +{ + delete [] id; +} + + +void r_MiterDirect::reset(void) +{ + r_Dimension i = 0; + r_ULong offset = 0; + + for (i=0; i<dim; i++) + { + id[i].pos = id[i].low; + offset += id[i].step * (id[i].low - id[i].origin); + } + for (i=0; i<dim; i++) + { + id[i].data = (void*)(((r_Octet*)baseAddress) + offset); + } + done = false; +} + + +void +r_MiterDirect::print_pos(std::ostream &str) const +{ + str << '[' << id[0].pos; + for (r_Dimension i=1; i<dim; i++) str << ',' << id[i].pos; + str << ']'; +} + + + +std::ostream &operator<<(std::ostream &str, const r_MiterDirect &iter) +{ + iter.print_pos(str); + return str; +} + +r_miter_direct_data::r_miter_direct_data() +:data(NULL), pos(0), low(0), high(0), + step(0), baseStep(0), extent(0), origin(0) +{ +} + +r_miter_direct_data::~r_miter_direct_data() +{ +} diff --git a/raslib/miterd.hh b/raslib/miterd.hh new file mode 100644 index 0000000..a4c26d1 --- /dev/null +++ b/raslib/miterd.hh @@ -0,0 +1,165 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: miterd.hh + * + * MODULE: raslib + * CLASS: r_MiterDirect + * +*/ + +#ifndef _R_MITERD_ +#define _R_MITERD_ + +#include "raslib/mddtypes.hh" +#include "raslib/odmgtypes.hh" + +#include <iosfwd> + +class r_Minterval; + +class r_miter_direct_data; + +//@ManMemo: Module {\bf raslib} + +/*@Doc: + r_MiterDirect is similar to r_Miter, but allows stepping by more + than one cell in each direction, arbitrary order of dimensions in + the iteration and has a lot of its internal state variables as public + members. + It should be used in low-level, very time-critical code like + folding operations which would otherwise require construction + of a new iterator for each cell when only position and base + address need to change. +*/ + +class r_MiterDirect +{ + public: + /// constructor + r_MiterDirect(void *data, const r_Minterval &total, const r_Minterval &iter, + r_Bytes tlen, unsigned int step=1); + /** + constructor getting the data, the total domain, the iteration + domain, the base type length and the number of steps per + iteration. + */ + + /// destructor + ~r_MiterDirect(void); + + /// increment the iterator in the default order, i.e. last dimension first + inline r_MiterDirect &operator++(void); + /// increment in user-specified order + inline r_MiterDirect &iterateUserOrder(const r_Dimension *order, const unsigned int *step); + /** + increment the iterator in a user-specified order. order points to an array + defining the order of the dimensions during iteration, e.g. for a 3D + iteration 0,1,2 would iterate over the first dimension first and the + last dimension last wheres 2,1,0 is equivalent to operator++(). step + is the number of steps to do in each dimension. + */ + /// increment or decrement in user-specified order + inline r_MiterDirect &iterateUserOrder(const unsigned int *order, const int *step); + /** + see the other incrementUserOrder method for more details + */ + + /// returns != 0 if iteration is finished. + inline bool isDone(void) const; + /// returns pointer to data during normal iteration. + inline void* getData(void); + /// return pointer to data for non-standard iteration order + inline void* getData(unsigned int *order); + /** + returns pointer to data during user-defined iteration; order is as + defined in iterateUserOrder(). + */ + /// returns number of bytes to step in dimension d in one iteration + inline r_Range getDimStep(r_Dimension d) const; + /// returns number of bytes to step in dimension d when pos changes by 1. + inline r_Bytes getDimBaseStep(r_Dimension d) const; + /// returns extent in dimension d + inline r_Range getExtent(r_Dimension d) const; + /// notify that the position was changed and internal variables need to be recalculated + inline void posChanged( void ); + /// reset the iterator (pos to low and data to baseAddress + offset) + void reset(void); + /// print the position + void print_pos(std::ostream &str) const; + + bool done; + r_miter_direct_data* id; + void* baseAddress; + + private: + + /// if this data should change you must construct a new iterator, + /// therefore no public access. + r_Dimension dim; + r_ULong length; +}; + + + +/*@Doc: + r_miter_direct_data encapsulates data for each dimension. + It's an auxiliary class for r_MiterDirect. The only reason + not to make it a simple struct was data protection. + */ + +class r_miter_direct_data +{ + friend class r_MiterDirect; + + public: + + r_miter_direct_data(); + ~r_miter_direct_data(); + + /// Data concerning the iteration position and domain. May + /// be changed by the user. + void *data; + r_Range pos; + r_Range low; + r_Range high; + + private: + + /// Data concerning the domain of the source object. Is fixed + /// in the constructor. + r_Range step; + r_Range baseStep; + r_Range extent; + r_Range origin; +}; + + +/// overloaded stream operator +extern std::ostream &operator<<(std::ostream &str, const r_MiterDirect &iter); + + + +#include "raslib/miterd.icc" + +#endif diff --git a/raslib/miterd.icc b/raslib/miterd.icc new file mode 100644 index 0000000..a30ec98 --- /dev/null +++ b/raslib/miterd.icc @@ -0,0 +1,166 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/* ------------------------------------------------------------------------ */ +// r_MiterDirect inline functions + +inline bool r_MiterDirect::isDone( void ) const +{ + return done; +} + +inline void *r_MiterDirect::getData( void ) +{ + return id[dim-1].data; +} + +inline void *r_MiterDirect::getData( unsigned int *order ) +{ + return id[order[0]].data; +} + +inline r_Range r_MiterDirect::getDimStep( r_Dimension d ) const +{ + return id[d].step; +} + +inline r_Bytes r_MiterDirect::getDimBaseStep( r_Dimension d ) const +{ + return id[d].baseStep; +} + +inline r_Range r_MiterDirect::getExtent( r_Dimension d ) const +{ + return id[d].extent; +} + +inline r_MiterDirect& +r_MiterDirect::operator++(void) +{ + int d = (int)dim-1; + + while (d >= 0) + { + id[d].pos += length; + id[d].data = (void*)(((char*)(id[d].data)) + id[d].step); + if (id[d].pos <= id[d].high) break; + id[d].pos = id[d].low; + d--; + } + if (d >= 0) + { + int i; + + for (i=d+1; i < (int)dim; i++) + { + id[i].data = id[d].data; + } + } + else + done = true; + + return *this; +} + +inline r_MiterDirect& +r_MiterDirect::iterateUserOrder(const unsigned int *order, const int *step) +{ + r_Dimension d = 0; + + while (d < dim) + { + r_miter_direct_data *idp = id + order[d]; + + idp->pos += step[d]; + idp->data = (void*)(((char*)(idp->data)) + step[d] * idp->baseStep); + if (idp->pos <= idp->high) break; + idp->pos = idp->low; + d++; + } + if (d < dim) + { + r_Dimension i; + void *newData = id[order[d]].data; + + for (i=d; i > 0; i--) + { + id[order[i-1]].data = newData; + } + } + else + done = true; + + return *this; +} + +inline r_MiterDirect& +r_MiterDirect::iterateUserOrder(const r_Dimension *order, const unsigned int *step) +{ + r_Dimension d = 0; + + while (d < dim) + { + r_miter_direct_data *idp = id + order[d]; + + idp->pos += step[d]; + idp->data = (void*)(((char*)(idp->data)) + step[d] * idp->baseStep); + if (step[d] > 0) + { + if (idp->pos <= idp->high) break; + idp->pos = idp->low; + } + else + { + if (idp->pos >= idp->low) break; + idp->pos = idp->high; + } + d++; + } + if (d < dim) + { + r_Dimension i; + void *newData = id[order[d]].data; + + for (i=d; i>0; i--) + { + id[order[i-1]].data = newData; + } + } + else + done = true; + + return *this; +} + + +inline void +r_MiterDirect::posChanged( void ) +{ + r_Range offset = 0; + r_Dimension i = 0; + + for (i=0; i<dim; i++) + offset += id[i].step * (id[i].pos - id[i].origin); + + for (i=0; i<dim; i++) + id[i].data = (void*)(((char*)baseAddress) + offset); +} diff --git a/raslib/miterf.hh b/raslib/miterf.hh new file mode 100644 index 0000000..18f38b6 --- /dev/null +++ b/raslib/miterf.hh @@ -0,0 +1,128 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: miter.hh + * + * MODULE: raslib + * CLASS: r_MiterFloat + * +*/ + +#ifndef _D_MITERF_ +#define _D_MITERF_ + +class r_Minterval; + + +#include "raslib/mddtypes.hh" + +class r_FixedPointNumber + { + public: + inline r_FixedPointNumber(); + inline r_FixedPointNumber(const double&); + + inline r_FixedPointNumber& operator=(const r_FixedPointNumber&); + inline r_FixedPointNumber& operator=(const double&); + + // returns intPart_new - intPart_old -- used for tests + inline r_Range stepForward(const r_FixedPointNumber&); + + // returns carry of fracPart + inline bool stepForwardFlag(const r_FixedPointNumber&); + + inline r_Range getIntPart(); + + private: + inline void init(const double&); + + r_Range intPart; + r_Range fracPart; + + static const int FIXPREC; + static const r_Range carryPos; + static const r_Range fracMask; + static const double fixOne; + + friend std::ostream& operator<<(std::ostream&,r_FixedPointNumber&); + }; + + + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + r_MiterFloat is used for iterating through parts of + multidimensional intervals with arbitrary stepping size using + nearest neighbours. It is given the tile, the source domain + and the destination domain + Apart from that behaviour is exactly as in r_Miter. + +*/ + +class r_MiterFloat + { + public: + /// Constructor getting the source tile, the source domain and the destination domain + inline r_MiterFloat(Tile *sourceTile, r_Minterval& sourceDomain, r_Minterval& destDomain); + + /// destructor + inline ~r_MiterFloat(); + + /// iterator reset + inline void reset(); + + /// get the next cell + inline char* nextCell(); + + /// true if done + inline bool isDone(); + + protected: + struct iter_desc + { + r_FixedPointNumber min; + r_FixedPointNumber pos; + r_FixedPointNumber step; + + r_Range countSteps; + r_Range maxSteps; + + r_Range dimStep; + r_Range scaleStep; + char *cell; + }; + + r_Dimension dim; + char *currentCell; + const char *firstCell; + + iter_desc *iterDesc; + + bool done; + }; + + +#include "miterf.icc" + +#endif diff --git a/raslib/miterf.icc b/raslib/miterf.icc new file mode 100644 index 0000000..dad1b2e --- /dev/null +++ b/raslib/miterf.icc @@ -0,0 +1,222 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * SOURCE: miterf.icc + * + * MODULE: raslib + * CLASS: r_MiterFloat + * +*/ + +#include "raslib/miterf.hh" +#include "raslib/minterval.hh" +#include "raslib/rmdebug.hh" + +#include <math.h> + + +const int r_FixedPointNumber::FIXPREC = 30; +const r_Range r_FixedPointNumber::carryPos = 1<<FIXPREC; +const r_Range r_FixedPointNumber::fracMask = carryPos-1; +const double r_FixedPointNumber::fixOne = pow(2,(double)FIXPREC); + +inline +r_FixedPointNumber::r_FixedPointNumber() + { + intPart=0; fracPart=0; + } + +inline +r_FixedPointNumber::r_FixedPointNumber(const double &d) + { init(d); + } + +inline +r_FixedPointNumber& r_FixedPointNumber::operator=(const r_FixedPointNumber &f) + { + intPart = f.intPart; + fracPart = f.fracPart; + return *this; + } + +inline +r_FixedPointNumber& r_FixedPointNumber::operator=(const double &d) + { + init(d); + return *this; + } + +inline +void r_FixedPointNumber::init(const double &d) + { + intPart = (r_Range)d; + + fracPart= (r_Range)fmod(fixOne*d,fixOne); + + } + +inline +r_Range r_FixedPointNumber::stepForward(const r_FixedPointNumber &f) + { + r_Range oldIntPart = intPart; + + intPart+=f.intPart; fracPart+=f.fracPart; + + if(fracPart & carryPos) + { + intPart++; + fracPart &= fracMask; + + } + return intPart-oldIntPart; + } + +inline +bool r_FixedPointNumber::stepForwardFlag(const r_FixedPointNumber &f) + { + intPart+=f.intPart; fracPart+=f.fracPart; + + if(fracPart & carryPos) + { + intPart++; + fracPart &= fracMask; + return true; + } + return false; + } + +inline +r_Range r_FixedPointNumber::getIntPart() + { + return intPart; + } + +inline +std::ostream& operator<<(std::ostream &os,r_FixedPointNumber &f) + { os<<'('<<f.intPart<<':'<<f.fracPart<<')'; + return os; + } + +//###################################### + +inline +r_MiterFloat::r_MiterFloat(Tile *sourceTile, r_Minterval& sourceDomain, r_Minterval& destDomain) + { + dim = sourceDomain.dimension(); + iterDesc = new iter_desc[dim]; + + r_Bytes cellSize = sourceTile->getType()->getSize(); + firstCell = sourceTile->getContents(); + + iter_desc *id = 0; + const r_Minterval& tileDomain = sourceTile->getDomain(); + + int i = 0; + r_Bytes step = cellSize; + + id = iterDesc + dim-1; + + for(i=dim-1; i>=0; i--, id-- ) + { + id->min = (double)sourceDomain[i].low(); + id->step = (double)(sourceDomain[i].high()-sourceDomain[i].low() +1) / ( destDomain[i].high() - destDomain[i].low()+1); + id->maxSteps = destDomain[i].high() - destDomain[i].low()+1; + id->dimStep = step; + id->scaleStep = step * id->step.getIntPart(); + firstCell += step* (sourceDomain[i].low() - tileDomain[i].low()); + step *= (tileDomain[i].high() - tileDomain[i].low() + 1); + } + reset(); + } + +inline +r_MiterFloat::~r_MiterFloat() + { + if(iterDesc) delete[] iterDesc; + } + +inline +void r_MiterFloat::reset() + { + for(r_Dimension i=0;i<dim;i++) + { + iterDesc[i].pos = iterDesc[i].min; + iterDesc[i].cell = (char*)firstCell; + iterDesc[i].countSteps = iterDesc[i].maxSteps; + } + + done=false; + } + +inline +char* r_MiterFloat::nextCell() + { + if(done) return currentCell; + + r_Dimension i = dim; + iter_desc *id = iterDesc + dim -1; + currentCell = iterDesc[dim-1].cell; + + while( i>0 ) + { + id->countSteps--; + + if(id->countSteps) + {// one more step in this dimension + if(id->pos.stepForwardFlag(id->step)) + id->cell += id->dimStep; + + id->cell += id->scaleStep; + break; + } + else + { // we are finished with this dimension + id->pos = id->min; + id->countSteps = id-> maxSteps; + id--; + i--; + } + } + + if(i<dim) + { + if(i == 0) + done = true; + else + { + r_Dimension j; + for( j=i; j<dim; j++) + iterDesc[j].cell = iterDesc[i-1].cell; + } + } + return currentCell; + } + +inline +bool r_MiterFloat::isDone() + { + return done; + } + + + diff --git a/raslib/odmgtypes.hh b/raslib/odmgtypes.hh new file mode 100644 index 0000000..21354e9 --- /dev/null +++ b/raslib/odmgtypes.hh @@ -0,0 +1,204 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: odmgtypes.hh + * + * MODULE: rasodmg + * + * PURPOSE: + * The file contains ODMG type definitions. + * + * COMMENTS: + * For further porting please adapt the typedef for r_Long and r_Ulong +*/ + +#ifndef _D_ODMGTYPES_ +#define _D_ODMGTYPES_ + +// for type-limits +#include <limits.h> +#include <float.h> + +//@Man: r_Char +//@Type: typedef +//@Args: as unsigned char (1 byte) +//@Memo: Module: {\bf rasodmg}. + +typedef unsigned char r_Char; + +/** + {\tt typedef unsigned char r_Char;} +*/ + + + +//@Man: r_Octet +//@Type: typedef +//@Args: as signed char (1 byte) +//@Memo: Module: {\bf rasodmg}. + +typedef signed char r_Octet; + +/** + {\tt typedef signed char r_Octet;} + (Stroustroup: sign of plain char is implementation-defined) +*/ + + + +//@Man: r_Short +//@Type: typedef +//@Args: as short (2 bytes) +//@Memo: Module: {\bf rasodmg}. + +typedef short r_Short; + +/** + {\tt typedef short r_Short;} +*/ + + + +//@Man: r_UShort +//@Type: typedef +//@Args: as unsigned short (2 bytes) +//@Memo: Module: {\bf rasodmg}. + +typedef unsigned short r_UShort; + +/** + {\tt typedef short r_UShort;} +*/ + + + +//@Man: r_Long +//@Type: typedef +//@Args: as long (4 bytes) +//@Memo: Module: {\bf rasodmg}. + +typedef int r_Long; +/** + {\tt typedef int r_Long;} +*/ + + + + + +//@Man: r_ULong +//@Type: typedef +//@Args: as unsigned long (4 bytes) +//@Memo: Module: {\bf rasodmg}. + +typedef unsigned int r_ULong; +/** + {\tt typedef unsigned long r_ULong;} +*/ + + +//@Man: r_Float +//@Type: typedef +//@Args: as float +//@Memo: Module: {\bf rasodmg}. + +typedef float r_Float; + +/** + {\tt typedef float r_Float;} +*/ + + + +//@Man: r_Double +//@Type: typedef +//@Args: as double +//@Memo: Module: {\bf rasodmg}. + +typedef double r_Double; + +/** + {\tt typedef double r_Double;} +*/ + + + +//@Man: r_Boolean +//@Type: typedef +//@Args: as unsigned char (1 byte) +//@Memo: Module: {\bf rasodmg}. + +typedef unsigned char r_Boolean; + +/** + {\tt typedef unsigned char r_Boolean;} + Changed to unsigned char +*/ + + +//@Man: get_limits() +//@Type: function +//@Args: as function +//@Memo: Module: {\bf rasodmg} + +inline void get_limits( const r_Octet *tptr, double &min, double &max ) +{ + min = (double)SCHAR_MIN; max = (double)SCHAR_MAX; +} + +inline void get_limits( const r_Char *tptr, double &min, double &max ) +{ + min = (double)0.0; max = (double)UCHAR_MAX; +} + +inline void get_limits( const r_Short *tptr, double &min, double &max ) +{ + min = (double)SHRT_MIN; max = (double)SHRT_MAX; +} + +inline void get_limits( const r_UShort *tptr, double &min, double &max ) +{ + min = (double)0.0; max = (double)USHRT_MAX; +} + +inline void get_limits( const r_Long *tptr, double &min, double &max ) +{ + min = (double)INT_MIN; max = (double)INT_MAX; +} + +inline void get_limits( const r_ULong *tptr, double &min, double &max ) +{ + min = (double)0.0; max = (double)UINT_MAX; +} + +inline void get_limits( const r_Float *tptr, double &min, double &max ) +{ + min = -((double)FLT_MAX); max = (double)FLT_MAX; +} + +inline void get_limits( const r_Double *tptr, double &min, double &max ) +{ + min = -((double)DBL_MAX); max = (double)DBL_MAX; +} + +#endif diff --git a/raslib/oid.cc b/raslib/oid.cc new file mode 100644 index 0000000..402aeb3 --- /dev/null +++ b/raslib/oid.cc @@ -0,0 +1,352 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * SOURCE: oid.cc + * + * MODULE: raslib + * CLASS: r_OId + * + * COMMENTS: + * +*/ + +#include "raslib/oid.hh" + +#ifdef __VISUALC__ +#include <strstrea.h> +#else +#include <strstream> +#endif +#include <fstream> +#include <iomanip> +#include <string.h> +#include <stdlib.h> + + +r_OId::r_OId() + : oidString(NULL), + systemName(NULL), + baseName(NULL), + localOId(0) +{ +} + +r_OId::r_OId( const char* initOIdString ) + : oidString(NULL), + systemName(NULL), + baseName(NULL), + localOId(0) +{ + // set oidString + if( initOIdString ) + { + oidString = new char[ strlen(initOIdString)+1 ]; + strcpy( oidString, initOIdString ); + + // + // extract oid parts + // + char* startPtr = NULL; + char* endPtr = NULL; + + // system name + startPtr = endPtr = oidString; + while( *endPtr != '|' && *endPtr != '\0' ) endPtr++; + if( endPtr - startPtr >= 1 ) + { + systemName = new char[ endPtr - startPtr + 1 ]; + strncpy( systemName, startPtr, endPtr - startPtr ); + systemName[endPtr - startPtr] = '\0'; + } + + if( *endPtr != '\0' ) + { + // base name + endPtr++; + startPtr = endPtr; + while( *endPtr != '|' && *endPtr != '\0' ) endPtr++; + if( endPtr - startPtr >= 1 ) + { + baseName = new char[ endPtr - startPtr + 1 ]; + strncpy( baseName, startPtr, endPtr - startPtr ); + baseName[endPtr - startPtr] = '\0'; + } + + if( *endPtr != '\0' ) + { + // local oid + endPtr++; + startPtr = endPtr; + + localOId = atof( startPtr ); + } + + } + + } +} + +r_OId::r_OId( const char* initSystemName, const char* initBaseName, double initLocalOId ) + : oidString(NULL), + systemName(NULL), + baseName(NULL), + localOId( initLocalOId ) +{ + // set members + if( initSystemName ) + { + systemName= new char[ strlen(initSystemName)+1 ]; + strcpy( systemName, initSystemName ); + } + + if( initBaseName ) + { + baseName= new char[ strlen(initBaseName)+1 ]; + strcpy( baseName, initBaseName ); + } + + // allocate buffer which is big enough + int bufferSize = ( systemName ? strlen( systemName ) : 0 ) + + ( baseName ? strlen( baseName ) : 0 ) + + 1024; + char* buffer = new char[bufferSize]; + std::ostrstream oidStream( buffer, bufferSize ); + + // write into the string stream + if( systemName ) + oidStream << systemName << "|"; + else + oidStream << "|"; + + if( baseName ) + oidStream << baseName << "|"; + else + oidStream << "|"; + + oidStream << std::setprecision(50) << localOId << std::ends; + + // allocate memory taking the final string + oidString = new char[strlen(buffer)+1]; + + // copy string + strcpy( oidString, buffer ); + + // delete buffer + delete[] buffer; +} + +r_OId::r_OId( const r_OId& obj ) + : oidString(NULL), + systemName(NULL), + baseName(NULL), + localOId(0) +{ + if( obj.oidString ) + { + oidString= new char[ strlen(obj.oidString)+1 ]; + strcpy( oidString, obj.oidString ); + } + + if( obj.systemName ) + { + systemName= new char[ strlen(obj.systemName)+1 ]; + strcpy( systemName, obj.systemName ); + } + + if( obj.baseName ) + { + baseName= new char[ strlen(obj.baseName)+1 ]; + strcpy( baseName, obj.baseName ); + } + + localOId = obj.localOId; +} + +r_OId::~r_OId() +{ + r_deactivate(); +} + +void +r_OId::r_deactivate() +{ + if( oidString ) + { + delete[] oidString; + oidString = NULL; + } + + if( systemName ) + { + delete[] systemName; + systemName = NULL; + } + + if( baseName ) + { + delete[] baseName; + baseName = NULL; + } +} + +void +r_OId::print_status( std::ostream& s ) const +{ + if( oidString ) + s << oidString; +} + +const r_OId& +r_OId::operator=( const r_OId& obj ) +{ + if( this != &obj ) + { + if( oidString ) + { + delete[] oidString; + oidString = NULL; + } + + if( obj.oidString ) + { + oidString = new char[ strlen(obj.oidString)+1 ]; + strcpy( oidString, obj.oidString ); + } + + if( systemName ) + { + delete[] systemName; + systemName = NULL; + } + + if( obj.systemName ) + { + systemName = new char[ strlen(obj.systemName)+1 ]; + strcpy( systemName, obj.systemName ); + } + + if( baseName ) + { + delete[] baseName; + baseName = NULL; + } + + if( obj.baseName ) + { + baseName = new char[ strlen(obj.baseName)+1 ]; + strcpy( baseName, obj.baseName ); + } + + localOId = obj.localOId; + } + + return *this; +} + +bool +r_OId::operator==( const r_OId& oid ) const +{ + bool equal = false; + + if( oidString && oid.oidString ) + equal = !strcmp( oidString, oid.oidString ); + + return equal; +} + +bool +r_OId::operator!=( const r_OId& oid ) const +{ + return !operator==( oid ); +} + +bool +r_OId::operator> ( const r_OId& oid ) const +{ + int comparison; + + if( systemName && oid.systemName ) + { + comparison = strcmp( systemName, oid.systemName ); + + if( !comparison && baseName && oid.baseName ) + { + comparison = strcmp( baseName, oid.baseName ); + + if( !comparison ) + if( localOId < oid.localOId ) + comparison = -1; + else if( localOId == oid.localOId ) + comparison = 0; + else + comparison = 1; + } + } + + return comparison > 0; +} + +bool +r_OId::operator< ( const r_OId& oid ) const +{ + int comparison; + + if( systemName && oid.systemName ) + { + comparison = strcmp( systemName, oid.systemName ); + + if( !comparison && baseName && oid.baseName ) + { + comparison = strcmp( baseName, oid.baseName ); + + if( !comparison ) + if( localOId < oid.localOId ) + comparison = -1; + else if( localOId == oid.localOId ) + comparison = 0; + else + comparison = 1; + } + } + + return comparison < 0; +} + +bool +r_OId::operator>=( const r_OId& oid ) const +{ + return !operator< ( oid ); +} + +bool +r_OId::operator<=( const r_OId& oid ) const +{ + return !operator> ( oid ); +} + +std::ostream& operator<<( std::ostream& s, const r_OId& oid ) +{ + oid.print_status( s ); + return s; +} + diff --git a/raslib/oid.hh b/raslib/oid.hh new file mode 100644 index 0000000..df2a824 --- /dev/null +++ b/raslib/oid.hh @@ -0,0 +1,137 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: oid.hh + * + * MODULE: raslib + * CLASS: r_OId + * + * COMMENTS: + * The class represents an object identifier (OId). + * +*/ + +#ifndef _D_OID_ +#define _D_OID_ + +#include <iosfwd> + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + Class \Ref{r_OId} represents an object identifier. + +*/ + +class r_OId +{ + public: + /// default constructor + r_OId(); + + /// constructs an OId from the string representation + r_OId( const char* ); + + /// constructor getting oid parts + r_OId( const char* initSystemName, const char* initBaseName, double initLocalOId ); + + /// copy constructor + r_OId( const r_OId& ); + + /// destructor + virtual ~r_OId(); + + /// it is called when an object leaves transient memory + virtual void r_deactivate(); + + /// debug output + void print_status(std::ostream& s) const; + + /// operator for assigning an oid + const r_OId& operator= ( const r_OId& ); + + //@Man: Comparison operators: + //@{ + /// + + /// operator for equality + bool operator==( const r_OId& ) const; + + /// operator for not equal + bool operator!=( const r_OId& ) const; + + /// operator for greater than + bool operator> ( const r_OId& ) const; + + /// operator for less than + bool operator< ( const r_OId& ) const; + + /// operator for greater or equal than + bool operator>=( const r_OId& ) const; + + /// operator for less than or equal + bool operator<=( const r_OId& ) const; + + /// + //@} + + /// gets the oid's string representation + inline const char* get_string_representation() const; + + /// get system name + inline const char* get_system_name() const; + + /// get base name + inline const char* get_base_name() const; + + /// get local oid + inline double get_local_oid() const; + + /// determines if oid is valid + inline bool is_valid() const; + + private: + /// string representation + char* oidString; + + /// system name + char* systemName; + + /// base name + char* baseName; + + /// local oid + double localOId; +}; + + + +//@ManMemo: Module: {\bf raslib} +/** + Output stream operator for objects of type {\tt const} \Ref{r_Oid}. +*/ +extern std::ostream& operator<<( std::ostream& s, const r_OId& oid ); + +#include "raslib/oid.icc" +#endif diff --git a/raslib/oid.icc b/raslib/oid.icc new file mode 100644 index 0000000..70b0ab1 --- /dev/null +++ b/raslib/oid.icc @@ -0,0 +1,62 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INLINE SOURCE: oid.icc + * + * MODULE: raslib + * CLASS: r_OId + * + * COMMENTS: + * +*/ + +inline const char* +r_OId::get_string_representation() const +{ + return oidString; +} + +inline const char* +r_OId::get_system_name() const +{ + return systemName; +} + +inline const char* +r_OId::get_base_name() const +{ + return baseName; +} + +inline double +r_OId::get_local_oid() const +{ + return localOId; +} + +inline bool +r_OId::is_valid() const +{ + return localOId != 0; +} + diff --git a/raslib/oidtype.cc b/raslib/oidtype.cc new file mode 100644 index 0000000..df751c9 --- /dev/null +++ b/raslib/oidtype.cc @@ -0,0 +1,80 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +static const char rcsid[] = "@(#)raslib, r_Oid_Type: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/oidtype.cc,v 1.6 2003/12/27 23:01:21 rasdev Exp $"; + +#include "raslib/oidtype.hh" + +r_Oid_Type::r_Oid_Type() + : r_Type() +{ +} + +bool +r_Oid_Type::isOidType() const + { + return true; + } + +r_Oid_Type::r_Oid_Type( const r_Oid_Type& oldObj ) + : r_Type(oldObj) +{ +} + +r_Type* +r_Oid_Type::clone() const +{ + return new r_Oid_Type( *this ); +} + +r_Type::r_Type_Id +r_Oid_Type::type_id() const +{ + return OIDTYPE; +} + +void +r_Oid_Type::convertToLittleEndian(char* cells, r_Area noCells) const +{ +} + +void +r_Oid_Type::convertToBigEndian(char* cells, r_Area noCells) const +{ +} + +void +r_Oid_Type::print_status( std::ostream& s ) const +{ + s << "oid"; +} + +r_Oid_Type::~r_Oid_Type() +{ +} + +std::ostream &operator<<( std::ostream &str, const r_Oid_Type &type ) +{ + type.print_status(str); + return str; +} diff --git a/raslib/oidtype.hh b/raslib/oidtype.hh new file mode 100644 index 0000000..e3018de --- /dev/null +++ b/raslib/oidtype.hh @@ -0,0 +1,79 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: oidtype.hh + * + * MODULE: raslib + * CLASS: r_Oid_Type + * + * COMMENTS: + * +*/ + +#ifndef _D_OID_TYPE_ +#define _D_OID_TYPE_ + +#include "raslib/type.hh" + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + This class represents the oid type in the ODMG conformant + representation of the RasDaMan type system. +*/ + +class r_Oid_Type : public r_Type +{ +public: + /// default constructor + r_Oid_Type(); + + /// copy constructor + r_Oid_Type( const r_Oid_Type& oldObj ); + + /// clone operation + virtual r_Type* clone() const; + + /// retrieve id of the type. + virtual r_Type::r_Type_Id type_id() const; + + /// converts array of cells from NT byte order to Unix byte order. + virtual void convertToLittleEndian(char* cells, r_Area noCells) const; + + /// converts array of cells from Unix byte order to NT byte order. + virtual void convertToBigEndian(char* cells, r_Area noCells) const; + + /// writes state of object to specified stream + virtual void print_status( std::ostream& s = std::cout ) const; + + virtual bool isOidType() const; + + /// destructor + ~r_Oid_Type(); +}; + +//@Doc: write the status of a oid type to a stream +extern std::ostream &operator<<( std::ostream &str, const r_Oid_Type &type ); + +#endif + diff --git a/raslib/parseparams.cc b/raslib/parseparams.cc new file mode 100644 index 0000000..963d68f --- /dev/null +++ b/raslib/parseparams.cc @@ -0,0 +1,283 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: parseparams.cc + * + * MODULE: raslib + * CLASS: r_Parse_Params + * + * COMMENTS: + * +*/ + +#include "mymalloc/mymalloc.h" + +#include <cstdio> +#include <cstdlib> +#include <cctype> +#include <cstring> +#include <cerrno> + +extern int errno; + +#include "raslib/rminit.hh" +#include "raslib/rmdebug.hh" + +#include "raslib/parseparams.hh" + + + +const unsigned int r_Parse_Params::granularity = 4; + +r_Parse_Params::r_Parse_Params( void ) +{ + params = NULL; + number = 0; + maxnum = 0; +} + + +r_Parse_Params::r_Parse_Params( unsigned int num ) +{ + number = 0; + maxnum = num; + params = (parse_params_t*)mymalloc(maxnum * sizeof(parse_params_t)); +} + + +r_Parse_Params::~r_Parse_Params( void ) +{ + if (params != NULL) + free(params); +} + + +int r_Parse_Params::add( const char *key, void *store, parse_param_type type ) +{ + + RMDBGONCE(2, RMDebug::module_raslib, "r_Parse_Params", "add('" + << (key?key:"NULL") << "', " + << (store?store:"NULL") << "," + << type << ")"); + + if (number >= maxnum) + { + maxnum += granularity; + if (params == NULL) + params = (parse_params_t*)mymalloc(maxnum * sizeof(parse_params_t)); + else + params = (parse_params_t*)realloc(params, maxnum * sizeof(parse_params_t)); + + if (params == NULL) + { + maxnum = 0; return -1; + } + } + params[number].key = key; + params[number].store = store; + params[number].type = type; + number++; + + return 0; +} + + +int r_Parse_Params::process( const char *str ) const +{ + static const int lenBuff=256; + static char buff[lenBuff]; + int numkeys = 0; + const char *b = str; + + RMDBGONCE(2, RMDebug::module_raslib, "r_Parse_Params", "process('" << (str?str:"NULL") << ")"); + + if ( (number == 0) || + (str == NULL) || + (!strcmp(str,"")) ) { + return 0; + } + + while (*b != '\0') + { + //cout << numkeys << '(' << b << ')' << std::endl; + while ((isspace((unsigned int)(*b))) || (*b == ',')) b++; + if (*b == '\0') break; + if (isalpha((unsigned int)(*b))) + { + const char *key = b; + unsigned int klen; + int knum; + int inquotes; + + while (isalnum((unsigned int)(*b))) b++; + + //store current item + klen = (b - key); + memset(buff,0, lenBuff); + memcpy(buff, key, klen); + for (knum=0; knum<number; knum++) + { + if (strcmp(buff, params[knum].key) == 0) + break; + } + // we actually understand this key + if (knum < number) + { + int statval = 0; // status: -1 error, 0 not found, 1 OK + + while (isspace((unsigned int)(*b))) b++; + if (*b == '=') + { + b++; + while (isspace((unsigned int)(*b))) b++; + if ((*b != ',') && (*b != '\0')) + { + const char *aux=b; + + switch (params[knum].type) + { + case param_type_int: + { + int val=0; + + errno=0; + val = strtol(b, (char**)&aux, 10); + if ((b == aux) || errno) + statval = -1; + else + { + int *vptr = (int*)(params[knum].store); + *vptr = val; + b = aux; statval = 1; + } + } + break; + case param_type_double: + { + double val=0.; + + errno=0; + val = strtod(b, (char**)&aux); + if ((b == aux) || errno) + statval = -1; + else + { + double *vptr = (double*)(params[knum].store); + *vptr = val; + b = aux; statval = 1; + } + } + break; + case param_type_string: + { + unsigned int vlen = 0; + + if (*b == '\"') + { + aux = ++b; + while ((*b != '\"') && (*b != '\0')) b++; + if (*b == '\0') + statval = -1; + else + { + vlen = (b - aux); + b++; statval = 1; + } + } + else + { + aux = b; + while ((!isspace((unsigned int)(*b))) && (*b != '\0') && (*b != ',')) b++; + vlen = (b - aux); statval = 1; + } + if (vlen > 0) + { + char **vptr = (char**)(params[knum].store); + if (*vptr != NULL) + delete [] *vptr; + *vptr = new char[vlen+1]; + strncpy(*vptr, aux, vlen); + (*vptr)[vlen] = '\0'; + } + } + break; + } + } + } + switch (statval) + { + case -1: + RMInit::logOut << "r_Parse_Params::process('" << str << "'): error parsing value for keyword " << params[knum].key << std::endl; + return -1; + case 0: + RMInit::logOut << "r_Parse_Params::process('" << str << "'): keyword " << params[knum].key << " without value" << std::endl; + return -1; + case 1: + numkeys++; + break; + default: + break; + } + } + inquotes = 0; + while (((*b != ',') || (inquotes != 0)) && (*b != '\0')) + { + if (*b == '\"') + inquotes ^= 1; + b++; + } + if (inquotes != 0) + { + RMInit::logOut << "r_Parse_Params::process('" << str << "'): unterminated string" << std::endl; + return -1; + } + } + else + { + RMInit::logOut << "r_Parse_Params::process('" << str << "'): the string must start with alphabetic character" << std::endl; + return -1; + } + } + + return numkeys; +} + +std::ostream& operator<<( std::ostream& s, const r_Parse_Params::parse_param_type& d ) +{ + switch( d ) + { + case r_Parse_Params::param_type_int: + s << "param_type_int"; + break; + case r_Parse_Params::param_type_double: + s << "param_type_double"; + break; + case r_Parse_Params::param_type_string: + s << "param_type_string"; + break; + default: + s << "UNKNOWN r_Parse_Params::parse_paramt_type" << d; + break; + } + return s; +} diff --git a/raslib/parseparams.hh b/raslib/parseparams.hh new file mode 100644 index 0000000..b5ebed6 --- /dev/null +++ b/raslib/parseparams.hh @@ -0,0 +1,116 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: parseparams.hh + * + * MODULE: raslib + * CLASS: r_Parse_Params + * + * COMMENTS: + * +*/ + +#ifndef _PARSE_PARAMS_HH_ +#define _PARSE_PARAMS_HH_ + +#include <iosfwd> + +//@ManMemo: Module {\bf raslib} + +/*@Doc: + Class for parsing a string consisting of key=value pairs separated by ",". +*/ + +class r_Parse_Params +{ +public: + + /// the possible parameter types used for add() + enum parse_param_type { + param_type_int, + param_type_double, + param_type_string + }; + /** + Possible parameter types and their corresponding C types are + + \begin{tabular}{ll} + param_type_int && int\\ + param_type_double && double\\ + param_type_string && char*\\ + \end{tabular} + */ + + struct parse_params_s; + + /// default constructor, should not be used + r_Parse_Params( void ); + /// constructor, gets descriptor of the values to scan for + r_Parse_Params( unsigned int num ); + /// destructor + ~r_Parse_Params( void ); + /// add parameters to the list + int add( const char *key, void *store, parse_param_type type ); + /** + Add a parameter to the list. key is the keyword, e.g. ``quality'', type + is one of the available types and describes the data type of the parameter + and store is a pointer to a variable of this type that will be updated + by process() if the parameter is encountered there. The variable pointed + to by store must not be initalized except for param_type_string where it + must be set to NULL before calling process() for the first time. The contents + of a string variable must be freed by the caller by first checking whether + the variable is NULL and if not doing a delete [] <var>. + */ + /// process parameter string + int process( const char *str ) const; + /** + process the parameter string. Returns the number of keywords found + or -1 for error. + */ + + +protected: + //@Man: The parameter descriptor + //@{ + typedef struct parse_params_s { + const char *key; + void *store; + parse_param_type type; + } parse_params_t; + //@} + + parse_params_t *params; + unsigned int maxnum; + unsigned int number; + + static const unsigned int granularity; +}; + +//@ManMemo: Module: {\bf raslib} +/** + Output stream operator for objects of type {\tt const} \Ref{r_Parse_Params::parse_param_type}. + */ +extern std::ostream& operator<<( std::ostream& s, const r_Parse_Params::parse_param_type& d ); + + +#endif diff --git a/raslib/point.cc b/raslib/point.cc new file mode 100644 index 0000000..8679dc5 --- /dev/null +++ b/raslib/point.cc @@ -0,0 +1,372 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * SOURCE: point.cc + * + * MODULE: raslib + * CLASS: r_Point + * + * COMMENTS: + * +*/ + +static const char rcsid[] = "@(#)raslib, r_Point: $Id: point.cc,v 1.22 2002/08/28 11:58:13 coman Exp $"; + +#include "point.hh" + +#include <string.h> +#ifdef __VISUALC__ +#include <strstrea.h> +#else +#include <strstream> +#endif + +#include "raslib/rminit.hh" +#include "raslib/error.hh" + +r_Point::r_Point( char* stringRep ) throw (r_Error) + : dimensionality(1), streamInitCnt(0), points(NULL) +{ + char charToken = 0; + r_Range valueToken = 0; + + // for parsing the string + std::istrstream str( stringRep, strlen(stringRep) + 1 ); + + // calculate dimensionality + char* p = stringRep; + while(p = strchr(++p, ',')) + dimensionality++; + + // allocate space for intervals + points = new r_Range[ dimensionality ]; + + str >> charToken; + if(charToken != '[') + { + // error + dimensionality = 0; + delete[] points; + points = NULL; + throw r_Error(NOPOINT); + } + + for( r_Dimension i=0; i<dimensionality; i++ ) + { + str >> valueToken; + points[i] = valueToken; + + if( i < dimensionality-1 ) + { + str >> charToken; + if(charToken != ',') + { + // error + dimensionality = 0; + delete[] points; + points = NULL; + throw r_Error(NOPOINT); + } + } + } +} + + +r_Point::r_Point( r_Dimension dim ) + : dimensionality( dim ), + streamInitCnt(0) +{ + points = new r_Range[ dimensionality ]; + + for( r_Dimension i=0; i< dimensionality; i++ ) + points[i] = 0; +} + + +r_Point& r_Point::operator<<( r_Range newElement ) throw( r_Einit_overflow ) +{ + if( streamInitCnt >= dimensionality ) + { + RMInit::logOut << "r_Point::operator<<(" << newElement << ") already fully initialised" << endl; + throw r_Einit_overflow(); + } + + points[streamInitCnt++] = newElement; + return *this; +} + + +r_Point::r_Point( r_Range p1, r_Range p2 ) + : dimensionality(2), + streamInitCnt(2) +{ + points = new r_Range[dimensionality]; + points[0] = p1; + points[1] = p2; +} + + +r_Point::r_Point( r_Range p1, r_Range p2, r_Range p3 ) + : dimensionality(3), + streamInitCnt(3) +{ + points = new r_Range[dimensionality]; + points[0] = p1; + points[1] = p2; + points[2] = p3; +} + + +r_Point::r_Point( r_Range p1, r_Range p2, r_Range p3, r_Range p4 ) + : dimensionality(4), + streamInitCnt(4) +{ + points = new r_Range[dimensionality]; + points[0] = p1; + points[1] = p2; + points[2] = p3; + points[3] = p4; +} + + +r_Point::r_Point( r_Range p1, r_Range p2, r_Range p3, r_Range p4, r_Range p5 ) + : dimensionality(5), + streamInitCnt(5) +{ + points = new r_Range[dimensionality]; + points[0] = p1; + points[1] = p2; + points[2] = p3; + points[3] = p4; + points[4] = p5; +} + + +r_Point::r_Point() + : dimensionality(0), + streamInitCnt(0), + points(NULL) +{ +} + + +r_Point::r_Point( const r_Point& pt ) + : dimensionality(pt.dimensionality), + streamInitCnt(pt.streamInitCnt), + points(new r_Range[pt.dimensionality]) +{ + for( r_Dimension i=0; i<dimensionality; i++ ) + points[i] = pt[i]; +} + + +r_Point::~r_Point() +{ + if( points ) + { + delete[] points; + points = NULL; + } +} + + +r_Range +r_Point::operator[]( r_Dimension i ) const throw( r_Eindex_violation ) +{ + if( i < 0 || i >= dimensionality ) + { + RMInit::logOut << "r_Point::operator[](" << i << ") const dimension out of bounds (" << dimensionality << ")" << endl; + throw r_Eindex_violation( 0, dimensionality-1, i ); + } + + return points[i]; +} + + +r_Range& +r_Point::operator[]( r_Dimension i ) throw( r_Eindex_violation ) +{ + if( i < 0 || i >= dimensionality ) + { + RMInit::logOut << "r_Point::operator[](" << i << ") dimension out of bounds (" << dimensionality << ")" << endl; + throw r_Eindex_violation( 0, dimensionality-1, i ); + } + + return points[i]; +} + + +const r_Point& +r_Point::operator=( const r_Point& pt ) +{ + if( this != &pt ) + { + if( points && dimensionality != pt.dimension() ) + { + delete[] points; + points = NULL; + } + + dimensionality = pt.dimension(); + streamInitCnt = dimensionality; + + if( !points ) + points = new r_Range[ dimensionality ]; + + for( r_Dimension i=0; i<dimensionality; i++ ) + points[i] = pt[i]; + + } + + return *this; +} + + + +bool +r_Point::operator==( const r_Point& pt ) const +{ + bool returnValue = false; + + if( dimensionality == pt.dimensionality ) + { + returnValue = true; + + for( r_Dimension i=0; i<dimensionality && returnValue ; i++ ) + { + if (points[i] != pt[i]) + { + returnValue = false; + break; + } + } + } + + return returnValue; +} + + + +bool +r_Point::operator!=( const r_Point& pt ) const +{ + return !operator==( pt ); +} + + + +r_Point +r_Point::operator+( const r_Point& pt ) const throw( r_Edim_mismatch ) +{ + if( dimensionality != pt.dimension() ) + { + RMInit::logOut << "r_Point::operator+(" << pt << ") dimensions (" << dimensionality << ") do not match" << endl; + throw r_Edim_mismatch( dimensionality, pt.dimension() ); + } + + r_Point result( dimensionality ); + + for( r_Dimension i=0; i<dimensionality; i++ ) + result[i] = points[i] + pt[i]; + + return result; +} + +r_Point +r_Point::operator-( const r_Point& pt ) const throw( r_Edim_mismatch ) +{ + if( dimensionality != pt.dimension() ) + { + RMInit::logOut << "r_Point::operator-(" << pt << ") dimensions (" << dimensionality << ") do not match" << endl; + throw r_Edim_mismatch( dimensionality, pt.dimension() ); + } + + r_Point result( dimensionality ); + + for( r_Dimension i=0; i<dimensionality; i++ ) + result[i] = points[i] - pt[i]; + + return result; +} + +r_Point +r_Point::operator*( const r_Point& pt ) const throw( r_Edim_mismatch ) +{ + if( dimensionality != pt.dimension() ) + { + RMInit::logOut << "r_Point::operator*(" << pt << ") dimensions (" << dimensionality << ") do not match" << endl; + throw r_Edim_mismatch( dimensionality, pt.dimension() ); + } + + r_Point result( dimensionality ); + + for( r_Dimension i=0; i<dimensionality; i++ ) + result[i] = points[i] * pt[i]; + + return result; +} + +void +r_Point::print_status( std::ostream& s ) const +{ + s << "["; + + if( dimensionality > 0 ) + { + for( r_Dimension i=0; i<dimensionality-1; i++ ) + s << points[i] << ","; + + s << points[dimensionality-1]; + } + + s << "]"; +} + + +char* +r_Point::get_string_representation() const +{ + r_Bytes bufferSize = dimensionality*25+3; // should be enough + + // allocate buffer and initialize string stream + char* buffer = new char[bufferSize]; + std::ostrstream domainStream( buffer, bufferSize ); + + // write into string stream + domainStream << (*this) << std::ends; + + // allocate memory taking the final string + char* returnString = strdup(buffer); + + // delete buffer + delete[] buffer; + + return returnString; +} + +std::ostream& operator<<( std::ostream& s, const r_Point& d ) +{ + d.print_status( s ); + return s; +} + diff --git a/raslib/point.hh b/raslib/point.hh new file mode 100644 index 0000000..6f6e634 --- /dev/null +++ b/raslib/point.hh @@ -0,0 +1,165 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: point.hh + * + * MODULE: raslib + * CLASS: r_Point + * + * COMMENTS: + * +*/ + +#ifndef _D_POINT_ +#define _D_POINT_ + +#ifdef __VISUALC__ +// disable warning for exception specification +#pragma warning( disable : 4290 ) +#endif + +class r_Error; +class r_Einit_overflow; +class r_Eindex_violation; +class r_Edim_mismatch; + +#include "raslib/mddtypes.hh" +#include "raslib/error.hh" + +#include <iostream> + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + Class \Ref{r_Point} represents an n-dimensional point vector. + +*/ + +class r_Point +{ + public: + /// constructor getting dimensionality for stream initializing + r_Point( r_Dimension ); + + /// stream-input operator for stream initializing + r_Point& operator<<( r_Range ) throw( r_Einit_overflow ); + + /// constructor taking string representation (e.g. [ 1, 2, 3]) + r_Point( char* ) throw( r_Error ); + + //@Man: 'easy-to-use' constructors + //@{ + /// + r_Point( r_Range, r_Range ); + /// + r_Point( r_Range, r_Range, r_Range ); + /// + r_Point( r_Range, r_Range, r_Range, r_Range ); + /// + r_Point( r_Range, r_Range, r_Range, r_Range, r_Range ); + /// + //@} + + /// default constructor + r_Point(); + + /// copy constructor + r_Point( const r_Point& ); + + /// destructor: cleanup dynamic memory + ~r_Point(); + + /// subscriptor for read access + r_Range operator[]( r_Dimension ) const throw( r_Eindex_violation ); + /// subscriptor for write access + r_Range& operator[]( r_Dimension ) throw( r_Eindex_violation ); + + /// assignment: cleanup + copy + const r_Point& operator= ( const r_Point& ); + + /// compares this point with the given point. + inline const int compare_with( const r_Point& p ) const; + /** + Returns 0 if this == p, -1 if this < p, 1 if this > p (considering + the coordinates in decreasing order of magnitude). + */ + + /// equal operator + bool operator==( const r_Point& ) const; + + /** + Two points are equal if they have the same number of dimensions and + the same values. + */ + + /// non equal operator - negation of equal operator + bool operator!=( const r_Point& ) const; + + /// vector addition + r_Point operator+( const r_Point& ) const + throw( r_Edim_mismatch ); + + /// vector subtraction + r_Point operator-( const r_Point& ) const + throw( r_Edim_mismatch ); + + /// vector multiplication + r_Point operator*( const r_Point& ) const + throw( r_Edim_mismatch ); + + /// get dimensionality + inline r_Dimension dimension() const; + + /// writes the state of the object to the specified stream + void print_status( std::ostream& s = std::cout ) const; + + /// gives back the string representation + char* get_string_representation() const; + /** + The string representation delivered by this method is allocated using {\tt malloc()} and + has to be free unsing {\tt free()} in the end. It can be used to construct a {\tt r_Point} + again with a special constructor provided. The string representation is build using + {\tt print_status()}. + */ + + private: + /// array holding the point coordinates + r_Range* points; + /// dimensionality of the point + r_Dimension dimensionality; + /// number of components initialized already + r_Dimension streamInitCnt; +}; + + + +//@ManMemo: Module: {\bf raslib} +/** + Output stream operator for objects of type {\tt const} \Ref{r_Point}. +*/ +extern std::ostream& operator<<( std::ostream& s, const r_Point& d ); + +#include "raslib/point.icc" + +#endif diff --git a/raslib/point.icc b/raslib/point.icc new file mode 100644 index 0000000..5bbbd27 --- /dev/null +++ b/raslib/point.icc @@ -0,0 +1,54 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INLINE SOURCE: point.icc + * + * MODULE: raslib + * CLASS: r_Point + * + * COMMENTS: + * +*/ + +inline r_Dimension +r_Point::dimension() const +{ + return dimensionality; +}; + +const int +r_Point::compare_with( const r_Point& p ) const +{ + if( dimensionality != p.dimensionality ) + return -2; + + for ( r_Dimension i = 0; i < dimensionality; i++ ) + { + if ( points[i] > p[i] ) + return 1; + if ( points[i] < p[i] ) + return -1 ; + } + return 0; +} + diff --git a/raslib/pointtype.cc b/raslib/pointtype.cc new file mode 100644 index 0000000..0a4f1a0 --- /dev/null +++ b/raslib/pointtype.cc @@ -0,0 +1,81 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +static const char rcsid[] = "@(#)raslib, r_Point_Type: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/pointtype.cc,v 1.6 2003/12/27 23:01:21 rasdev Exp $"; + +#include "raslib/pointtype.hh" + +r_Point_Type::r_Point_Type() + : r_Type() +{ +} + +r_Point_Type::r_Point_Type( const r_Point_Type& oldObj ) + : r_Type(oldObj) +{ +} + +r_Type* +r_Point_Type::clone() const +{ + return new r_Point_Type( *this ); +} + +r_Type::r_Type_Id +r_Point_Type::type_id() const +{ + return POINTTYPE; +} + +void +r_Point_Type::convertToLittleEndian(char* cells, unsigned int noCells) + const +{ +} + +void +r_Point_Type::convertToBigEndian(char* cells, unsigned int noCells) const +{ +} + +void +r_Point_Type::print_status( std::ostream& s ) const +{ + s << "point"; +} + +r_Point_Type::~r_Point_Type() +{ +} + +bool +r_Point_Type::isPointType() const + { + return true; + } + +std::ostream &operator<<( std::ostream &str, const r_Point_Type &type ) +{ + type.print_status(str); + return str; +} diff --git a/raslib/pointtype.hh b/raslib/pointtype.hh new file mode 100644 index 0000000..53a1d26 --- /dev/null +++ b/raslib/pointtype.hh @@ -0,0 +1,81 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: pointtype.hh + * + * MODULE: raslib + * CLASS: r_Point_Type + * + * COMMENTS: + * +*/ + +#ifndef _D_POINT_TYPE_ +#define _D_POINT_TYPE_ + +#include "raslib/type.hh" + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + This class represents the point type in the ODMG conformant + representation of the RasDaMan type system. +*/ + +class r_Point_Type : public r_Type +{ +public: + /// default constructor + r_Point_Type(); + + /// copy constructor + r_Point_Type( const r_Point_Type& oldObj ); + + /// clone operation + virtual r_Type* clone() const; + + /// retrieve id of the type. + virtual r_Type::r_Type_Id type_id() const; + + /// converts array of cells from NT byte order to Unix byte order. + virtual void convertToLittleEndian(char* cells, unsigned int noCells) const; + + /// converts array of cells from Unix byte order to NT byte order. + virtual void convertToBigEndian(char* cells, unsigned int noCells) const; + + /// writes state of object to specified stream + virtual void print_status( std::ostream& s = std::cout ) const; + + virtual bool isPointType() const; + + /// destructor + ~r_Point_Type(); +}; + +//@Doc: write the status of point type to a stream +extern std::ostream &operator<<( std::ostream &str, const r_Point_Type &type ); + +#endif + + + diff --git a/raslib/primitive.cc b/raslib/primitive.cc new file mode 100644 index 0000000..a9ffc1e --- /dev/null +++ b/raslib/primitive.cc @@ -0,0 +1,439 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * SOURCE: primitive.cc + * + * MODULE: raslib + * CLASS: r_Primitive + * + * COMMENTS: + * +*/ + +#include "mymalloc/mymalloc.h" + +#include "raslib/primitive.hh" +#include "raslib/primitivetype.hh" +#include "raslib/rminit.hh" +#include "raslib/error.hh" + +#ifdef __VISUALC__ +#include <strstrea.h> +#else +#include <strstream> +#endif +#include <string.h> +#include <fstream> +#include <stdlib.h> + +r_Primitive::r_Primitive( const char* newBuffer, const r_Primitive_Type* newType ) + : r_Scalar( newType ) +{ + if( valueType ) + { + valueBuffer = (char*)mymalloc( valueType->size() ); + if( newBuffer) + memcpy( (void*)valueBuffer, (void*)newBuffer, valueType->size() ); + else + memset( (void*)valueBuffer, 0, valueType->size() ); + } +} + +r_Primitive::r_Primitive( const r_Primitive& obj ) + : r_Scalar( obj ), + valueBuffer(NULL) +{ + valueBuffer = (char*)mymalloc( valueType->size() ); + if( obj.valueBuffer ) + memcpy( (void*)valueBuffer, (void*)obj.valueBuffer, valueType->size() ); + else + memset( (void*)valueBuffer, 0, valueType->size()); +} + +r_Primitive::~r_Primitive() +{ + if( valueBuffer ) free( valueBuffer ); +} + +bool +r_Primitive::isPrimitive() const + { + return true; + } + +r_Scalar* +r_Primitive::clone() const +{ + return new r_Primitive( *this ); +} + + + +const r_Primitive& +r_Primitive::operator=( const r_Primitive& obj ) +{ + if( this != &obj ) + { + // assign scalar + r_Scalar::operator=( obj ); + + if( valueBuffer ) + { + free( valueBuffer ); + valueBuffer = NULL; + } + + if( valueType ) + { + valueBuffer = (char*)mymalloc( valueType->size() ); + if( obj.valueBuffer ) + memcpy( (void*)valueBuffer, (void*)obj.valueBuffer, valueType->size() ); + else + memset((void*)valueBuffer, 0, valueType->size()); + } + } + + return *this; +} + + + +const char* +r_Primitive::get_buffer() const +{ + return valueBuffer; +} + + + +void +r_Primitive::print_status( std::ostream& s ) const +{ + if( valueType && valueBuffer ) + valueType->print_value( valueBuffer, s ); + else + s << "<nn>" << std::flush; +} + + + +r_Boolean +r_Primitive::get_boolean() const throw( r_Error ) +{ + if( !valueBuffer || !valueType ) + { + RMInit::logOut << "r_Primitive::get_boolean() buffer null or type null " << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + return ((r_Primitive_Type*)valueType)->get_boolean(valueBuffer); +} + + + +r_Char +r_Primitive::get_char() const throw( r_Error ) +{ + if( !valueBuffer || !valueType) + { + RMInit::logOut << "r_Primitive::get_char() buffer null or type null" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + return ((r_Primitive_Type*)valueType)->get_char(valueBuffer); +} + + + +r_Octet +r_Primitive::get_octet() const throw( r_Error ) +{ + if( !valueBuffer || !valueType ) + { + RMInit::logOut << "r_Primitive::get_octet() buffer null or type null" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + return ((r_Primitive_Type*)valueType)->get_octet(valueBuffer); +} + + + +r_Short +r_Primitive::get_short() const throw( r_Error ) +{ + if( !valueBuffer || !valueType ) + { + RMInit::logOut << "r_Primitive::get_short() buffer null or type null" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + return ((r_Primitive_Type*)valueType)->get_short(valueBuffer); +} + + + +r_UShort +r_Primitive::get_ushort() const throw( r_Error ) +{ + if( !valueBuffer || !valueType ) + { + RMInit::logOut << "r_Primitive::get_ushort() buffer null or type null" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + return ((r_Primitive_Type*)valueType)->get_ushort(valueBuffer); +} + + + +r_Long +r_Primitive::get_long() const throw( r_Error ) +{ + if( !valueBuffer || !valueType ) + { + RMInit::logOut << "r_Primitive::get_long() buffer null or type null" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + return ((r_Primitive_Type*)valueType)->get_long(valueBuffer); +} + + + +r_ULong +r_Primitive::get_ulong() const throw( r_Error ) +{ + if( !valueBuffer || !valueType ) + { + RMInit::logOut << "r_Primitive::get_ulong() buffer null or type null" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + return ((r_Primitive_Type*)valueType)->get_ulong(valueBuffer); +} + + + +r_Float +r_Primitive::get_float() const throw( r_Error ) +{ + if( !valueBuffer || !valueType ) + { + RMInit::logOut << "r_Primitive::get_float() buffer null or type null" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + return ((r_Primitive_Type*)valueType)->get_float(valueBuffer); +} + + + +r_Double +r_Primitive::get_double() const throw( r_Error ) +{ + if( !valueBuffer || !valueType ) + { + RMInit::logOut << "r_Primitive::get_double() buffer null or type null" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + return ((r_Primitive_Type*)valueType)->get_double(valueBuffer); +} + + +void +r_Primitive::set_boolean(r_Boolean val) throw( r_Error ) +{ + if( !valueType || valueType->type_id() != r_Type::BOOL ) + { + RMInit::logOut << "r_Primitive::set_boolean(" << val << ") not a boolean" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + if( !valueBuffer ) + valueBuffer = (char*)mymalloc( valueType->size()); + + memmove(valueBuffer, &val, valueType->size()); +} + + + +void +r_Primitive::set_char(r_Char val) throw( r_Error ) +{ + if( !valueType || valueType->type_id() != r_Type::CHAR ) + { + RMInit::logOut << "r_Primitive::set_char(" << val << ") not a char" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + if( !valueBuffer ) + valueBuffer = (char*)mymalloc( valueType->size()); + + memmove(valueBuffer, &val, valueType->size()); +} + + + +void +r_Primitive::set_octet(r_Octet val) throw( r_Error ) +{ + if( !valueType || valueType->type_id() != r_Type::OCTET ) + { + RMInit::logOut << "r_Primitive::set_octet(" << val << ") not a octet" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + if( !valueBuffer ) + valueBuffer = (char*)mymalloc( valueType->size()); + + memmove(valueBuffer, &val, valueType->size()); +} + + + +void +r_Primitive::set_short(r_Short val) throw( r_Error ) +{ + if( !valueType || valueType->type_id() != r_Type::SHORT ) + { + RMInit::logOut << "r_Primitive::set_short(" << val << ") not a short" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + if( !valueBuffer ) + valueBuffer = (char*)mymalloc( valueType->size()); + + memmove(valueBuffer, &val, valueType->size()); +} + + + +void +r_Primitive::set_ushort(r_UShort val) throw( r_Error ) +{ + if( !valueType || valueType->type_id() != r_Type::USHORT ) + { + RMInit::logOut << "r_Primitive::set_ushort(" << val << ") not a ushort" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + if( !valueBuffer ) + valueBuffer = (char*)mymalloc( valueType->size()); + + memmove(valueBuffer, &val, valueType->size()); +} + + + +void +r_Primitive::set_long(r_Long val) throw( r_Error ) +{ + if( !valueType || valueType->type_id() != r_Type::LONG ) + { + RMInit::logOut << "r_Primitive::set_long(" << val << ") not a long" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + if( !valueBuffer ) + valueBuffer = (char*)mymalloc( valueType->size()); + + memmove(valueBuffer, &val, valueType->size()); +} + + + +void +r_Primitive::set_ulong(r_ULong val) throw( r_Error ) +{ + if( !valueType || valueType->type_id() != r_Type::ULONG ) + { + RMInit::logOut << "r_Primitive::set_ulong(" << val << ") not a ulong" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + if( !valueBuffer ) + valueBuffer = (char*)mymalloc( valueType->size()); + + memmove(valueBuffer, &val, valueType->size()); +} + + + +void +r_Primitive::set_float(r_Float val) throw( r_Error ) +{ + if( !valueType || valueType->type_id() != r_Type::FLOAT ) + { + RMInit::logOut << "r_Primitive::set_float(" << val << ") not a float" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + if( !valueBuffer ) + valueBuffer = (char*)mymalloc( valueType->size()); + + memmove(valueBuffer, &val, valueType->size()); +} + + + +void +r_Primitive::set_double(r_Double val) throw( r_Error ) +{ + if( !valueType || valueType->type_id() != r_Type::DOUBLE ) + { + RMInit::logOut << "r_Primitive::set_double(" << val << ") not a double" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw err; + } + + if( !valueBuffer ) + valueBuffer = (char*)mymalloc( valueType->size()); + memmove(valueBuffer, &val, valueType->size()); +} + + +std::ostream& operator<<( std::ostream& s, const r_Primitive& obj ) +{ + obj.print_status( s ); + return s; +} + diff --git a/raslib/primitive.hh b/raslib/primitive.hh new file mode 100644 index 0000000..a4d1dc6 --- /dev/null +++ b/raslib/primitive.hh @@ -0,0 +1,143 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: primitive.hh + * + * MODULE: raslib + * CLASS: r_Primitive + * + * COMMENTS: + * The class represents a primitive type value. + * +*/ + +#ifndef _D_PRIMITIVE_ +#define _D_PRIMITIVE_ + +#include <iostream> + +class r_Error; + +#include "raslib/scalar.hh" +#include "raslib/odmgtypes.hh" + +class r_Primitive_Type; + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + Class \Ref{r_Primitive} represents a primitive type value. + +*/ + +class r_Primitive : public r_Scalar +{ + public: + + explicit + + /// constructs a scalar type value + r_Primitive( const char* newBuffer, const r_Primitive_Type* newType ); + + /// copy constructor + r_Primitive( const r_Primitive& obj ); + + /// destructor + ~r_Primitive(); + + /// clone operator + virtual r_Scalar* clone() const; + + /// operator for assigning a primitive + virtual const r_Primitive& operator= ( const r_Primitive& ); + + /// gets the pointer to the buffer + const char* get_buffer() const; + + /// debug output + virtual void print_status(std::ostream& s) const; + + virtual bool isPrimitive() const; + + //@Man: Type-safe value access methods. In case of type mismatch, an exception is raised. + //@{ + /// + + /// + r_Boolean get_boolean() const throw( r_Error ); + /// + r_Char get_char() const throw( r_Error ); + /// + r_Octet get_octet() const throw( r_Error ); + /// + r_Short get_short() const throw( r_Error ); + /// + r_UShort get_ushort() const throw( r_Error ); + /// + r_Long get_long() const throw( r_Error ); + /// + r_ULong get_ulong() const throw( r_Error ); + /// + r_Float get_float() const throw( r_Error ); + /// + r_Double get_double() const throw( r_Error ); + + /// + void set_boolean(r_Boolean) throw( r_Error ); + /// + void set_char(r_Char) throw( r_Error ); + /// + void set_octet(r_Octet) throw( r_Error ); + /// + void set_short(r_Short) throw( r_Error ); + /// + void set_ushort(r_UShort) throw( r_Error ); + /// + void set_long(r_Long) throw( r_Error ); + /// + void set_ulong(r_ULong) throw( r_Error ); + /// + void set_float(r_Float) throw( r_Error ); + /// + void set_double(r_Double) throw( r_Error ); + + + /// + //@} + + private: + /// buffer + char* valueBuffer; +}; + + + +//@ManMemo: Module: {\bf raslib} +/** + Output stream operator for objects of type {\tt const} \Ref{r_Primitive}. +*/ +extern std::ostream& operator<<( std::ostream& s, const r_Primitive& obj ); + +#endif + diff --git a/raslib/primitivetype.cc b/raslib/primitivetype.cc new file mode 100644 index 0000000..a0dbb37 --- /dev/null +++ b/raslib/primitivetype.cc @@ -0,0 +1,601 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +static const char rcsid[] = "@(#)raslib, r_Primitive_Type: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/primitivetype.cc,v 1.26 2003/12/27 23:01:21 rasdev Exp $"; + +#include "raslib/primitivetype.hh" +#include "raslib/rminit.hh" +#include "raslib/rmdebug.hh" +#include "raslib/odmgtypes.hh" +#include "raslib/endian.hh" +#include "raslib/error.hh" + +#include <iomanip> +#include <string> +#include <cstring> + +r_Primitive_Type::r_Primitive_Type() + : r_Base_Type(), + typeId(UNKNOWNTYPE) +{ +} + +r_Primitive_Type::r_Primitive_Type( const char* newTypeName, + const r_Type::r_Type_Id newTypeId ) + : r_Base_Type(newTypeName, 0), + typeId(newTypeId) +{ + + switch( typeId ) + { + case ULONG: typeSize = 4; break; + case USHORT: typeSize = 2; break; + case BOOL: typeSize = 1; break; + case LONG: typeSize = 4; break; + case SHORT: typeSize = 2; break; + case OCTET: typeSize = 1; break; + case DOUBLE: typeSize = 8; break; + case FLOAT: typeSize = 4; break; + case CHAR: typeSize = 1; break; + case COMPLEXTYPE1: + typeSize = 2 * sizeof(float); + break; + case COMPLEXTYPE2: + typeSize = 2 * sizeof(double); + break; + default: + RMDBGONCE(3, RMDebug::module_raslib, "r_Primitive_Type", "r_Primitive_Type(....) bad typeId " << typeId); + break; + } +} + +r_Primitive_Type::r_Primitive_Type( const r_Primitive_Type& oldObj ) + : r_Base_Type(oldObj), + typeId(oldObj.typeId) +{ +} + +const r_Primitive_Type& +r_Primitive_Type::operator=( const r_Primitive_Type& oldObj ) +{ + // Gracefully handle self assignment + if (this == &oldObj) return *this; + + r_Base_Type::operator=( oldObj ); + typeId = oldObj.typeId; + + return *this; +} + +r_Primitive_Type::~r_Primitive_Type() +{ +} + +r_Type* +r_Primitive_Type::clone() const +{ + return new r_Primitive_Type( *this ); +} + + +r_Type::r_Type_Id +r_Primitive_Type::type_id() const +{ + return typeId; +} + +bool +r_Primitive_Type::isPrimitiveType() const +{ + return true; +} + +void +r_Primitive_Type::convertToLittleEndian(char* cells, r_Bytes noCells) const + { + char c0 = 0; + char c1 = 0; + char c2 = 0; + char c3 = 0; + r_Bytes i = 0; + + switch( typeId ) + { + case USHORT: + case SHORT: + for(i=0; i<noCells; i++ ) + { + c1 = cells[i*typeSize]; + c0 = cells[i*typeSize + 1]; + cells[i*typeSize] = c0; + cells[i*typeSize + 1] = c1; + } + break; + + case ULONG: + case LONG: + for(i=0; i<noCells; i++ ) + { + c3 = cells[i*typeSize]; + c2 = cells[i*typeSize + 1]; + c1 = cells[i*typeSize + 2]; + c0 = cells[i*typeSize + 3]; + cells[i*typeSize] = c0; + cells[i*typeSize + 1] = c1; + cells[i*typeSize + 2] = c2; + cells[i*typeSize + 3] = c3; + } + break; + + case FLOAT: + for(i = 0; i < noCells; ++i) + ((r_Float *)cells)[i] = r_Endian::swap( ((r_Float *)cells)[i] ); + break; + + case DOUBLE: + for(i = 0; i < noCells; ++i) + ((r_Double *)cells)[i] = r_Endian::swap( ((r_Double *)cells)[i] ); + break; + default: + RMDBGONCE(3, RMDebug::module_raslib, "r_Primitive_Type", "convertToLittleEndian(....) bad typeId " << typeId); + break; + } + } + +void +r_Primitive_Type::convertToBigEndian(char* cells, r_Bytes noCells) const + { + char c0 = 0; + char c1 = 0; + char c2 = 0; + char c3 = 0; + r_Bytes i = 0; + + switch( typeId ) + { + case USHORT: + case SHORT: + for(i=0; i<noCells; i++) + { + c1 = cells[i*typeSize]; + c0 = cells[i*typeSize + 1]; + cells[i*typeSize] = c0; + cells[i*typeSize + 1] = c1; + } + break; + + case ULONG: + case LONG: + for(i=0; i<noCells; i++) + { + c3 = cells[i*typeSize]; + c2 = cells[i*typeSize + 1]; + c1 = cells[i*typeSize + 2]; + c0 = cells[i*typeSize + 3]; + cells[i*typeSize] = c0; + cells[i*typeSize + 1] = c1; + cells[i*typeSize + 2] = c2; + cells[i*typeSize + 3] = c3; + } + break; + + case FLOAT: + for(i = 0; i < noCells; ++i) + ((r_Float *)cells)[i] = r_Endian::swap( ((r_Float *)cells)[i] ); + break; + + case DOUBLE: + for(i = 0; i < noCells; ++i) + ((r_Double *)cells)[i] = r_Endian::swap( ((r_Double *)cells)[i] ); + break; + default: + RMDBGONCE(3, RMDebug::module_raslib, "r_Primitive_Type", "convertToBigEndian(....) bad typeId " << typeId); + break; + } + } + +void +r_Primitive_Type::print_status( std::ostream& s ) const +{ + s << typeId; +} + +void +r_Primitive_Type::print_value( const char* storage, std::ostream& s ) const +{ + switch( typeId ) + { + case r_Type::ULONG: s << std::setw(5) << get_ulong( storage ); break; + case r_Type::USHORT: s << std::setw(5) << get_ushort( storage ); break; + case r_Type::BOOL: s << std::setw(5) << ( get_boolean( storage ) ? "T" : "F" ); break; + case r_Type::LONG: s << std::setw(5) << get_long( storage ); break; + case r_Type::SHORT: s << std::setw(5) << get_short( storage ); break; + case r_Type::OCTET: s << std::setw(5) << (int)( get_octet( storage ) ); break; + case r_Type::DOUBLE: s << std::setw(5) << get_double( storage ) ; break; + case r_Type::FLOAT: s << std::setw(5) << get_float( storage ); break; + case r_Type::CHAR: s << std::setw(5) << (int)( get_char( storage ) ); break; + default: + RMInit::logOut << "r_Primitive_Type::print_value(...) type unknown" << endl; + break; + } +} + +//FIXME +// We have to return the value in the most powerfull type(e.g. now r_Double) without loss +// This may change in future + +r_Double +r_Primitive_Type::get_value( const char* storage ) const throw(r_Error) +{ + r_Double retVal=0.; + + switch( typeId ) + { + case r_Type::ULONG: retVal=get_ulong( storage ); break; + case r_Type::USHORT: retVal=get_ushort( storage ); break; + case r_Type::BOOL: retVal=get_boolean( storage ); break; + case r_Type::LONG: retVal=get_long( storage ); break; + case r_Type::SHORT: retVal=get_short( storage ); break; + case r_Type::OCTET: retVal=get_octet( storage ); break; + case r_Type::DOUBLE: retVal=get_double( storage ); break; + case r_Type::FLOAT: retVal=get_float( storage ); break; + case r_Type::CHAR: retVal=get_char( storage ); break; + default: + { + RMInit::logOut << "r_Primitive_Type::get_value(...) type unknown" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + }; + break; + } + return retVal; +} + +//FIXME +// We have to set the value from the most powerfull type(e.g. now r_Double) without loss +// This may change in future + +void +r_Primitive_Type::set_value( char* storage, r_Double val ) throw(r_Error) +{ + switch( typeId ) + { + case r_Type::ULONG: set_ulong( storage, (r_ULong)val ); break; + case r_Type::USHORT: set_ushort( storage, (r_UShort)val ); break; + case r_Type::BOOL: set_boolean( storage, (r_Boolean)val ); break; + case r_Type::LONG: set_long( storage, (r_Long)val ); break; + case r_Type::SHORT: set_short( storage, (r_Short)val ); break; + case r_Type::OCTET: set_octet( storage, (r_Octet)val ); break; + case r_Type::DOUBLE: set_double( storage, (r_Double)val); break; + case r_Type::FLOAT: set_float( storage, (r_Float)val ); break; + case r_Type::CHAR: set_char( storage, (r_Char)val ); break; + default: + { + RMInit::logOut << "r_Primitive_Type::set_value(...) type unknown" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + }; + break; + } +} + +//FIXME +// We have to set the value from the most powerfull type(e.g. now r_Double) without loss +// This may change in future + +void +r_Primitive_Type::get_limits( r_Double& min, r_Double& max ) throw(r_Error) +{ + r_Double *type=NULL; + switch( typeId ) + { + case r_Type::ULONG: ::get_limits( (r_ULong*)type, min, max ); break; + case r_Type::USHORT: ::get_limits( (r_UShort*)type, min, max ); break; + case r_Type::BOOL: ::get_limits( (r_Boolean*)type, min, max ); break; + case r_Type::LONG: ::get_limits( (r_Long*)type, min, max ); break; + case r_Type::SHORT: ::get_limits( (r_Short*)type, min, max ); break; + case r_Type::OCTET: ::get_limits( (r_Octet*)type, min, max ); break; + case r_Type::DOUBLE: ::get_limits( (r_Double*)type, min, max); break; + case r_Type::FLOAT: ::get_limits( (r_Float*)type, min, max ); break; + case r_Type::CHAR: ::get_limits( (r_Char*)type, min, max ); break; + default: + { + RMInit::logOut << "r_Primitive_Type::get_limits(...) type unknown" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + }; + break; + } +} + +r_Boolean +r_Primitive_Type::get_boolean( const char* cell ) const throw( r_Error ) +{ + if( typeId != r_Type::BOOL ) + { + RMInit::logOut << "r_Primitive_Type::get_boolean(cell) type not a boolean" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + return *((r_Boolean*)cell); +} + + + +r_Char +r_Primitive_Type::get_char( const char* cell ) const throw( r_Error ) +{ + if( typeId != r_Type::CHAR ) + { + RMInit::logOut << "r_Primitive_Type::get_char(cell) type not a char" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + return *((r_Char*)cell); +} + + + +r_Octet +r_Primitive_Type::get_octet( const char* cell ) const throw( r_Error ) +{ + if( typeId != r_Type::OCTET ) + { + RMInit::logOut << "r_Primitive_Type::get_octet(cell) type not a octet" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + return *((r_Octet*)cell); +} + + + +r_Short +r_Primitive_Type::get_short( const char* cell ) const throw( r_Error ) +{ + if( typeId != r_Type::SHORT ) + { + RMInit::logOut << "r_Primitive_Type::get_short(cell) type not a short" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + return *((r_Short*)cell); +} + + + +r_UShort +r_Primitive_Type::get_ushort( const char* cell ) const throw( r_Error ) +{ + if( typeId != r_Type::USHORT ) + { + RMInit::logOut << "r_Primitive_Type::get_ushort(cell) type not a ushort" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + return *((r_UShort*)cell); +} + + + +r_Long +r_Primitive_Type::get_long( const char* cell ) const throw( r_Error ) +{ + if( typeId != r_Type::LONG ) + { + RMInit::logOut << "r_Primitive_Type::get_long(cell) type not a long" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + return *((r_Long*)cell); +} + + + +r_ULong +r_Primitive_Type::get_ulong( const char* cell ) const throw( r_Error ) +{ + if( typeId != r_Type::ULONG ) + { + RMInit::logOut << "r_Primitive_Type::get_ulong(cell) type not a ulong" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + return *((r_ULong*)cell); +} + + + +r_Float +r_Primitive_Type::get_float( const char* cell ) const throw( r_Error ) +{ + if( typeId != r_Type::FLOAT ) + { + RMInit::logOut << "r_Primitive_Type::get_float(cell) type not a float" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + return *((r_Float*)cell); +} + + + +r_Double +r_Primitive_Type::get_double( const char* cell ) const throw( r_Error ) +{ + if( typeId != r_Type::DOUBLE ) + { + RMInit::logOut << "r_Primitive_Type::get_double(cell) type not a double" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + return *((r_Double*)cell); +} + +void +r_Primitive_Type::set_boolean( char* cell, r_Boolean val ) throw( r_Error ) +{ + if( typeId != r_Type::BOOL ) + { + RMInit::logOut << "r_Primitive_Type::set_boolean(cell, val) type not a boolean" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + memmove(cell, &val, typeSize); +} + + + +void +r_Primitive_Type::set_char( char* cell, r_Char val ) throw( r_Error ) +{ + if( typeId != r_Type::CHAR ) + { + RMInit::logOut << "r_Primitive_Type::set_char(cell, val) type not a char" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + memmove(cell, &val, typeSize); +} + + + +void +r_Primitive_Type::set_octet( char* cell, r_Octet val ) throw( r_Error ) +{ + if( typeId != r_Type::OCTET ) + { + RMInit::logOut << "r_Primitive_Type::set_octet(cell, val) type not a octet" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + memmove(cell, &val, typeSize); +} + + + +void +r_Primitive_Type::set_short( char* cell, r_Short val ) throw( r_Error ) +{ + if( typeId != r_Type::SHORT ) + { + RMInit::logOut << "r_Primitive_Type::set_short(cell, val) type not a short" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + memmove(cell, &val, typeSize); +} + + + +void +r_Primitive_Type::set_ushort( char* cell, r_UShort val ) throw( r_Error ) +{ + if( typeId != r_Type::USHORT ) + { + RMInit::logOut << "r_Primitive_Type::set_ushort(cell, val) type not a ushort" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + memmove(cell, &val, typeSize); +} + + + +void +r_Primitive_Type::set_long( char* cell, r_Long val ) throw( r_Error ) +{ + if( typeId != r_Type::LONG ) + { + RMInit::logOut << "r_Primitive_Type::set_long(cell, val) type not a long" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + memmove(cell, &val, typeSize); +} + + + +void +r_Primitive_Type::set_ulong( char* cell, r_ULong val ) throw( r_Error ) +{ + if( typeId != r_Type::ULONG ) + { + RMInit::logOut << "r_Primitive_Type::set_ulong(cell, val) type not a ulong" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + memmove(cell, &val, typeSize); +} + + + +void +r_Primitive_Type::set_float( char* cell, r_Float val ) throw( r_Error ) +{ + if( typeId != r_Type::FLOAT ) + { + RMInit::logOut << "r_Primitive_Type::set_float(cell, val) type not a float" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + memmove(cell, &val, typeSize); +} + + + +void +r_Primitive_Type::set_double( char* cell, r_Double val ) throw( r_Error ) +{ + if( typeId != r_Type::DOUBLE ) + { + RMInit::logOut << "r_Primitive_Type::set_double(cell, val) type not a double" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + memmove(cell, &val, typeSize); +} + +std::ostream &operator<<( std::ostream &str, const r_Primitive_Type &type ) +{ + type.print_status(str); + return str; +} diff --git a/raslib/primitivetype.hh b/raslib/primitivetype.hh new file mode 100644 index 0000000..9dac808 --- /dev/null +++ b/raslib/primitivetype.hh @@ -0,0 +1,147 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: primitivetype.hh + * + * MODULE: raslib + * CLASS: r_Primitive_Type + * + * COMMENTS: + * +*/ + +#ifndef _D_PRIMITIVE_TYPE_ +#define _D_PRIMITIVE_TYPE_ + +class r_Error; + +#include "raslib/basetype.hh" +#include "raslib/odmgtypes.hh" + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + This class represents all primitive types in the ODMG conformant + representation of the RasDaMan type system. Examples are ULONG or + BOOL. +*/ + +class r_Primitive_Type : public r_Base_Type +{ +public: + /// constructor getting name of type, size of type and type id. + r_Primitive_Type( const char* newTypeName, const r_Type::r_Type_Id newTypeId ); + /// copy constructor + r_Primitive_Type( const r_Primitive_Type& oldObj ); + /// assignment operator. + const r_Primitive_Type& operator=( const r_Primitive_Type& oldObj ); + /// destructor. + virtual ~r_Primitive_Type(); + + /// clone operation + virtual r_Type* clone() const; + + /// retrieve id of the type. + virtual r_Type::r_Type_Id type_id() const; + + /// converts array of cells from NT byte order to Unix byte order. + virtual void convertToLittleEndian(char* cells, r_Area noCells) const; + + /// converts array of cells from Unix byte order to NT byte order. + virtual void convertToBigEndian(char* cells, r_Area noCells) const; + + /// writes state of object to specified stream + virtual void print_status( std::ostream& s = std::cout ) const; + + /// check, if type is primitive. + virtual bool isPrimitiveType() const; + + /// prints value of a primitive type + virtual void print_value( const char* storage, std::ostream& s = std::cout ) const; + + //@Man: Type-safe value access methods. In case of type mismatch, an exception is raised. + //@{ + /// + + /// + r_Double get_value( const char* cell ) const throw( r_Error ); + /// + void set_value( char* cell, r_Double ) throw( r_Error ); + /// + void get_limits( r_Double&, r_Double& ) throw( r_Error ); + + + /// + r_Boolean get_boolean( const char* cell ) const throw( r_Error ); + /// + r_Char get_char( const char* cell ) const throw( r_Error ); + /// + r_Octet get_octet( const char* cell ) const throw( r_Error ); + /// + r_Short get_short( const char* cell ) const throw( r_Error ); + /// + r_UShort get_ushort( const char* cell ) const throw( r_Error ); + /// + r_Long get_long( const char* cell ) const throw( r_Error ); + /// + r_ULong get_ulong( const char* cell ) const throw( r_Error ); + /// + r_Float get_float( const char* cell ) const throw( r_Error ); + /// + r_Double get_double( const char* cell ) const throw( r_Error ); + + /// + void set_boolean( char* cell, r_Boolean ) throw( r_Error ); + /// + void set_char( char* cell, r_Char ) throw( r_Error ); + /// + void set_octet( char* cell, r_Octet ) throw( r_Error ); + /// + void set_short( char* cell, r_Short ) throw( r_Error ); + /// + void set_ushort( char* cell, r_UShort ) throw( r_Error ); + /// + void set_long( char* cell, r_Long ) throw( r_Error ); + /// + void set_ulong( char* cell, r_ULong ) throw( r_Error ); + /// + void set_float( char* cell, r_Float ) throw( r_Error ); + /// + void set_double( char* cell, r_Double ) throw( r_Error ); + + + /// + //@} + + protected: + /// default constructor. + r_Primitive_Type(); + + r_Type::r_Type_Id typeId; +}; + +//@Doc: write the status of a primitive type to a stream +extern std::ostream &operator<<( std::ostream &str, const r_Primitive_Type &type ); + +#endif + diff --git a/raslib/property.cc b/raslib/property.cc new file mode 100644 index 0000000..ddd75c2 --- /dev/null +++ b/raslib/property.cc @@ -0,0 +1,99 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +static const char rcsid[] = "@(#)raslib, r_Meta_Object: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/property.cc,v 1.7 2003/12/27 23:01:21 rasdev Exp $"; + +#include "raslib/property.hh" +#include "raslib/basetype.hh" +#include "raslib/rminit.hh" +#include "raslib/error.hh" + + +#include <malloc.h> +#include <string.h> + +r_Property::r_Property() + : r_Meta_Object(), + myType(NULL) + { + } + +r_Property::r_Property(const char* newTypeName, const r_Base_Type& newType) + : r_Meta_Object(newTypeName), + myType((r_Base_Type*)newType.clone()) + { + } + +r_Property::r_Property(const r_Property& oldObj) + : r_Meta_Object(oldObj) + { + if (oldObj.myType) + myType = (r_Base_Type*)oldObj.myType->clone(); + else { + RMInit::logOut << "r_Property::r_Property(oldObj) property does not have a base type" << endl; + throw r_Error(PROPERTYTYPEHASNOELEMENTTYPE); + } + } + +const r_Property& +r_Property::operator=(const r_Property& oldObj) + { + // Gracefully handle self assignment + if (this != &oldObj) + { + r_Meta_Object::operator=(oldObj); + if (myType) + { + delete myType; + myType = 0; + } + + if (oldObj.myType) + myType = (r_Base_Type*)oldObj.myType->clone(); + else { + RMInit::logOut << "r_Property::operator=(oldObj) property does not have a base type" << endl; + throw r_Error(PROPERTYTYPEHASNOELEMENTTYPE); + } + } + + return *this; + } + +r_Property::~r_Property() + { + if (myType) + delete myType; + } + +const r_Base_Type& +r_Property::type_of() const + { + if (!myType) + { + RMInit::logOut << "r_Property::type_of() property does not have a base type" << endl; + throw r_Error(PROPERTYTYPEHASNOELEMENTTYPE); + } + + return *myType; + } + diff --git a/raslib/property.hh b/raslib/property.hh new file mode 100644 index 0000000..1985993 --- /dev/null +++ b/raslib/property.hh @@ -0,0 +1,77 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: property.hh + * + * MODULE: raslib + * CLASS: r_Property + * + * COMMENTS: + * +*/ + +#ifndef _D_PROPERTY_ +#define _D_PROPERTY_ + +#include "metaobject.hh" + + +class r_Base_Type; +class r_Type_Id; + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + This class the superclass for properties of classes in the ODMG + conformant representation of the RasDaMan type system. +*/ + +class r_Property : public r_Meta_Object + { + public: + + /// constructor getting name and type of property. + r_Property( const char* newTypeName, const r_Base_Type& newType ); + + /// copy constructor. + r_Property( const r_Property& oldObj ); + + /// assignment operator. + const r_Property& operator=( const r_Property& oldObj ); + + /// destructor. + virtual ~r_Property(); + + /// retrieve type of property. + const r_Base_Type& type_of() const; + + protected: + + r_Base_Type* myType; + + /// default constructor. + r_Property(); + + }; + +#endif diff --git a/raslib/rm.cc b/raslib/rm.cc new file mode 100644 index 0000000..4698f5b --- /dev/null +++ b/raslib/rm.cc @@ -0,0 +1,31 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: rm.hh + * + * PURPOSE: + * Artificially created to manipulate hierarchy tree. + * + * COMMENTS: + * +*/ diff --git a/raslib/rm.hh b/raslib/rm.hh new file mode 100644 index 0000000..39643b9 --- /dev/null +++ b/raslib/rm.hh @@ -0,0 +1,38 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: rm.hh + * + * PURPOSE: + * Artificial class to manipulate hierarchy tree. + * + * COMMENTS: + * +*/ + +#ifndef _RM_CLASS_ +#define _RM_CLASS_ + +class RM_Class {}; + +#endif diff --git a/raslib/rmdebug.cc b/raslib/rmdebug.cc new file mode 100644 index 0000000..d047812 --- /dev/null +++ b/raslib/rmdebug.cc @@ -0,0 +1,430 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * SOURCE: rmdebug.cc + * + * MODULE: raslib + * CLASS: + * + * COMMENTS: + * +*/ + +static const char rcsid[] = "@(#)raslib, RMDebug: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/rmdebug.cc,v 1.33 2005/12/02 14:51:55 rasdev Exp $"; + +#include <iostream> +using namespace std; + +#include <stdio.h> // fopen, getc +#include <string.h> +#include <ctype.h> +#include <stdlib.h> +#include <fstream> + + +#include "raslib/rmdebug.hh" +#include "raslib/odmgtypes.hh" + +int RManDebug = 0; // debug level (0-4), 0 means no debug info at all +int RManBenchmark = 0; // benchmark level (0-4) + +// initialization of static variables for RMDebug +int RMDebug::level = 0; +int RMDebug::numDebugModules = 0; +char** RMDebug::debugModules = 0; +char* RMDebug::debugModulesText = 0; +int* RMDebug::transDebugModules = 0; +int RMDebug::numDebugClasses = 0; +char** RMDebug::debugClasses = 0; +char* RMDebug::debugClassesText = 0; + +// all module names +const char* RMDebug::allModuleNames[] = { + "adminif", + "applications", + "blobif", + "cachetamgr", + "catalogif", + "catalogmgr", + "clientcomm", + "conversion", + "compression", + "httpserver", + "indexif", + "indexmgr", + "insertutils", + "mddif", + "mddmgr", + "qlparser", + "rasdl", + "raslib", + "rasodmg", + "rasql", + "server", + "servercomm", + "storageif", + "storagemgr", + "tools", + "tilemgr", + "utilities" +}; + +int RMDebug::allModuleLevels[RMDebug::module_number]; + + +// initialization of static variable for RMTimer +#ifndef __VISUALC__ +struct timezone RMTimer::dummy; +#endif + +RMDebug::RMDebug(const char* newClass, const char* newFunc, const char* newModule, + const char* newFile, int newLine) + : myClass(newClass), myFunc(newFunc), myModule(newModule), + myFile(newFile), myLine(newLine), myModuleNum(-1), myDebugLevel(2) +{ + myDebugOn = checkDebug(); + + int useLevel = -1; + if (myModuleNum >= 0) + useLevel = allModuleLevels[myModuleNum]; + + if (useLevel < 0) + useLevel = RManDebug; + + myDebugOn = myDebugOn && (useLevel >= myDebugLevel); + + if( myDebugOn ) + { + indentLine(); + // output, when entering function + RMInit::dbgOut << "D: " << myClass << "::" << myFunc << " entered " + << "(" << myModule << ", " << myFile << ": " << myLine + << ")." << endl; + // indentation + level++; + } +} + +RMDebug::RMDebug(int newLevel, const char* newClass, const char* newFunc, int newModuleNum, + const char* newFile, int newLine) + : myClass(newClass), myFunc(newFunc), myModule(NULL), myFile(newFile), + myLine(newLine), myModuleNum(newModuleNum), myDebugLevel(newLevel) +{ + myDebugOn = checkDebug() && (allModuleLevels[newModuleNum] >= myDebugLevel); + + if ( myDebugOn ) + { + indentLine(); + // output when entering function + RMInit::dbgOut << "D: " << myClass << "::" << myFunc << " entered " + << "(" << allModuleNames[myModuleNum] << ", " << myFile << ": " + << myLine << ")." << endl; + // indentation + level++; + } +} + +RMDebug::~RMDebug(void) +{ + if( myDebugOn ) + { + // indentation + level--; + indentLine(); + // output, when exiting function + RMInit::dbgOut << "D: " << myClass << "::" << myFunc + << " exited." << endl; + } +} + +char* +RMDebug::loadTextFile(const char* name) +{ + + std::ifstream f; + f.open(name); + if (f.is_open()) + { + char* result; + f.seekg(0, std::ios::end); + std::streampos end = f.tellg(); + r_Long resLen=(r_Long)end + 1; + result = new char[resLen]; + memset(result, 0, resLen); + f.seekg(0, std::ios::beg); + f.read(result, end); + f.close(); + result[resLen] = '\0'; + return result; + } + return NULL; +} + +int +RMDebug::initRMDebug(void) +{ + int errmod=0; + int errclass=0; + int j; + const char* enVar; + char* myPtr; + + // init all debug levels to global debug level + for (j=0; j<module_number; j++) + allModuleLevels[j] = RManDebug; + + // ------------------- + // reading rmdbmodules + // ------------------- + + // environment variable overrides text file + if ((enVar = getenv("RMDBGMODULES")) != NULL) + { + debugModulesText = new char[strlen(enVar)+1]; + strcpy(debugModulesText, enVar); + } + else + { + if ((debugModulesText = loadTextFile("rmdbmodules")) == NULL) + errmod = -1; + } + + if (debugModulesText != NULL) + { + // first switch off debugging info for all modules + for (j=0; j<module_number; j++) + allModuleLevels[j] = 0; + + // count number of lines (whitespace separates) + myPtr = debugModulesText; + while (*myPtr != '\0') + { + while (isspace((unsigned int)(*myPtr))) myPtr++; + if (*myPtr != '\0') + { + numDebugModules++; + while ((*myPtr != '\0') && !isspace((unsigned int)(*myPtr))) myPtr++; + } + } + debugModules = new char*[numDebugModules]; + transDebugModules = new int[numDebugModules]; + // read text + j = 0; + myPtr = debugModulesText; + while (*myPtr != '\0') + { + int modLevel = RManDebug; // default debug level + transDebugModules[j] = -1; + while (isspace((unsigned int)(*myPtr))) myPtr++; + if (*myPtr != '\0') + { + debugModules[j] = myPtr; + while ((*myPtr != '\0') && !isspace((unsigned int)(*myPtr))) + { + if (*myPtr == ',') + { + char* rest; + *myPtr++ = '\0'; + modLevel = strtol(myPtr, &rest, 10); + if (rest == myPtr) + { + cerr << "RMDebug::initRMDebug: Parse error in item " << j << endl; + } + myPtr = rest; + } + else myPtr++; + } + } + if (*myPtr != '\0') *myPtr++ = '\0'; + for (int i=0; i<module_number; i++) + { + if (debugModules[j] == NULL) + RMInit::logOut << "RMDebug::initRMDebug: debugModules[" << j << "] is NULL, skipping this." << std::endl; + else if (allModuleNames[i] == NULL) + RMInit::logOut << "RMDebug::initRMDebug: allModuleNames[" << i << "] is NULL, skipping this." << std::endl; + else if (strcmp(debugModules[j], allModuleNames[i]) == 0) + { + transDebugModules[j] = i; break; + } + } + if (transDebugModules[j] >= 0) + allModuleLevels[transDebugModules[j]] = modLevel; + j++; + } + for (j=0; j<module_number; j++) + RMInit::dbgOut << allModuleNames[j] << " : " << allModuleLevels[j] << endl; + } + + // ------------------- + // reading rmdbclasses + // ------------------- + + if ((enVar = getenv("RMDBGCLASSES")) != NULL) + { + debugClassesText = new char[strlen(enVar)+1]; + strcpy(debugClassesText, enVar); + } + else + { + if ((debugClassesText = loadTextFile("rmdbclasses")) == NULL) + errclass = -1; + } + + if (debugClassesText != NULL) + { + myPtr = debugClassesText; + while (*myPtr != '\0') + { + while (isspace((unsigned int)(*myPtr))) myPtr++; + if (*myPtr != '\0') + { + numDebugClasses++; + while ((*myPtr != '\0') && !isspace((unsigned int)(*myPtr))) myPtr++; + } + } + debugClasses = new char*[numDebugClasses]; + // read text + j = 0; + myPtr = debugClassesText; + while (*myPtr != '\0') + { + while (isspace((unsigned int)(*myPtr))) myPtr++; + if (*myPtr != '\0') + { + debugClasses[j++] = myPtr; + while ((*myPtr != '\0') && !isspace((unsigned int)(*myPtr))) myPtr++; + if (*myPtr != '\0') *myPtr++ = '\0'; + } + } + } +RMInit::dbgOut << endl; + for (j=0; j<numDebugClasses; j++) + RMInit::dbgOut << debugClasses[j] << endl; + + if(errmod == -1 && errclass == -1) + return -1; + else + return 0; +} + +int +RMDebug::checkDebug(void) +{ + int i; + + if(numDebugModules == 0 && numDebugClasses == 0) + // all classes should be debugged + return 1; + else + { + if (numDebugModules > 0) + { + if(myModuleNum >= 0) + { + if (allModuleLevels[myModuleNum] == 0) + return 0; + } + else + { + // check if module is mentioned + for(i = 0; i < numDebugModules; i++) + { + if(strcmp(debugModules[i], myModule) == 0) + { + myModuleNum = transDebugModules[i]; + break; + } + } + if (i >= numDebugModules) return 0; + } + } + if((numDebugClasses > 0) && (myClass != NULL)) + { + // check if class is mentioned + for(i = 0; i < numDebugClasses; i++) + if(strcmp(debugClasses[i], myClass) == 0) + break; + if (i >= numDebugClasses) return 0; + } + } + return 1; +} + +int +RMDebug::debugOutput(int dbgLevel, int modNum, const char* className) +{ + int retval = 0; + if ((numDebugModules == 0) && (numDebugClasses == 0)) + { + retval = (RManDebug >= dbgLevel); + } + else { + if (numDebugModules > 0) { + retval = (allModuleLevels[modNum] >= dbgLevel); + } + else { + if ((numDebugClasses > 0) && (className != NULL)) + { + int i; + for (i=0; i<numDebugClasses; i++) + { + if (strcmp(debugClasses[i], className) == 0) + { + break; + } + } + if (i >= numDebugClasses) + retval = 0; + else + retval = 1; + } + else { + //nothing to do + } + } + } + return retval; +} + +RMCounter::RMCounter(int levell, int module, const char* cls) + : doStuff(false) + { + if (RMDebug::debugOutput( levell, module, cls )) + { + //RMInit::dbgOut << "RMCounter() " << RMDebug::level << " "; + doStuff = true; + RMDebug::level++; + //RMInit::dbgOut << RMDebug::level << endl; + } + } + +RMCounter::~RMCounter() + { + if (doStuff == true) + { + //RMInit::dbgOut << "~RMCounter() " << RMDebug::level << " "; + RMDebug::level--; + //RMInit::dbgOut << RMDebug::level << endl; + } + } + diff --git a/raslib/rmdebug.hh b/raslib/rmdebug.hh new file mode 100644 index 0000000..08e38cc --- /dev/null +++ b/raslib/rmdebug.hh @@ -0,0 +1,382 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: rmdebug.hh + * + * PURPOSE: + * Contains debug stuff. + * + * COMMENTS: + * +*/ + +#ifndef _RMDEBUG_ +#define _RMDEBUG_ + +#ifdef __VISUALC__ +#include <time.h> +#else +#include <sys/time.h> +#endif + +#include "raslib/rminit.hh" +#include "raslib/rm.hh" + +extern int RManDebug; +extern int RManBenchmark; + +#ifdef RMANDEBUG + +#define RMDBGIF( levell, module, cls, text ) \ + if (RMDebug::debugOutput( levell, module, cls )) { text } + +#define RMDBGENTER( levell, module, cls, text ) \ + RMCounter rmCounter(levell, module, cls); \ + if (RMDebug::debugOutput( levell, module, cls )) { \ + RMInit::dbgOut << "ENTER "; RMInit::dbgOut.width(18); RMInit::dbgOut.setf(ios::left, ios::adjustfield); RMInit::dbgOut << cls << " "; RMDebug::indentLine(); RMInit::dbgOut << text << endl << std::flush; \ + } + +#define RMDBGMIDDLE( levell, module, cls, text ) \ + if (RMDebug::debugOutput( levell, module, cls )) { \ + RMInit::dbgOut << "MIDDLE "; RMInit::dbgOut.width(18); RMInit::dbgOut.setf(ios::left, ios::adjustfield); RMInit::dbgOut << cls << " "; RMDebug::indentLine(); RMInit::dbgOut << text << endl << std::flush; \ + } + +#define RMDBGONCE( levell, module, cls, text ) \ + RMCounter rmCounter(levell, module, cls); \ + if (RMDebug::debugOutput(levell, module, cls)) \ + { \ + RMInit::dbgOut << "ONCE "; RMInit::dbgOut.width(18); RMInit::dbgOut.setf(ios::left, ios::adjustfield); RMInit::dbgOut << cls << " "; \ + RMDebug::indentLine(); \ + RMInit::dbgOut << text << endl << std::flush; \ + } + +#define RMDBGEXIT( levell, module, cls, text ) \ + if (RMDebug::debugOutput( levell, module, cls )) { \ + RMInit::dbgOut << "EXIT "; RMInit::dbgOut.width(18); RMInit::dbgOut.setf(ios::left, ios::adjustfield); RMInit::dbgOut << cls << " "; RMDebug::indentLine(); RMInit::dbgOut << text << endl << std::flush; \ + } + +#define RMDBCLASS( t1, t2, t3, t4, t5 ) RMDebug localRMDebug = RMDebug( t1, t2, t3, t4, t5 ); + +#else + +// Note: some parts of the code rely on these to be terminated by a ';'! +#define RMDBGENTER( level, module, cls, text ) ; +#define RMDBGMIDDLE( level, module, cls, text ) ; +#define RMDBGONCE( level, module, cls, text ) ; +#define RMDBGEXIT( level, module, cls, text ) ; +#define RMDBGIF( level, module, cls, text) ; + +#define RMDBCLASS( t1, t2, t3, t4, t5 ) ; +#endif + +#ifdef RMANBENCHMARK + +#define RMTIMER(class, func) RMTimer localRMTimer = RMTimer(class, func); + +#else + +#define RMTIMER(class, func) + +#endif + +//@ManMemo: Module: {\bf raslib}. + +/*@Doc: +RMDebug is not strictly part of RasLib. It is a class used for +generating debug output if compiling with RMANDEBUG defined. One way +of using it is to put the following at the beginning of a function: + +{\tt RMDebug localRMDebug = RMDebug("className", "functionName", +"moduleName", __FILE__, __LINE__");} + +This can be patched in automatically by a modified funchead.pl script. + +{\bf Functionality} + +Debug output printing class name, function name, module name, file +name and line number given as parameters to the constructor is +created, whenever the constructor is called. The destructor +outputs class name and function name. If the static members {\tt +debugModules} or {\tt debugClasses} are set, then only modules +which are mentioned in the array of strings {\tt debugModules} or +classes which are mentioned {\tt debugClasses} give debug output. +{\tt debugModules} and {\tt debugClasses} can either be read from +files named "rmdbmodules" and "rmdbclasses" or from the environment +variables RMDBGMODULES and RMDBGCLASSES. The environment variables +override the files. The contents of the files / variables are the +names of the modules / classes separated by whitespace (space, +newlines, ...). In the case of the modules each modulename may +be followed by ",<dbgLevel>" to set the debug level for that +module explizitly, otherwise the default is used. + +{\bf Interdependencies} + +If only certain modules or classes are to be debugged, RMDebug +has to be initialized in {\Ref RMInit}. This is done by reading +the files {\tt rmdbmodules} and {\tt rmdbclasses}. The files +should contain names of modules resp. classes to be debugged, each +(including the last one!) followed by end of line. */ + +/** + * \defgroup RMs RM Classes + */ + +/** + * \ingroup RMs + */ + +class RMDebug : public RM_Class +{ +public: + /// constructor, initializes members and prints message. + RMDebug(const char* newClass, const char* newFunc, const char* newModule, + const char* newFile, int newLine); + /// constructor taking an identifier to the module for more efficiency + RMDebug(int newLevel, const char* newClass, const char* newFun, int newModuleNum, + const char* newFile, int newLine); + /// destructor, prints message. + ~RMDebug(void); + + /// for initializing modules and classes to debug. + static int initRMDebug(void); + + /// get the debug level of a module by its number + static inline int getModuleDebugLevel(int modNum) { + return allModuleLevels[modNum]; + } + /// get the name of a module by its number + static inline const char* getModuleName(int modNum) { + return allModuleNames[modNum]; + } + /// indent by the amount specified by level + static inline void indentLine(void) { + for (int i=0; i<level; i++) RMInit::dbgOut << " "; + } + + /// return whether debug output should happen for the given module, class + /// and debugging level + static int debugOutput(int dbgLevel, int modNum, const char* className); + + /// all modules for debugging + enum { + module_adminif = 0, + module_applications, + module_blobif, + module_cachetamgr, + module_catalogif, + module_catalogmgr, + module_clientcomm, + module_conversion, + module_compression, + module_httpserver, + module_indexif, + module_indexmgr, + module_insertutils, + module_mddif, + module_mddmgr, + module_qlparser, + module_rasdl, + module_raslib, + module_rasodmg, + module_rasql, + module_server, + module_servercomm, + module_storageif, + module_storagemgr, + module_tilemgr, + module_tools, + module_utilities, + module_number + } RMDebugModules; + /*@ManMemo level of function calls (incremented by constructor, + decremented by destrctor. */ + static int level; + +private: + /// checks, if messages should be printed. + int checkDebug(void); + /// loads a file containing text and returns a 0-terminated string + static char* loadTextFile(const char* name); + /*@Doc: + If {\tt debugModules} or {\tt debugClasses} is set, checks + if myModule or myClass is in the corresponding array. + */ + + /// name of class. + const char* myClass; + /// name of function (no parameters). + const char* myFunc; + /// name of module. + const char* myModule; + /// name of source file. + const char* myFile; + /// line of code where destructor call is. + int myLine; + /// number of module + int myModuleNum; + /// debugging level for this instance + int myDebugLevel; + /// debugging on for this class? + int myDebugOn; + /// number of strings in {\tt debugModules}. + static int numDebugModules; + /// array with pointers into names of modules to be debugged. + static char** debugModules; + /// names of modules to be debugged. + static char* debugModulesText; + /// number of strings in {\tt debugClasses}. + static int numDebugClasses; + /// array with pointers into names of classes to be debugged. + static char** debugClasses; + /// names of class es to be debugged. + static char* debugClassesText; + /// translate index of debug module into index of all modules + static int* transDebugModules; + /// names of all modules + static const char* allModuleNames[]; + /// the debug levels for all modules + static int allModuleLevels[]; +}; + +///Module: {\bf raslib}. + +/** +RMTimer is not strictly part of RasLib. It is a class used for taking +timing measurements if compiling with RMANBENCHMARK defined. One way +of using it is to put the following at the beginning of a function: + +{\tt RMTIMER("className", "functionName");} + +If RMANBENCHMARK is defined this is expanded to: + +{\tt RMTimer localRMTimer = RMTimer("className", "functionName");} + +Time is taken between this line and exiting the block where this line +was. For more elaborate timing measurements an RMTimer object can be +used directly. All timing information is stored in the object, so +multiple RMTimer objects can be used at the same time. + +If output is generated on RMInit::bmOut depends on the flag {\tt +output} and the benchmark level. Output is generated if {\tt output} +is TRUE and {\tt bmLevel} is lower than the global benchmark level +stored in RManBenchmark. The flag {\tt output} can be changed with +setOutput(). The function start() sets {\tt output} to TRUE, stop() +sets {\tt output} to FALSE. + +{\bf Important}: If a RMTimer is used as a static variable, it must be +ensured that no output is generated in the destructor either by +calling stop() or by manually setting {\tt output} to FALSE using +setOutput() before termination of the program. The reason is that +potentially RMInit::bmOut may be destructed before the RMTimer +destructor is called possibly causing a crash. +*/ + +/** + * \ingroup RMs + */ + +class RMTimer : public RM_Class +{ +public: + /// constructor, initializes members and starts timer. + inline RMTimer(const char* newClass, const char* newFunc, + int newBmLevel = 0); + /** + The parameters newClass and newFunc have to be string literals. Just + a pointer to them is stored. No output is generated if RManBenchmark + < newBmLevel. + */ + /// destructor, calls stop(). + inline ~RMTimer(); + /// switch output on RMInit::bmOut on and off. + inline void setOutput(int newOutput); + /** + If newOutoutput is FALSE no output is created on RMInit::bmOut on + the following calls to stop() and ~RMTimer() until the next start(). + */ + /// pauses timer. + inline void pause(); + /// resumes timer. + inline void resume(); + /// resets timer. + inline void start(); + /** + Also switches output to RMInit::bmOut on again. + */ + /// prints time spent if output is TRUE. + inline void stop(); + /** + Time spent is the time since construction or last start() excluding + the times between pause() and resume(). + */ +private: + /// name of class. + const char* myClass; + /// name of function (no parameters). + const char* myFunc; + /// flag, if stop() should print timing information + int output; + /// stores benchmark level, checked before output. + int bmLevel; + // reference parameter for gettimeofday(). +#ifdef __VISUALC__ + time_t acttime; +#else + timeval acttime; +#endif + /// accu for saving time in us + long accuTime; + /// flag indicating if the timer is currently running. + unsigned short running; + // reference parameter for gettimeofday, not used. + static struct timezone dummy; + /// used to calculate time spent in function. + long oldsec; + /// used to calculate time spent in function. + long oldusec; +}; +///Module: {\bf raslib}. + +/** +Objects of this class increment the indent level of RMDebug at construction time and decrease this level at destruction time. +*/ + +/** + * \ingroup RMs + */ + +class RMCounter : public RM_Class +{ +public: + /// constructor, increments indent level if the class should be debugged. + RMCounter(int levell, int module, const char* cls); + /// destructor, decrements indent level. + ~RMCounter(); +private: + bool doStuff; +}; + + +#include "raslib/rmdebug.icc" + +#endif diff --git a/raslib/rmdebug.icc b/raslib/rmdebug.icc new file mode 100644 index 0000000..5c7a292 --- /dev/null +++ b/raslib/rmdebug.icc @@ -0,0 +1,120 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +// -*-C++-*- (for Emacs) + +inline +RMTimer::RMTimer(const char* newClass, const char* newFunc, int newBmLevel) + : myClass(newClass), myFunc(newFunc), bmLevel(newBmLevel), running(0) +{ +#ifdef __VISUALC__ + /* Set time zone from TZ environment variable.If TZ is not set, + * the operating system is queried to obtain the default value + * for the variable + */ + _tzset(); +#endif + start(); +} + +inline +RMTimer::~RMTimer() +{ + stop(); +} + +inline void +RMTimer::setOutput(int newOutput) +{ + output = newOutput; +} + +inline void +RMTimer::start() +{ + // reset accu + accuTime = 0; + // set output to TRUE + output = 1; + resume(); +} + +inline void +RMTimer::pause() +{ + if( running ) + { +#ifdef __VISUALC__ + // save start time + oldsec = acttime; + oldusec = 0; // Windows only counts the seconds (too slow??!!) + + // get stop time + time(&acttime); + + // add new time to accu + accuTime += (acttime-oldsec)*1000000; +#else + // save start time + oldsec = acttime.tv_sec; + oldusec = acttime.tv_usec; + + // get stop time + gettimeofday(&acttime, &dummy); + + // add new time to accu + accuTime += (acttime.tv_sec-oldsec)*1000000 + acttime.tv_usec - oldusec; + + // reset acttime.tv_usec which means that no timer is running + acttime.tv_usec = 0; +#endif + // timer is not running + running = 0; + } +} + +inline void +RMTimer::resume() +{ +#ifdef __VISUALC__ + time(&acttime); +#else + gettimeofday(&acttime, &dummy); +#endif + + // timer is running + running = 1; +} + +inline void +RMTimer::stop() +{ + pause(); + + if(output && RManBenchmark >= bmLevel ) { + RMInit::bmOut << "T: " << myClass << "::" << myFunc << ": " + << accuTime << "us" << std::endl; + // set output to FALSE + output = 0; + } +} diff --git a/raslib/rminit.cc b/raslib/rminit.cc new file mode 100644 index 0000000..78c68cf --- /dev/null +++ b/raslib/rminit.cc @@ -0,0 +1,321 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * SOURCE: rminit.cc + * + * MODULE: raslib + * CLASS: RMInit + * + * COMMENTS: + * +*/ + +static const char rcsid[] = "@(#)raslib, RMInit: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/rminit.cc,v 1.36 2005/09/09 16:14:24 rasdev Exp $"; + +#include "raslib/rminit.hh" + +#include "raslib/error.hh" +#include "raslib/rmdebug.hh" + +#include <string.h> +#include <stdlib.h> + +using std::cout; +using std::ios; + +char* RMInit::userName = 0; +bool RMInit::useTileContainer = false; +bool RMInit::tiling; +unsigned long RMInit::timeOut; +bool RMInit::noTimeOut = 0; +unsigned int RMInit::clientcommMaxRetry = 6; // changed from 100, with new wait algorithm in rnprotocol/rnpclientcomm.cc this is ~6sec -- PB 2005-sep-09 +unsigned int RMInit::clientcommSleep = 0; +unsigned int RMInit::rpcMaxRetry = 5; + +r_Bytes RMInit::clientTileSize = 786432; + +RMInit::RMInit( char initApplicationType ) + : applicationType( initApplicationType ) +{ + char* optString; + + if( applicationType == 'C' ) + { + char* value; + + // read environment options + optString = getenv("RMANCLIENTOPT"); + + // + // set log stream + // + if( optString && checkOptionString( optString, "-l", value ) ) + if( value ) + { + logFileOut.open( value ); + logOut.rdbuf(logFileOut.rdbuf()); + delete[] value; + } + else { + logOut.rdbuf(cout.rdbuf()); + } + else + { + // default + logFileOut.open("/dev/null",ios::app); //"client.log"); + logOut.rdbuf(logFileOut.rdbuf()); + } + + + + // + // set dbg stream + // + if( optString && checkOptionString( optString, "-d", value ) ) + if( value ) + { + dbgFileOut.open( value ); + dbgOut.rdbuf(dbgFileOut.rdbuf()); + delete[] value; + } + else + dbgOut.rdbuf(cout.rdbuf()); + else + { + // default + dbgFileOut.open("/dev/null",ios::app); //"client.dbg"); + dbgOut.rdbuf(dbgFileOut.rdbuf()); + } + + + // + // set debug level + // + if( optString && checkOptionString( optString, "-dl", value ) ) + if( value ) + { + RManDebug = (int)strtoul( value, (char **)NULL, 10 ); +// It is not clarrified why the delete statement crashes with VISUALC. +#ifndef __VISUALC__ + delete[] value; +#endif + } + + + // + // set bm stream + // + if( optString && checkOptionString( optString, "-b", value ) ) + if( value ) + { + bmFileOut.open( value ); + bmOut.rdbuf(bmFileOut.rdbuf()); + delete[] value; + } + else + bmOut.rdbuf(cout.rdbuf()); + else + { + // default + bmFileOut.open("/dev/null",ios::app); //"client.bm"); + bmOut.rdbuf(bmFileOut.rdbuf()); + } + + + // + // set benchmark level + // + if( optString && checkOptionString( optString, "-bl", value ) ) + if( value ) + { + RManBenchmark = (int)strtoul( value, (char **)NULL, 10 ); +// It is not clarrified why the delete statement crashes with VISUALC. +#ifndef __VISUALC__ + delete[] value; +#endif + } + + + // + // set tiling parameters + // + if(optString) + tiling = !checkOptionString( optString, "-notiling", value ); + else + tiling = 1; + + if( optString && checkOptionString( optString, "-tilesize", value ) ) + if( value ) + { + RMInit::clientTileSize = strtoul( value, (char **)NULL, 10 ); + delete[] value; + } + + if(optString && checkOptionString( optString, "-useTC", value )) + useTileContainer = true; + else + useTileContainer = false; + + timeOut = 3600; // default + if( optString && checkOptionString( optString, "-timeout", value ) ) + if( value ) + { + timeOut = strtoul( value, (char **)NULL, 10 ); + delete[] value; + } + + if( optString && checkOptionString( optString, "-notimeout", value ) ) + noTimeOut = 1; + else + noTimeOut = 0; + } + else + { + // default + logOut.rdbuf(cout.rdbuf()); + dbgOut.rdbuf(cout.rdbuf()); + bmOut.rdbuf(cout.rdbuf()); + } + + // initialize error text table + initTextTable(); + + // initialize user name + if( userName ) + { + delete [] userName; + userName = 0; + } + + optString = getenv("USER"); + if( optString ) + { + userName = new char[strlen(optString)+1]; + strcpy( userName, optString ); + } + else + { + userName = new char[8]; + strcpy( userName, "unknown" ); + } + +#ifdef RMANDEBUG + RMDebug::initRMDebug(); +#endif +} + + + +RMInit::~RMInit() +{ + // reset output streams + logOut.rdbuf(NULL); + dbgOut.rdbuf(NULL); + bmOut.rdbuf(NULL); + + // free error text table + freeTextTable(); + + if( userName ) + { + delete [] userName; + userName = 0; + } +} + + + +int +RMInit::checkOptionString( const char* optString, const char* option, char* &value ) +{ + char* optPos=0; + char* optValueStart; + char* optValueEnd; + int valueLength; + + using namespace std; + + value = 0; + + if( (optString != NULL) && (option != NULL) ) + { + unsigned short found = 0; + + optPos = (char*)optString; + + do{ + optPos = strstr( optPos, option ); + + if( optPos ) + { + // Check if character after option is either a space or end of string. + // If not, continue with search. + + char* continuePos = optPos + strlen(option); + + found = (*continuePos == ' ') || (*continuePos == '\0'); + + if( !found ) optPos = continuePos; + } + + }while( !found && optPos != 0 ); + + } + + if( optPos ) + { + + optValueStart = optPos + strlen(option); // move over option + while( *optValueStart == ' ' ) optValueStart++; // move over spaces + + if( *optValueStart != '-' && *optValueStart != '\0' ) + { + optValueEnd = optValueStart; + while( *optValueEnd != ' ' && *optValueEnd != '\0' ) optValueEnd++; // move over option value + + valueLength = optValueEnd - optValueStart; + if( valueLength ) + { + value = new char[valueLength+1]; + strncpy( value, optValueStart, valueLength ); + value[valueLength] = '\0'; + } + } + } + + /* + if( optPos ) + { + cout << "Option " << option << " specified;" << flush; + + if( value ) + cout << " value: " << value << " length: " << strlen(value) << endl; + else + cout << endl; + } + else + cout << "Option " << option << " not specified." << endl; + */ + + return optPos != 0; +} diff --git a/raslib/rminit.hh b/raslib/rminit.hh new file mode 100644 index 0000000..fc1ef9e --- /dev/null +++ b/raslib/rminit.hh @@ -0,0 +1,181 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: rminit.hh + * + * PURPOSE: + * Contains the RMInit class. + * + * COMMENTS: + * - RASMGRPORT should be centrally defined +*/ + +#ifndef _RMINIT_ +#define _RMINIT_ + +#include <iostream> +using std::ios; +using std::endl; + +#include <fstream> +#include <raslib/mddtypes.hh> +#include <raslib/rm.hh> + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + RMANVERSION is the version of the RasDaMan server times 1000 (int). + RPCVERSION is the version of the RPC interface times 1000 (int); + +*/ + +//@Man: Version numbers +// RMANVERSION now comes in via -DRMANVERSION -- PB 2003-sep-03 +// const int RMANVERSION = 5100; +const int RPCVERSION = 1003; + +// default rasmgr port +const int RASMGRPORT = 7001; + +// RPC timeout [secs]; used in clientcomm/rpcclientcomm.cc -- PB 2005-sep-09 +const unsigned int RPC_TIMEOUT = 3; + +// timeout in RNP communication +const unsigned int RNP_COMM_TIMEOUT = 60; + +// timeout in nerver.cc +const unsigned int RNP_TIMEOUT_LISTEN = 30; + +// maximum number of retries in rnprotocol/rnpclientcomm2.cc +const unsigned int RNP_MAX_RETRY = 10; + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + Class {\tt RMInit} is supposed to be instantiated just once. The scope + of this instance is equal to the program scope (global variable) + and therefore lifetime of the {\tt RMInit} instance and the application + are the same. The constructor is used to allocate ressources needed + during the whole application and the destructor cleans up memory at + the end of the application. + +*/ + +/** + * \ingroup RMs + */ + +class RMInit : public RM_Class +{ + public: + /// constructor + RMInit( char applicationType ); + + /// destructor + ~RMInit(); + + /// output stream for log information + static std::ostream logOut; + + /// output stream for debug information + static std::ostream dbgOut; + + /// output stream for benchmark information + static std::ostream bmOut; + + /// file output for log information + static std::ofstream logFileOut; + + /// file output for debug information + static std::ofstream dbgFileOut; + + /// file output for benchmark information + static std::ofstream bmFileOut; + + /// name of the user + static char* userName; + + /// use inlinetiles and inlinetile container index + static bool useTileContainer; + + /// switch for turning on/off tiling + static bool tiling; + + /// specifies time out in seconds + static unsigned long timeOut; + + /// flag, if time out checking is enabled (causes sometimes problems because of signal handler) + static bool noTimeOut; + + static r_Bytes clientTileSize; + + static unsigned int clientcommMaxRetry; + + static unsigned int clientcommSleep; + + static unsigned int rpcMaxRetry; + + private: + /// check the option string for the occurance of an option and return its value if available + int checkOptionString( const char* optString, const char* option, char* &value ); + /** + The method searches for an option of type {\tt -option value } in the option string specified. + It returns 1 if the option is in the string, otherwise 0. If a value is given for the option + to check, it is returned by the reference pointer {\tt value}. The value has to freed using + {\tt delete[] value} after it is not needed anymore. + */ + + /// type of application can either be 'S' for server or 'C' for client + char applicationType; +}; + +// Macro for initialization of static members and creation of global RMInit instance +// --------------------------------------------------------------------------------- +// The macro has to be invoked exactly once in each executable using raslib. +// +// rasserver -> in servercomm.o +// rasdaman clients -> in clientcomm.o +// test programms without clientcomm.o and servercomm.o -> in main.o +// +// The reason is that initialisation of globals can be initialized in any +// order if they are in different files. Only in one file the order is defined. +// As it is implemented now, the streams have to be defined somewhere. This +// could easily be done in rminit.cc. But the call to the constructor of RMInit +// has to get a flag for client ('C') or server ('S') as a parameter. This has +// be done somewhere else. In that case the constructor may be called before +// initialization of the streams, the pogram crashes! If all initialisations +// are in the same file, the order is defined. That is what this macro is for. +// +// Note: At some point it may be useful to reimplement this mess. + +#define RMINITGLOBALS( appMode ) std::ostream RMInit::logOut(std::cout.rdbuf()); \ + std::ostream RMInit::dbgOut(std::cout.rdbuf()); \ + std::ostream RMInit::bmOut(std::cout.rdbuf()); \ + std::ofstream RMInit::logFileOut; \ + std::ofstream RMInit::dbgFileOut; \ + std::ofstream RMInit::bmFileOut; \ + RMInit rmInit( appMode ); + +#endif diff --git a/raslib/scalar.cc b/raslib/scalar.cc new file mode 100644 index 0000000..23603e4 --- /dev/null +++ b/raslib/scalar.cc @@ -0,0 +1,120 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * SOURCE: scalar.cc + * + * MODULE: raslib + * CLASS: r_Scalar + * + * COMMENTS: + * +*/ + +#ifdef __VISUALC__ +#include <strstrea.h> +#else +#include <strstream> +#endif +#include <string.h> +#include <fstream> +#include <stdlib.h> + +#include "raslib/rminit.hh" +#include "raslib/scalar.hh" +#include "raslib/basetype.hh" +#include "raslib/error.hh" + + + + +r_Scalar::r_Scalar( const r_Base_Type* newType ) + : valueType(NULL) +{ + if( newType ) + valueType = (r_Base_Type*)newType->clone(); + else { + RMInit::logOut << "r_Scalar::r_Scalar(NULL) base type must be not NULL" << endl; + throw r_Error(SCALARWASPASSEDNULLTYPE); + } +} + + + +r_Scalar::r_Scalar( const r_Scalar& obj ) + : valueType(obj.valueType) +{ +} + + + +r_Scalar::~r_Scalar() +{ + delete valueType; +} + + + +const r_Scalar& +r_Scalar::operator=( const r_Scalar& obj ) +{ + if( this != &obj ) + { + delete valueType; + valueType = (r_Base_Type*)obj.valueType->clone(); + } + + return *this; +} + +bool +r_Scalar::isStructure() const + { + return false; + } + +bool +r_Scalar::isComplex() const + { + return false; + } + +bool +r_Scalar::isPrimitive() const + { + return false; + } + +const r_Base_Type* +r_Scalar::get_type() const +{ + return valueType; +} + + +std::ostream& operator<<( std::ostream& s, const r_Scalar& obj ) +{ + obj.print_status( s ); + return s; +} + + diff --git a/raslib/scalar.hh b/raslib/scalar.hh new file mode 100644 index 0000000..84132b4 --- /dev/null +++ b/raslib/scalar.hh @@ -0,0 +1,100 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: scalar.hh + * + * MODULE: raslib + * CLASS: r_Scalar + * + * COMMENTS: + * + * The class represents a scalar type value. + * +*/ + +#ifndef _D_SCALAR_ +#define _D_SCALAR_ + +#include <iosfwd> + +#include "raslib/error.hh" + +class r_Base_Type; + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + Class \Ref{r_Scalar} represents a scalar type value which + is either \Ref{r_Primitive} or \Ref{r_Structure}. + +*/ + +class r_Scalar +{ + public: + /// constructs a scalar value + r_Scalar( const r_Base_Type* newType ); + + /// copy constructor + r_Scalar( const r_Scalar& obj ); + + /// destructor + virtual ~r_Scalar(); + + /// clone operator + virtual r_Scalar* clone() const=0; + + /// operator for assigning a scalar + virtual const r_Scalar& operator= ( const r_Scalar& ); + + /// debug output + virtual void print_status(std::ostream& s) const = 0; + + /// get type + virtual const r_Base_Type* get_type() const; + + /// + virtual bool isStructure() const; + + /// + virtual bool isComplex() const; + + /// + virtual bool isPrimitive() const; + + protected: + /// type + r_Base_Type* valueType; +}; + + + +//@ManMemo: Module: {\bf raslib} +/** + Output stream operator for objects of type {\tt const} \Ref{r_Scalar}. +*/ +extern std::ostream& operator<<(std::ostream& s, const r_Scalar& obj ); + +#endif + diff --git a/raslib/shhopt.c b/raslib/shhopt.c new file mode 100644 index 0000000..217c096 --- /dev/null +++ b/raslib/shhopt.c @@ -0,0 +1,485 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/* $Id: shhopt.c,v 1.4 2000/09/20 14:41:56 widmann Exp $ */ +/* * + * FILE shhopt.c + * + * DESCRIPTION Functions for parsing command line arguments. Values + * of miscellaneous types may be stored in variables, + * or passed to functions as specified. + * + * REQUIREMENTS Some systems lack the ANSI C -function strtoul. If your + * system is one of those, you'll ned to write one yourself, + * or get the GNU liberty-library (from prep.ai.mit.edu). + * +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <ctype.h> +#include <limits.h> +#include <errno.h> + +#include "shhopt.h" + +/************************************************************************** + * * + * P R I V A T E D A T A * + * * + **************************************************************************/ + +static void optFatalFunc(const char *, ...); +static void (*optFatal)(const char *format, ...) = optFatalFunc; + + + +/************************************************************************** + * * + * P R I V A T E F U N C T I O N S * + * * + **************************************************************************/ + +/*------------------------------------------------------------------------- + * + * NAME optFatalFunc + * + * FUNCTION Show given message and abort the program. + * + * INPUT format, ... + * Arguments used as with printf(). + * + * RETURNS Never returns. The program is aborted. + * + */ +void optFatalFunc(const char *format, ...) +{ + va_list ap; + + fflush(stdout); + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + exit(99); +} + + + +/*------------------------------------------------------------------------- + * + * NAME optStructCount + * + * FUNCTION Get number of options in a optStruct. + * + * INPUT opt array of possible options. + * + * RETURNS Number of options in the given array. + * + * DESCRIPTION Count elements in an optStruct-array. The strcture must + * be ended using an element of type OPT_END. + * + */ +static int optStructCount(optStruct opt[]) +{ + int ret = 0; + + while (opt[ret].type != OPT_END) + ++ret; + return ret; +} + + + +/*------------------------------------------------------------------------- + * + * NAME optMatch + * + * FUNCTION Find a matching option. + * + * INPUT opt array of possible options. + * s string to match, without `-' or `--'. + * lng match long option, otherwise short. + * + * RETURNS Index to the option if found, -1 if not found. + * + * DESCRIPTION Short options are matched from the first character in + * the given string. + * + */ +static int optMatch(optStruct opt[], const char *s, int lng) +{ + int nopt, q, matchlen = 0; + char *p; + + nopt = optStructCount(opt); + if (lng) { + if ((p = (char*)strchr(s, '=')) != NULL) + matchlen = p - s; + else + matchlen = strlen(s); + } + for (q = 0; q < nopt; q++) { + if (lng) { + if (!opt[q].longName) + continue; + if (strncmp(s, opt[q].longName, matchlen) == 0) + return q; + } else { + if (!opt[q].shortName) + continue; + if (*s == opt[q].shortName) + return q; + } + } + return -1; +} + + + +/*------------------------------------------------------------------------- + * + * NAME optString + * + * FUNCTION Return a (static) string with the option name. + * + * INPUT opt the option to stringify. + * lng is it a long option? + * + * RETURNS Pointer to static string. + * + */ +static char *optString(optStruct *opt, int lng) +{ + static char ret[31]; + + if (lng) { + strcpy(ret, "--"); + strncpy(ret + 2, opt->longName, 28); + } else { + ret[0] = '-'; + ret[1] = opt->shortName; + ret[2] = '\0'; + } + return ret; +} + + + +/*------------------------------------------------------------------------- + * + * NAME optNeedsArgument + * + * FUNCTION Check if an option requires an argument. + * + * INPUT opt the option to check. + * + * RETURNS Boolean value. + * + */ +static int optNeedsArgument(optStruct *opt) +{ + return opt->type == OPT_STRING + || opt->type == OPT_INT + || opt->type == OPT_UINT + || opt->type == OPT_LONG + || opt->type == OPT_ULONG; +} + + + +/*------------------------------------------------------------------------- + * + * NAME argvRemove + * + * FUNCTION Remove an entry from an argv-array. + * + * INPUT argc pointer to number of options. + * argv array of option-/argument-strings. + * i index of option to remove. + * + * OUTPUT argc new argument count. + * argv array with given argument removed. + * + */ +static void argvRemove(int *argc, char *argv[], int i) +{ + if (i >= *argc) + return; + while (i++ < *argc) + argv[i - 1] = argv[i]; + --*argc; +} + + + +/*------------------------------------------------------------------------- + * + * NAME optExecute + * + * FUNCTION Perform the action of an option. + * + * INPUT opt array of possible options. + * arg argument to option, if it applies. + * lng was the option given as a long option? + * + * RETURNS Nothing. Aborts in case of error. + * + */ +void optExecute(optStruct *opt, char *arg, int lng) +{ + switch (opt->type) { + case OPT_FLAG: + if (opt->flags & OPT_CALLFUNC) + ((void (*)(void)) opt->arg)(); + else + *((int *) opt->arg) = 1; + break; + + case OPT_STRING: + if (opt->flags & OPT_CALLFUNC) + ((void (*)(char *)) opt->arg)(arg); + else + *((char **) opt->arg) = arg; + break; + + case OPT_INT: + case OPT_LONG: { + long tmp; + char *e; + + tmp = strtol(arg, &e, 10); + if (*e) + optFatal("invalid number `%s'\n", arg); + if (errno == ERANGE + || (opt->type == OPT_INT && (tmp > INT_MAX || tmp < INT_MIN))) + optFatal("number `%s' to `%s' out of range\n", + arg, optString(opt, lng)); + if (opt->type == OPT_INT) { + if (opt->flags & OPT_CALLFUNC) + ((void (*)(int)) opt->arg)((int) tmp); + else + *((int *) opt->arg) = (int) tmp; + } else /* OPT_LONG */ { + if (opt->flags & OPT_CALLFUNC) + ((void (*)(long)) opt->arg)(tmp); + else + *((long *) opt->arg) = tmp; + } + break; + } + + case OPT_UINT: + case OPT_ULONG: { + unsigned long tmp; + char *e; + + tmp = strtoul(arg, &e, 10); + if (*e) + optFatal("invalid number `%s'\n", arg); + if (errno == ERANGE + || (opt->type == OPT_UINT && tmp > UINT_MAX)) + optFatal("number `%s' to `%s' out of range\n", + arg, optString(opt, lng)); + if (opt->type == OPT_UINT) { + if (opt->flags & OPT_CALLFUNC) + ((void (*)(unsigned)) opt->arg)((unsigned) tmp); + else + *((unsigned *) opt->arg) = (unsigned) tmp; + } else /* OPT_ULONG */ { + if (opt->flags & OPT_CALLFUNC) + ((void (*)(unsigned long)) opt->arg)(tmp); + else + *((unsigned long *) opt->arg) = tmp; + } + break; + } + + default: + break; + } +} + + + +/************************************************************************** + * * + * P U B L I C F U N C T I O N S * + * * + **************************************************************************/ + +/*------------------------------------------------------------------------- + * + * NAME optSetFatalFunc + * + * FUNCTION Set function used to display error message and exit. + * + * SYNOPSIS #include "shhmsg.h" + * void optSetFatalFunc(void (*f)(const char *, ...)); + * + * INPUT f function accepting printf()'like parameters, + * that _must_ abort the program. + * + */ +void optSetFatalFunc(void (*f)(const char *, ...)) +{ + optFatal = f; +} + + + +/*------------------------------------------------------------------------- + * + * NAME optParseOptions + * + * FUNCTION Parse commandline options. + * + * SYNOPSIS #include "shhopt.h" + * void optParseOptions(int *argc, char *argv[], + * optStruct opt[], int allowNegNum); + * + * INPUT argc Pointer to number of options. + * argv Array of option-/argument-strings. + * opt Array of possible options. + * allowNegNum + * a negative number is not to be taken as + * an option. + * + * OUTPUT argc new argument count. + * argv array with arguments removed. + * + * RETURNS Nothing. Aborts in case of error. + * + * DESCRIPTION This function checks each option in the argv-array + * against strings in the opt-array, and `executes' any + * matching action. Any arguments to the options are + * extracted and stored in the variables or passed to + * functions pointed to by entries in opt. + * + * Options and arguments used are removed from the argv- + * array, and argc is decreased accordingly. + * + * Any error leads to program abortion. + * + */ +void optParseOptions(int *argc, char *argv[], optStruct opt[], int allowNegNum) +{ + int ai, /* argv index. */ + optarg, /* argv index of option argument, or -1 if none. */ + mi, /* Match index in opt. */ + done; + char *arg, /* Pointer to argument to an option. */ + *o, /* pointer to an option character */ + *p; + + /* + * Loop through all arguments. + */ + for (ai = 0; ai < *argc; ) { + /* + * "--" indicates that the rest of the argv-array does not + * contain options. + */ + if (strcmp(argv[ai], "--") == 0) { + argvRemove(argc, argv, ai); + break; + } + + if (allowNegNum && argv[ai][0] == '-' && isdigit(argv[ai][1])) { + ++ai; + continue; + } else if (strncmp(argv[ai], "--", 2) == 0) { + /* long option */ + /* find matching option */ + if ((mi = optMatch(opt, argv[ai] + 2, 1)) < 0) + optFatal("unrecognized option `%s'\n", argv[ai]); + + /* possibly locate the argument to this option. */ + arg = NULL; + if ((p = strchr(argv[ai], '=')) != NULL) + arg = p + 1; + + /* does this option take an argument? */ + optarg = -1; + if (optNeedsArgument(&opt[mi])) { + /* option needs an argument. find it. */ + if (!arg) { + if ((optarg = ai + 1) == *argc) + optFatal("option `%s' requires an argument\n", + optString(&opt[mi], 1)); + arg = argv[optarg]; + } + } else { + if (arg) + optFatal("option `%s' doesn't allow an argument\n", + optString(&opt[mi], 1)); + } + /* perform the action of this option. */ + optExecute(&opt[mi], arg, 1); + /* remove option and any argument from the argv-array. */ + if (optarg >= 0) + argvRemove(argc, argv, ai); + argvRemove(argc, argv, ai); + } else if (*argv[ai] == '-') { + /* A dash by itself is not considered an option. */ + if (argv[ai][1] == '\0') { + ++ai; + continue; + } + /* Short option(s) following */ + o = argv[ai] + 1; + done = 0; + optarg = -1; + while (*o && !done) { + /* find matching option */ + if ((mi = optMatch(opt, o, 0)) < 0) + optFatal("unrecognized option `-%c'\n", *o); + + /* does this option take an argument? */ + optarg = -1; + arg = NULL; + if (optNeedsArgument(&opt[mi])) { + /* option needs an argument. find it. */ + arg = o + 1; + if (!*arg) { + if ((optarg = ai + 1) == *argc) + optFatal("option `%s' requires an argument\n", + optString(&opt[mi], 0)); + arg = argv[optarg]; + } + done = 1; + } + /* perform the action of this option. */ + optExecute(&opt[mi], arg, 0); + ++o; + } + /* remove option and any argument from the argv-array. */ + if (optarg >= 0) + argvRemove(argc, argv, ai); + argvRemove(argc, argv, ai); + } else { + /* a non-option argument */ + ++ai; + } + } +} diff --git a/raslib/shhopt.h b/raslib/shhopt.h new file mode 100644 index 0000000..2fca504 --- /dev/null +++ b/raslib/shhopt.h @@ -0,0 +1,56 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +/* $Id: shhopt.h,v 1.4 2000/09/20 14:41:56 widmann Exp $ */ +#ifndef SHHOPT_H +#define SHHOPT_H + +/* constants for recognized option types. */ +typedef enum { + OPT_END, /* nothing. used as ending element. */ + OPT_FLAG, /* no argument following. sets variable to 1. */ + OPT_STRING, /* string argument. */ + OPT_INT, /* signed integer argument. */ + OPT_UINT, /* unsigned integer argument. */ + OPT_LONG, /* signed long integer argument. */ + OPT_ULONG /* unsigned long integer argument. */ +} optArgType; + +/* flags modifying the default way options are handeled. */ +#define OPT_CALLFUNC 1 /* pass argument to a function. */ + +typedef struct { + char shortName; /* Short option name. */ + char *longName; /* Long option name, no including '--'. */ + optArgType type; /* Option type. */ + void *arg; /* Pointer to variable to fill with argument, + * or pointer to function if Type == OPT_FUNC. */ + int flags; /* Modifier flags. */ +} optStruct; + + +void optSetFatalFunc(void (*f)(const char *, ...)); +void optParseOptions(int *argc, char *argv[], + optStruct opt[], int allowNegNum); + +#endif diff --git a/raslib/sinterval.cc b/raslib/sinterval.cc new file mode 100644 index 0000000..e05857f --- /dev/null +++ b/raslib/sinterval.cc @@ -0,0 +1,1018 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * SOURCE: sinterval.cc + * + * MODULE: raslib + * CLASS: r_Sinterval + * + * COMMENTS: + * +*/ + +static const char rcsid[] = "@(#)raslib, r_Sinterval: $Id: sinterval.cc,v 1.29 2002/08/19 11:11:25 coman Exp $"; + +#include "sinterval.hh" + +#include <string> +#include <cstring> + +#ifdef __VISUALC__ +#include <strstrea.h> +#else +#include <strstream> +#endif + +// for min and max +#include <algorithm> + +using namespace std; + + +#include "raslib/error.hh" +#include "raslib/rminit.hh" + +r_Sinterval::r_Sinterval() + : lower_bound(0), + upper_bound(0), + low_fixed(false), + high_fixed(false) +{ +} + + +r_Sinterval::r_Sinterval( char* stringRep ) throw(r_Eno_interval) + : lower_bound(0), + upper_bound(0), + low_fixed(false), + high_fixed(false) +{ + if(!stringRep) { + RMInit::dbgOut << "r_Sinterval::r_Sinterval(" << (stringRep?stringRep: "NULL") << ")" << std::endl; + throw r_Eno_interval(); + } + + char charToken = 0; + r_Range valueToken = 0; + + // for parsing the string + std::istrstream str(stringRep, strlen(stringRep) + 1); + + str >> charToken; + if(charToken == '*') + set_low('*'); + else + { + str.putback(charToken); + str >> valueToken; + set_low(valueToken); + } + + str >> charToken; + if(charToken != ':') + { + // error + lower_bound=0; + upper_bound=0; + low_fixed=false; + high_fixed=false; + + RMInit::dbgOut << "r_Sinterval::r_Sinterval(" << stringRep << ") string doesn't have the pattern a:b" << endl; + throw r_Eno_interval(); + } + + str >> charToken; + if(charToken == '*') + set_high('*'); + else + { + str.putback(charToken); + str >> valueToken; + set_high(valueToken); + } +} + + +r_Sinterval::r_Sinterval( r_Range low, r_Range high ) throw( r_Eno_interval ) + : lower_bound(low), + upper_bound(high), + low_fixed(true), + high_fixed(true) +{ + if( low > high ) + { + RMInit::dbgOut << "r_Sinterval::r_Sinterval(" << low << ", " << high << ") not a interval" << endl; + throw r_Eno_interval(); + } +} + + +r_Sinterval::r_Sinterval( char, r_Range high ) + : lower_bound(0), + upper_bound(high), + low_fixed(false), + high_fixed(true) +{ +} + + +r_Sinterval::r_Sinterval( r_Range low, char ) + : lower_bound(low), + upper_bound(0), + low_fixed(true), + high_fixed(false) +{ +} + + +r_Sinterval::r_Sinterval( char, char) + : lower_bound(0), + upper_bound(0), + low_fixed(false), + high_fixed(false) +{ +} + + +bool +r_Sinterval::operator==( const r_Sinterval& interval ) const +{ + bool returnValue=true; + + if (low_fixed) + returnValue = interval.low_fixed && lower_bound == interval.lower_bound; + else + returnValue = !interval.low_fixed;//other is fixed -> false + if (returnValue) + { + if( high_fixed ) + returnValue = interval.high_fixed && upper_bound == interval.upper_bound; + else + returnValue = !interval.high_fixed; + } + + return returnValue; +} + + + +bool +r_Sinterval::operator!=( const r_Sinterval& interval ) const +{ + return !operator==( interval ); +} + +r_Range +r_Sinterval::get_extent() const throw(r_Error) + { + r_Range ext; + + if(!low_fixed || !high_fixed) { + RMInit::dbgOut << "r_Sinterval::get_extent() low or high are not fixed (" << *this << ")" << std::endl; + throw r_Error(INTERVALOPEN); + } + + ext = upper_bound - lower_bound + 1; + + return ext; + } + +void +r_Sinterval::set_low ( r_Range low ) throw( r_Eno_interval ) { + if( high_fixed && low > upper_bound ) { + RMInit::dbgOut << "r_Sinterval::set_low(" << low << ") not an interval (" << *this << ")" << endl; + throw r_Eno_interval(); + } + + lower_bound = low; + low_fixed = true; +} + + +void +r_Sinterval::set_high( r_Range high ) throw( r_Eno_interval ) +{ + if( low_fixed && high < lower_bound ) { + RMInit::dbgOut << "r_Sinterval::set_high(" << high << ") not an interval (" << *this << ")" << endl; + throw r_Eno_interval(); + } + + upper_bound = high; + high_fixed = true; +} + + +void +r_Sinterval::set_interval( r_Range low, r_Range high ) throw( r_Eno_interval ) +{ + if( low > high ) { + RMInit::dbgOut << "r_Sinterval::set_interval(" << low << ", " << high << ") not an interval (" << *this << ")" << endl; + throw r_Eno_interval(); + } + + lower_bound = low; + upper_bound = high; + low_fixed = true; + high_fixed = true; +} + + +void +r_Sinterval::set_interval( char, r_Range high ) +{ + lower_bound = 0; + upper_bound = high; + low_fixed = false; + high_fixed = true; +} + + +void +r_Sinterval::set_interval( r_Range low, char ) +{ + lower_bound = low; + upper_bound = 0; + low_fixed = true; + high_fixed = false; +} + + +void +r_Sinterval::set_interval( char, char ) +{ + lower_bound = 0; + upper_bound = 0; + low_fixed = false; + high_fixed = false; +} + + +bool +r_Sinterval::intersects_with( const r_Sinterval& interval ) const +{ + int classnr = classify( *this, interval ); + + return classnr != 1 && classnr != 6 && classnr != 16 && classnr != 21 && + classnr != 26 && classnr != 31 && classnr != 34 && classnr != 37; +} + + +r_Sinterval& +r_Sinterval::union_of( const r_Sinterval& interval1, const r_Sinterval& interval2 ) throw( r_Eno_interval ) +{ + *this = calc_union( interval1, interval2 ); + + return *this; +} + + +r_Sinterval& +r_Sinterval::union_with( const r_Sinterval& interval ) throw( r_Eno_interval ) +{ + *this = calc_union( interval, *this ); + + return *this; +} + + +r_Sinterval& +r_Sinterval::operator+=( const r_Sinterval& interval ) throw( r_Eno_interval ) +{ + *this = calc_union( interval, *this ); + + return *this; +} + + +r_Sinterval +r_Sinterval::create_union( const r_Sinterval& interval ) const throw( r_Eno_interval ) +{ + r_Sinterval result; + + result = calc_union( interval, *this ); + + return result; +} + + +r_Sinterval +r_Sinterval::operator+( const r_Sinterval& interval ) const throw( r_Eno_interval ) +{ + r_Sinterval result; + + result = calc_union( interval, *this ); + + return result; +} + + +r_Sinterval& +r_Sinterval::difference_of( const r_Sinterval& interval1, const r_Sinterval& interval2 ) throw( r_Eno_interval ) +{ + *this = calc_difference( interval1, interval2 ); + + return *this; +} + + +r_Sinterval& +r_Sinterval::difference_with( const r_Sinterval& interval ) throw( r_Eno_interval ) +{ + *this = calc_difference( interval, *this ); + + return *this; +} + + + +r_Sinterval& +r_Sinterval::operator-=( const r_Sinterval& interval ) throw( r_Eno_interval ) +{ + *this = calc_difference( interval, *this ); + + return *this; +} + + +r_Sinterval +r_Sinterval::create_difference( const r_Sinterval& interval ) const throw( r_Eno_interval ) +{ + r_Sinterval result; + + result = calc_difference( interval, *this ); + + return result; +} + + +r_Sinterval +r_Sinterval::operator-( const r_Sinterval& interval ) const throw( r_Eno_interval ) +{ + r_Sinterval result; + + result = calc_difference( interval, *this ); + + return result; +} + + +r_Sinterval& +r_Sinterval::intersection_of( const r_Sinterval& interval1, const r_Sinterval& interval2 ) throw( r_Eno_interval ) +{ + *this = calc_intersection( interval1, interval2 ); + + return *this; +} + + +r_Sinterval& +r_Sinterval::intersection_with( const r_Sinterval& interval ) throw( r_Eno_interval ) +{ + *this = calc_intersection( interval, *this ); + + return *this; +} + + +r_Sinterval& +r_Sinterval::operator*=( const r_Sinterval& interval ) throw( r_Eno_interval ) +{ + *this = calc_intersection( interval, *this ); + + return *this; +} + + +r_Sinterval +r_Sinterval::create_intersection( const r_Sinterval& interval ) const throw( r_Eno_interval ) +{ + r_Sinterval result; + + result = calc_intersection( interval, *this ); + + return result; +} + + +r_Sinterval +r_Sinterval::operator*( const r_Sinterval& interval ) const throw( r_Eno_interval ) +{ + r_Sinterval result; + + result = calc_intersection( interval, *this ); + + return result; +} + + +r_Sinterval& +r_Sinterval::closure_of( const r_Sinterval& interval1, const r_Sinterval& interval2 ) throw( r_Eno_interval ) +{ + *this = calc_closure( interval1, interval2 ); + + return *this; +} + + +r_Sinterval& +r_Sinterval::closure_with( const r_Sinterval& interval ) throw( r_Eno_interval ) +{ + *this = calc_closure( interval, *this ); + + return *this; +} + + +r_Sinterval +r_Sinterval::create_closure( const r_Sinterval& interval ) const throw( r_Eno_interval ) +{ + r_Sinterval result; + + result = calc_closure( interval, *this ); + + return result; +} + + +void +r_Sinterval::print_status( std::ostream& s ) const +{ + if( low_fixed ) + s << lower_bound; + else + s << "*"; + + s << ":"; + + if( high_fixed ) + s << upper_bound; + else + s << "*"; +} + + +r_Bytes +r_Sinterval::get_storage_size( ) const +{ + return ( 2 * ( sizeof( r_Range ) + sizeof(bool) ) ); +} + +r_Sinterval +r_Sinterval::calc_union( const r_Sinterval& a, const r_Sinterval& b ) const throw( r_Eno_interval ) +{ + r_Sinterval result; + + switch( classify( a, b ) ) + { + case 2: + case 7: + case 9: + case 12: + case 22: + case 23: + case 27: + case 28: + case 35: + case 36: + // result = [a1:b2] + + if( a.is_low_fixed() ) + result.set_low( a.low() ); + else + result.set_low('*'); + + if( b.is_high_fixed() ) + result.set_high( b.high() ); + else + result.set_high('*'); + + break; + + case 4: + case 8: + case 10: + case 13: + case 17: + case 18: + case 32: + case 33: + case 38: + case 39: + // result = [b1:a2] + + if( b.is_low_fixed() ) + result.set_low( b.low() ); + else + result.set_low('*'); + + if( a.is_high_fixed() ) + result.set_high( a.high() ); + else + result.set_high('*'); + + break; + + case 3: + case 11: + case 14: + case 15: + case 19: + case 20: + case 41: + case 42: + case 43: + case 44: + case 46: + case 48: + case 49: + case 52: + result = a; + break; + + case 5: + case 24: + case 25: + case 29: + case 30: + case 40: + case 45: + case 47: + case 50: + case 51: + result = b; + break; + + default: // case in { 1, 6, 16, 21, 26, 31, 34, 37 } + { + RMInit::dbgOut << "r_Sinterval::calc_union(" << a << ", " << b << ") not an interval" << endl; + throw r_Eno_interval(); + } + } + + return result; +} + + +r_Sinterval +r_Sinterval::calc_difference( const r_Sinterval& a, const r_Sinterval& b ) const throw( r_Eno_interval ) +{ + r_Sinterval result; + + switch( classify( a, b ) ) + { + case 2: + case 9: + case 20: + case 23: + case 28: + case 36: + case 39: + case 43: + case 49: + // result = [a1:b1] + + if( a.is_low_fixed() ) + result.set_low( a.low() ); + else + result.set_low('*'); + + if( b.is_low_fixed() ) + result.set_high( b.low() ); + else + result.set_high('*'); + + break; + + case 1: + case 6: + case 7: + case 8: + case 16: + case 17: + case 21: + case 22: + case 26: + case 27: + case 31: + case 32: + case 34: + case 35: + case 37: + case 38: + result = a; + break; + + case 4: + case 10: + case 15: + case 18: + case 33: + case 42: + case 48: + // result = [b2:a2] + + if( b.is_high_fixed() ) + result.set_low( b.high() ); + else + result.set_low('*'); + + if( a.is_high_fixed() ) + result.set_high( a.high() ); + else + result.set_high('*'); + + break; + + default: // case in { 3, 5, 11, 12, 13, 14, 19, 24, 25, 29, 30, 40, 41, 44, 45, 46, 47, 50, 51, 52 } + { + RMInit::dbgOut << "r_Sinterval::calc_difference(" << a << ", " << b << ") not an interval" << endl; + throw r_Eno_interval(); + } + } + + return result; +} + + +r_Sinterval +r_Sinterval::calc_intersection( const r_Sinterval& a, const r_Sinterval& b ) const throw( r_Eno_interval ) +{ + r_Sinterval result; + + switch( classify( a, b ) ) + { + case 4: + case 18: + case 33: + case 39: + // result = [a1:b2] + + if( a.is_low_fixed() ) + result.set_low( a.low() ); + else + result.set_low('*'); + + if( b.is_high_fixed() ) + result.set_high( b.high() ); + else + result.set_high('*'); + + break; + + case 2: + case 23: + case 28: + case 36: + // result = [b1:a2] + + if( b.is_low_fixed() ) + result.set_low( b.low() ); + else + result.set_low('*'); + + if( a.is_high_fixed() ) + result.set_high( a.high() ); + else + result.set_high('*'); + + break; + + case 5: + case 11: + case 12: + case 13: + case 24: + case 25: + case 29: + case 30: + case 40: + case 41: + case 44: + case 45: + case 47: + case 50: + case 51: + case 52: + result = a; + break; + + case 3: + case 9: + case 10: + case 14: + case 15: + case 19: + case 20: + case 42: + case 43: + case 46: + case 48: + case 49: + result = b; + break; + + case 7: + case 22: + case 27: + case 35: + // result = [a2:a2] + + if( a.is_high_fixed() ) + result.set_interval( a.high(), a.high() ); + else + result.set_interval( '*', '*' ); + + break; + + case 8: + case 17: + case 32: + case 38: + // result = [b2:b2] + + if( b.is_high_fixed() ) + result.set_interval( b.high(), b.high() ); + else + result.set_interval( '*', '*' ); + + break; + + default: // case in { 1, 6, 16, 21, 26, 31, 34, 37 } + RMInit::dbgOut << "r_Sinterval::calc_intersection(" << a << ", " << b << ") not an interval" << endl; + throw r_Eno_interval(); + } + + return result; +} + + +r_Sinterval +r_Sinterval::calc_closure( const r_Sinterval& a, const r_Sinterval& b ) const throw( r_Eno_interval ) +{ + r_Sinterval closure; + + if( !a.is_low_fixed() || !b.is_low_fixed() ) + closure.set_low('*'); + else + closure.set_low( std::min( a.low(), b.low() ) ); + + if( !a.is_high_fixed() || !b.is_high_fixed() ) + closure.set_high('*'); + else + closure.set_high( std::max( a.high(), b.high() ) ); + + return closure; +} + + +/************************************************************* + * Method name...: classify + * + * Arguments.....: Two intervals for the classification. + * Return value..: The classification class number (1..52). + * Description...: The method classifies the two intervals into + * one of 13 classes according to their spatial + * relationship. Based on the classification, the + * result of the operations union, difference, + * and intersection can be calculated as shown + * in the table in file sinterval.hh: + ************************************************************/ + +int +r_Sinterval::classify( const r_Sinterval& a, const r_Sinterval& b ) const +{ + int classification = 0; + + if( a.is_low_fixed() && a.is_high_fixed() && b.is_low_fixed() && b.is_high_fixed() ) + { + // classification 1..13 + + if( a.low() < b.low() ) + { + if( a.high() < b.high() ) + { + if( a.high() < b.low() ) + classification = 1; + else + if( a.high() == b.low() ) + classification = 7; + else + classification = 2; + } + else if( a.high() == b.high() ) + classification = 9; + else + classification = 3; + } + else if( a.low() == b.low() ) + { + if( a.high() < b.high() ) + classification = 12; + else if( a.high() == b.high() ) + classification = 11; + else + classification = 10; + } + else + if( a.high() < b.high() ) + classification = 5; + else if( a.high() == b.high() ) + classification = 13; + else + { + if( a.low() < b.high() ) + classification = 4; + else if( a.low() == b.high() ) + classification = 8; + else + classification = 6; + } + } + else if( a.is_low_fixed() && !a.is_high_fixed() && b.is_low_fixed() && b.is_high_fixed() ) + { + // classification 14..18 + + if( a.low() < b.low() ) + classification = 14; + else if( a.low() == b.low() ) + classification = 15; + else + { + if( b.high() < a.low() ) + classification = 16; + else if( b.high() == a.low() ) + classification = 17; + else + classification = 18; + } + } + else if( !a.is_low_fixed() && a.is_high_fixed() && b.is_low_fixed() && b.is_high_fixed() ) + { + // classification 19..23 + + if( a.high() > b.high() ) + classification = 19; + else if( a.high() == b.high() ) + classification = 20; + else + { + if( a.high() < b.low() ) + classification = 21; + else if( a.high() == b.low() ) + classification = 22; + else + classification = 23; + } + } + else if( a.is_low_fixed() && a.is_high_fixed() && b.is_low_fixed() && !b.is_high_fixed() ) + { + // classification 24..28 + + if( b.low() < a.low() ) + classification = 24; + else if( b.low() == a.low() ) + classification = 25; + else + { + if( a.high() < b.low() ) + classification = 26; + else if( a.high() == b.low() ) + classification = 27; + else + classification = 28; + } + } + else if( a.is_low_fixed() && a.is_high_fixed() && !b.is_low_fixed() && b.is_high_fixed() ) + { + // classification 29..33 + + if( b.high() > a.high() ) + classification = 29; + else if( b.high() == a.high() ) + classification = 30; + else + { + if( b.high() < a.low() ) + classification = 31; + else if( b.high() == a.low() ) + classification = 32; + else + classification = 33; + } + } + else if( !a.is_low_fixed() && a.is_high_fixed() && b.is_low_fixed() && !b.is_high_fixed() ) + { + // classification 34..36 + + if( a.high() < b.low() ) + classification = 34; + else if( a.high() == b.low() ) + classification = 35; + else + classification = 36; + } + else if( a.is_low_fixed() && !a.is_high_fixed() && !b.is_low_fixed() && b.is_high_fixed() ) + { + // classification 37..39 + + if( b.high() < a.low() ) + classification = 37; + else if( b.high() == a.low() ) + classification = 38; + else + classification = 39; + } + else if( !a.is_low_fixed() && a.is_high_fixed() && !b.is_low_fixed() && b.is_high_fixed() ) + { + // classification 40..42 + + if( a.high() < b.high() ) + classification = 40; + else if( a.high() == b.high() ) + classification = 41; + else + classification = 42; + } + else if( a.is_low_fixed() && !a.is_high_fixed() && b.is_low_fixed() && !b.is_high_fixed() ) + { + // classification 43..45 + + if( a.low() < b.low() ) + classification = 43; + else if( a.low() == b.low() ) + classification = 44; + else + classification = 45; + } + else if( !a.is_low_fixed() && !a.is_high_fixed() && b.is_low_fixed() && b.is_high_fixed() ) + classification = 46; + else if( a.is_low_fixed() && a.is_high_fixed() && !b.is_low_fixed() && !b.is_high_fixed() ) + classification = 47; + else if( !a.is_low_fixed() && !a.is_high_fixed() && !b.is_low_fixed() && b.is_high_fixed() ) + classification = 48; + else if( !a.is_low_fixed() && !a.is_high_fixed() && b.is_low_fixed() && !b.is_high_fixed() ) + classification = 49; + else if( !a.is_low_fixed() && a.is_high_fixed() && !b.is_low_fixed() && !b.is_high_fixed() ) + classification = 50; + else if( a.is_low_fixed() && !a.is_high_fixed() && !b.is_low_fixed() && !b.is_high_fixed() ) + classification = 51; + else // !a.is_low_fixed() && !a.is_high_fixed() && !b.is_low_fixed() && !b.is_high_fixed() + classification = 52; + + return classification; +} + + + +char* +r_Sinterval::get_string_representation() const +{ + unsigned int bufferSize = 128; // should be enough + + // allocate buffer and initialize string stream + char* buffer = new char[bufferSize]; + std::ostrstream domainStream( buffer, bufferSize ); + + // write into string stream + domainStream << (*this) << ends; + + // allocate memory taking the final string + char* returnString = strdup(buffer); + + // delete buffer + delete[] buffer; + + return returnString; +} + + + +/************************************************************* + * Method name...: operator<<( std::ostream& s, r_Sinterval& d ) + ************************************************************/ +std::ostream& operator<<( std::ostream& s, const r_Sinterval& d ) +{ + d.print_status( s ); + return s; +} + diff --git a/raslib/sinterval.hh b/raslib/sinterval.hh new file mode 100644 index 0000000..f3edfab --- /dev/null +++ b/raslib/sinterval.hh @@ -0,0 +1,451 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: sinterval.hh + * + * MODULE: raslib + * CLASS: r_Sinterval + * + * COMMENTS: + * +*/ + +#ifndef _D_SINTERVAL_ +#define _D_SINTERVAL_ + +#ifdef __VISUALC__ +// Disable warning about exception specification. +#pragma warning( disable : 4290 ) +#endif + +class r_Error; +class r_Eno_interval; + +#include <iostream> + +#include "raslib/point.hh" + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + The class represents an interval with lower and upper bound. + Operations on the interval are defined according to the + ODMG-93 standard. + The operations union, difference, and intersection are + defined according to the following table: + + | ... fixed bound \\ + * ... open bound + + + \begin{verbatim} + + class orientation union difference intersection + ----------------------------------------------------------- + 1 |-a-| |-b-| error a error + + 2 |-a-| [a1,b2] [a1,b1] [b1,a2] + |-b-| + + 3 |--a--| a error b + |-b-| + + 4 |-b-| [b1,a2] [b2,a2] [a1,b2] + |-a-| + + 5 |--b--| b error a + |-a-| + + 6 |-b-| |-a-| error a error + + 7 |-a-|-b-| [a1,b2] a [a2,a2] + + 8 |-b-|-a-| [b1,a2] a [b2,b2] + + 9 |--a--| a [a1,b1] b + |-b-| + + 10 |--a--| a [b2,a2] b + |-b-| + + 11 |-a-| a error a + |-b-| + + 12 |--b--| b error a + |-a-| + + 13 |--b--| b error a + |-a-| + + ----------------------------------------------------- + + 14 |--a--* a error b + |-b-| + + 15 |--a--* a [b2,a2] b + |-b-| + + 16 |-b-| |-a-* error a error + + 17 |-b-|-a-* [b1,a2] a [b2,b2] + + 18 |--a--* [b1,a2] [b2,a2] [a1,b2] + |-b-| + + ----------------------------------------------------- + + 19 *--a--| a error b + |-b-| + + 20 *--a--| a [a1,b1] b + |-b-| + + 21 *-a-| |-b-| error a error + + 22 *-a-|-b-| [a1,b2] a [a2,a2] + + 23 *--a--| [a1,b2] [a1,b1] [b1,a2] + |-b-| + + ----------------------------------------------------- + + 24 |--b--* b error a + |-a-| + + 25 |--b--* b error a + |-a-| + + 26 |-a-| |-b-* error a error + + 27 |-a-|-b-* [a1,b2] a [a2,a2] + + 28 |--b--* [a1,b2] [a1,b1] [b1,a2] + |-a-| + + ----------------------------------------------------- + + 29 *--b--| b error a + |-a-| + + 30 *--b--| b error a + |-a-| + + 31 *-b-| |-a-| error a error + + 32 *-b-|-a-| [b1,a2] a [b2,b2] + + 33 *--b--| [b1,a2] [b2,a2] [a1,b2] + |-a-| + + ----------------------------------------------------- + + 34 *-a-| |-b-* error a error + + 35 *-a-|-b-* [a1,b2] a [a2,a2] + + 36 *-a-| [a1,b2] [a1,b1] [b1,a2] + |-b-* + + ----------------------------------------------------- + + 37 *-b-| |-a-* error a error + + 38 *-b-|-a-* [b1,a2] a [b2,b2] + + 39 *-b-| [b1,a2] [a1,b1] [a1,b2] + |-a-* + + ----------------------------------------------------- + + 40 *-a-| b error a + *-b-| + + 41 *-a-| a error a + *-b-| + + 42 *-b-| a [b2,a2] b + *-a-| + + ----------------------------------------------------- + + 43 |-a-* a [a1,b1] b + |-b-* + + 44 |-a-* a error a + |-b-* + + 45 |-b-* b error a + |-a-* + + ----------------------------------------------------- + 46 *-a-* |-b-| a error b + + 47 *-b-* |-a-| b error a + + 48 *-a-* a [b2,a2] b + *-b-| + + 49 *-a-* a [a1,b1] b + |-b-* + + 50 *-b-* b error a + *-a-| + + 51 *-b-* b error a + |-a-* + + 52 *-a-* a error a + *-b-* + + \end{verbatim} + + Attention: The difference operation has to be reconsidered in future + concerning a discrete interpretation of the intervals. + + The closure operation defines an interval which is the smallest + interval containing the two operands. + The method {\tt intersects_with()} returns 0 in the error cases of the + intersection operation and 1 otherwise. + +*/ + +class r_Sinterval +{ + public: + /// default constructor creates an interval with open bounds + r_Sinterval(); + + /// constructor taking string representation (e.g. *:200 ) + r_Sinterval( char* ) throw(r_Eno_interval); + + /// constructor for an interval with fixed bounds + r_Sinterval( r_Range low, r_Range high ) throw( r_Eno_interval ); + + //@Man: Constructors for intervals with at least one open bound. + //@{ + /// + r_Sinterval( char, r_Range high ); + /// + r_Sinterval( r_Range low, char ); + /// + r_Sinterval( char, char ); + /// + //@} + + /// equal operator + bool operator==( const r_Sinterval& ) const; + + /** + Two intervals are equal if they have the same lower and upper bound. + */ + + /// non equal operator - negation of equal operator + bool operator!=( const r_Sinterval& ) const; + + //@Man: Read/Write methods: + //@{ + /// + inline r_Range low () const; + /// + inline r_Range high() const; + /// + inline bool is_low_fixed() const; + /// + inline bool is_high_fixed() const; + + /// + void set_low ( r_Range low ) throw( r_Eno_interval ); + /// + void set_high ( r_Range high ) throw( r_Eno_interval ); + /// + inline void set_low ( char ); + /// + inline void set_high( char ); + + /// get the size of one dimensional interval as range. + r_Range get_extent() const throw(r_Error); + /*@Doc: + Returns a range with high() - low() + 1 of this interval. + */ + + /// + void set_interval( r_Range low, r_Range high ) throw( r_Eno_interval ); + /// + void set_interval( char, r_Range high ); + /// + void set_interval( r_Range low, char ); + /// + void set_interval( char, char ); + /// + //@} + + /// determines if the self interval intersects with the delivered one + bool intersects_with( const r_Sinterval& ) const; + + //@Man: Methods/Operators for the union operation: + //@{ + /// + r_Sinterval& union_of ( const r_Sinterval&, const r_Sinterval& ) + throw( r_Eno_interval ); + /// + r_Sinterval& union_with ( const r_Sinterval& ) + throw( r_Eno_interval ); + /// + r_Sinterval& operator+= ( const r_Sinterval& ) + throw( r_Eno_interval ); + /// + r_Sinterval create_union ( const r_Sinterval& ) const + throw( r_Eno_interval ); + /// + r_Sinterval operator+ ( const r_Sinterval& ) const + throw( r_Eno_interval ); + /// + //@} + + //@Man: Methods/Operators for the difference operation: + //@{ + /// + r_Sinterval& difference_of ( const r_Sinterval&, const r_Sinterval& ) + throw( r_Eno_interval ); + /// + r_Sinterval& difference_with ( const r_Sinterval& ) + throw( r_Eno_interval ); + /// + r_Sinterval& operator-= ( const r_Sinterval& ) + throw( r_Eno_interval ); + /// + r_Sinterval create_difference ( const r_Sinterval& ) const + throw( r_Eno_interval ); + /// + r_Sinterval operator- ( const r_Sinterval& ) const + throw( r_Eno_interval ); + /// + //@} + + //@Man: Methods/Operators for the intersection operation: + //@{ + /// + r_Sinterval& intersection_of ( const r_Sinterval&, const r_Sinterval& ) + throw( r_Eno_interval ); + /// + r_Sinterval& intersection_with ( const r_Sinterval& ) + throw( r_Eno_interval ); + /// + r_Sinterval& operator*= ( const r_Sinterval&) + throw( r_Eno_interval); + /// + r_Sinterval create_intersection ( const r_Sinterval& ) const + throw( r_Eno_interval ); + /// + r_Sinterval operator* ( const r_Sinterval& ) const + throw( r_Eno_interval ); + /// + //@} + + //@Man: Methods/Operators for the closure operation: + //@{ + /// + r_Sinterval& closure_of ( const r_Sinterval&, const r_Sinterval& ) + throw( r_Eno_interval ); + /// + r_Sinterval& closure_with ( const r_Sinterval& ) + throw( r_Eno_interval ); + /// + r_Sinterval create_closure ( const r_Sinterval& ) const + throw( r_Eno_interval ); + /// + //@} + + /// writes the state of the object to the specified stream + void print_status( std::ostream& s = std::cout ) const; + + /// gives back the string representation + char* get_string_representation() const; + /** + The string representation delivered by this method is allocated using {\tt malloc()} and + has to be free unsing {\tt free()} in the end. It can be used to construct a {\tt r_Sinterval} + again with a special constructor provided. The string representation is build using + {\tt print_status()}. + */ + + //@Man: Methods for internal use only: + //@{ + /// calculate the size of the storage space occupied + r_Bytes get_storage_size( ) const; + /// + //@} + +private: + + //@Man: Calculation methods for the operations: + //@{ + /// + r_Sinterval calc_union ( const r_Sinterval& a, const r_Sinterval& b ) const + throw( r_Eno_interval ); + /// + r_Sinterval calc_difference ( const r_Sinterval& a, const r_Sinterval& b ) const + throw( r_Eno_interval ); + /// + r_Sinterval calc_intersection( const r_Sinterval& a, const r_Sinterval& b ) const + throw( r_Eno_interval ); + /// + r_Sinterval calc_closure ( const r_Sinterval& a, const r_Sinterval& b ) const + throw( r_Eno_interval ); + /// + //@} + + /// compute the class of the two operands + int classify( const r_Sinterval& a, const r_Sinterval& b ) const; + + //@Man: Attributes storing the bounds: + //@{ + /// + r_Range lower_bound; + /// + r_Range upper_bound; + /// + //@} + + //@Man: Attributes specifying wheter the lower/upper bound is fixed or not: + //@{ + /// + bool low_fixed; + /// + bool high_fixed; + /// + //@} +}; + + + + +//@ManMemo: Module: {\bf raslib} +/** + Output stream operator for objects of type {\tt const r_Sinterval}. +*/ +extern std::ostream& operator<<( std::ostream& s, const r_Sinterval& d ); + +#include "raslib/sinterval.icc" + +#endif diff --git a/raslib/sinterval.icc b/raslib/sinterval.icc new file mode 100644 index 0000000..5d3311e --- /dev/null +++ b/raslib/sinterval.icc @@ -0,0 +1,76 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INLINE SOURCE: sinterval.icc + * + * MODULE: raslib + * CLASS: r_Sinterval + * + * COMMENTS: + * +*/ + +inline r_Range +r_Sinterval::low() const +{ + return lower_bound; +}; + + +inline r_Range +r_Sinterval::high() const +{ + return upper_bound; +}; + + +inline bool +r_Sinterval::is_low_fixed() const +{ + return low_fixed; +}; + + +inline bool +r_Sinterval::is_high_fixed() const +{ + return high_fixed; +}; + + +inline void +r_Sinterval::set_low( char ) +{ + lower_bound = 0; + low_fixed = false; +}; + + +inline void +r_Sinterval::set_high( char ) +{ + upper_bound = 0; + high_fixed = false; +}; + + diff --git a/raslib/sintervaltype.cc b/raslib/sintervaltype.cc new file mode 100644 index 0000000..241d606 --- /dev/null +++ b/raslib/sintervaltype.cc @@ -0,0 +1,80 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +static const char rcsid[] = "@(#)raslib, r_Sinterval_Type: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/sintervaltype.cc,v 1.6 2003/12/27 23:01:21 rasdev Exp $"; + +#include "raslib/sintervaltype.hh" + +r_Sinterval_Type::r_Sinterval_Type() + : r_Type() +{ +} + +r_Sinterval_Type::r_Sinterval_Type( const r_Sinterval_Type& oldObj ) + : r_Type(oldObj) +{ +} + +r_Type* +r_Sinterval_Type::clone() const +{ + return new r_Sinterval_Type( *this ); +} + +r_Type::r_Type_Id +r_Sinterval_Type::type_id() const +{ + return SINTERVALTYPE; +} + +bool +r_Sinterval_Type::isSintervalType() const + { + return true; + } + +void +r_Sinterval_Type::convertToLittleEndian(char* cells, r_Bytes noCells) const +{ +} + +void +r_Sinterval_Type::convertToBigEndian(char* cells, r_Bytes noCells) const +{ +} + +void +r_Sinterval_Type::print_status( std::ostream& s ) const +{ + s << "interval"; +} + +r_Sinterval_Type::~r_Sinterval_Type() +{ +} + +std::ostream &operator<<( std::ostream &str, const r_Sinterval_Type &type ) +{ + type.print_status(str); + return str; +} diff --git a/raslib/sintervaltype.hh b/raslib/sintervaltype.hh new file mode 100644 index 0000000..1a102cd --- /dev/null +++ b/raslib/sintervaltype.hh @@ -0,0 +1,81 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: sintervaltype.hh + * + * MODULE: raslib + * CLASS: r_Sinterval_Type + * + * COMMENTS: + * +*/ + +#ifndef _D_SINTERVAL_TYPE_ +#define _D_SINTERVAL_TYPE_ + +#include "raslib/type.hh" + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + This class represents the sinterval type in the ODMG conformant + representation of the RasDaMan type system. +*/ + +class r_Sinterval_Type : public r_Type +{ +public: + /// default constructor + r_Sinterval_Type(); + + /// copy constructor + r_Sinterval_Type( const r_Sinterval_Type& oldObj ); + + /// clone operation + virtual r_Type* clone() const; + + /// retrieve id of the type. + virtual r_Type::r_Type_Id type_id() const; + + /// converts array of cells from NT byte order to Unix byte order. + virtual void convertToLittleEndian(char* cells, r_Area noCells) const; + + /// converts array of cells from Unix byte order to NT byte order. + virtual void convertToBigEndian(char* cells, r_Area noCells) const; + + /// writes state of object to specified stream + virtual void print_status( std::ostream& s = std::cout ) const; + + virtual bool isSintervalType() const; + + /// destructor + ~r_Sinterval_Type(); +}; + +//@Doc: write the status of a sinterval type to a stream +extern std::ostream &operator<<( std::ostream &str, const r_Sinterval_Type &type ); + +#endif + + + diff --git a/raslib/storageman.cc b/raslib/storageman.cc new file mode 100644 index 0000000..8527bde --- /dev/null +++ b/raslib/storageman.cc @@ -0,0 +1,133 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: storageman.cc + * + * MODULE: raslib + * + * CLASSES: r_Storage_Man, r_Storage_Man_C, r_Storage_Man_CPP + * + * COMMENTS: + * + * Transparent handling of malloc/free vs. new/delete + * +*/ + +#include "mymalloc/mymalloc.h" + +#include "raslib/storageman.hh" + + +// auxiliary static functions +static void *alloc_c_style( size_t size ) +{ + return mymalloc( size ); +} + +static void free_c_style( void *data ) +{ + free(data); +} + +static void *alloc_cpp_style( size_t size ) +{ + return new char[size]; +} + +static void free_cpp_style( void *data ) +{ + delete [] data; +} + + + +r_Storage_Man::r_Storage_Man( void ) +{ + myalloc = alloc_c_style; + myfree = free_c_style; +} + +r_Storage_Man::r_Storage_Man( storage_man_alloc a, storage_man_free f ) +{ + myalloc = a; + myfree = f; +} + +r_Storage_Man::r_Storage_Man( const r_Storage_Man &src ) +{ + myalloc = src.myalloc; + myfree = src.myfree; +} + +r_Storage_Man::~r_Storage_Man( void ) +{ +} + +void r_Storage_Man::set_storage_functions( storage_man_alloc a, storage_man_free f ) +{ + myalloc = a; + myfree = f; +} + +r_Storage_Man &r_Storage_Man::operator=( const r_Storage_Man &src ) +{ + myalloc = src.myalloc; + myfree = src.myfree; + return *this; +} + +void *r_Storage_Man::storage_alloc( size_t size ) const throw(r_Error) +{ + void *result; + + if ((result = myalloc(size)) == NULL) + { + r_Error err(r_Error::r_Error_General); + throw(err); + } + return result; +} + +void r_Storage_Man::storage_free( void *data ) const +{ + myfree(data); +} + + + +r_Storage_Man_C::r_Storage_Man_C( void ) : r_Storage_Man( alloc_c_style, free_c_style ) +{ +} + +r_Storage_Man_C::~r_Storage_Man_C( void ) +{ +} + + +r_Storage_Man_CPP::r_Storage_Man_CPP( void ) : r_Storage_Man( alloc_cpp_style, free_cpp_style ) +{ +} + +r_Storage_Man_CPP::~r_Storage_Man_CPP( void ) +{ +} diff --git a/raslib/storageman.hh b/raslib/storageman.hh new file mode 100644 index 0000000..a985f8c --- /dev/null +++ b/raslib/storageman.hh @@ -0,0 +1,116 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: storageman.hh + * + * MODULE: raslib + * + * CLASSES: r_Storage_Man, r_Storage_Man_C, r_Storage_Man_CPP + * + * COMMENTS: + * + * Transparent handling of malloc/free vs. new/delete + * +*/ + +#ifndef _R_STORAGE_MAN_ +#define _R_STORAGE_MAN_ + + +// for size_t +#include <stdlib.h> + +#include "raslib/error.hh" + + + +//@ManMemo: Module {\bf raslib} + +/*@Doc: + r_Storage_Man provides an interface to a pair of heap management + functions for allocating and freeing blocks. I want to be able + to use constructs like sman1 = sman2, therefore I can't use + virtual functions to implement this. +*/ + +class r_Storage_Man +{ + public: + + /// types of storage management functions + typedef void *(*storage_man_alloc)( size_t ); + typedef void (*storage_man_free)( void *data ); + + /// default constructor, switches to c-style allocation + r_Storage_Man( void ); + /// constructor setting the storage functions + r_Storage_Man( storage_man_alloc a, storage_man_free f ); + /// copy constructor + r_Storage_Man( const r_Storage_Man &src ); + /// destructor + ~r_Storage_Man( void ); + /// setting the storage functions + void set_storage_functions( storage_man_alloc a, storage_man_free f ); + /// assignment + r_Storage_Man &operator=( const r_Storage_Man &src ); + /// allocation + void *storage_alloc( size_t size ) const throw(r_Error); + /// deallocation + void storage_free( void *data ) const; + + + protected: + /// the storage functions + storage_man_alloc myalloc; + storage_man_free myfree; +}; + + +/*@Doc: + r_Storage_Man_C implements C-style allocation using malloc/free +*/ + +class r_Storage_Man_C : public r_Storage_Man +{ + public: + /// default constructor + r_Storage_Man_C( void ); + /// default destructor + ~r_Storage_Man_C( void ); +}; + + +/*@Doc: + r_Storage_Man_CPP implements C++-style allocation using new/delete +*/ + +class r_Storage_Man_CPP : public r_Storage_Man +{ + public: + /// default constructor + r_Storage_Man_CPP( void ); + /// destructor + ~r_Storage_Man_CPP( void ); +}; + +#endif diff --git a/raslib/structure.cc b/raslib/structure.cc new file mode 100644 index 0000000..4c81015 --- /dev/null +++ b/raslib/structure.cc @@ -0,0 +1,282 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * SOURCE: structure.cc + * + * MODULE: raslib + * CLASS: r_Structure + * + * COMMENTS: + * +*/ + +#include "raslib/structure.hh" +#include "raslib/primitive.hh" +#include "raslib/structuretype.hh" +#include "raslib/error.hh" +#include "raslib/rminit.hh" +#include "mymalloc/mymalloc.h" + +#ifdef __VISUALC__ +#include <strstrea.h> +#else +#include <strstream> +#endif +#include <string.h> +#include <fstream> +#include <stdlib.h> + + + + +r_Structure::r_Structure( const char* newBuffer, const r_Structure_Type* newType ) + : r_Scalar( newType ), + numElements(0), + elements(NULL), + valueBuffer(NULL) +{ + if( newType ) + { + + numElements = newType->count_elements(); + elements = new r_Scalar*[numElements]; + + valueBuffer = (char*)mymalloc(newType->size()); + + if(newBuffer) + memcpy(valueBuffer, newBuffer, newType->size()); + else + memset(valueBuffer, 0, newType->size()); + + r_Structure_Type::attribute_iterator iter( newType->defines_attribute_begin() ); + + for( int i=0; iter != newType->defines_attribute_end(); iter++, i++ ) + { + if( (*iter).type_of().type_id() == r_Type::STRUCTURETYPE ) + elements[i] = new r_Structure( valueBuffer + (*iter).offset(), (r_Structure_Type*)&((*iter).type_of()) ); + else + elements[i] = new r_Primitive( valueBuffer + (*iter).offset(), (r_Primitive_Type*)&((*iter).type_of()) ); + } + } +} + + + +r_Structure::r_Structure( const r_Structure& obj ) + : r_Scalar( obj ), + numElements(obj.numElements), + elements(NULL), + valueBuffer(NULL) +{ + if( numElements ) + { + elements = new r_Scalar*[numElements]; + + for( unsigned int i=0; i < numElements; i++ ) + elements[i] = obj.elements[i]->clone(); + } + + valueBuffer = (char*) mymalloc(valueType->size()); + + if(obj.valueBuffer) + memcpy(valueBuffer, obj.valueBuffer, valueType->size()); + else + memset(valueBuffer, 0, valueType->size()); +} + + + +r_Structure::~r_Structure() +{ + if( numElements ) + { + for( unsigned int i =0; i < numElements; i++ ) + delete elements[i]; + + delete[] elements; + } + + if(valueBuffer) + free(valueBuffer); +} + + + +r_Scalar* +r_Structure::clone() const +{ + return new r_Structure( *this ); +} + + + +const r_Structure& +r_Structure::operator=( const r_Structure& obj ) +{ + if( this != &obj ) + { + // assign scalar + r_Scalar::operator=( obj ); + + if( numElements ) + { + for( unsigned int i =0; i < numElements; i++ ) + delete elements[i]; + + delete[] elements; + } + + if( obj.numElements ) + { + numElements = obj.numElements; + elements = new r_Scalar*[numElements]; + + for( unsigned int i =0; i < numElements; i++ ) + elements[i] = obj.elements[i]->clone(); + } + + if(valueBuffer) + free(valueBuffer); + + valueBuffer = (char*) mymalloc(valueType->size()); + + if(obj.valueBuffer) + memcpy(valueBuffer, obj.valueBuffer, valueType->size()); + else + memset(valueBuffer, 0, valueType->size()); + + } + + return *this; +} + + + +unsigned int +r_Structure::count_elements() const +{ + return numElements; +} + +const char* +r_Structure::get_buffer() const +{ + memset(valueBuffer, 0, valueType->size()); + + r_Structure_Type::attribute_iterator iter( ((r_Structure_Type*)valueType)->defines_attribute_begin() ); + + for( int i=0; iter != ((r_Structure_Type*)valueType)->defines_attribute_end(); iter++, i++ ) + if( (*iter).type_of().type_id() == r_Type::STRUCTURETYPE ) + memcpy( valueBuffer + (*iter).offset(), ((r_Structure*)elements[i])->get_buffer(), elements[i]->get_type()->size()); + else + memcpy( valueBuffer + (*iter).offset(), ((r_Primitive*)elements[i])->get_buffer(), elements[i]->get_type()->size()); + + return valueBuffer; +} + + +bool +r_Structure::isStructure() const +{ + return true; +} + + + +const r_Scalar& +r_Structure::operator[]( unsigned int index ) const throw( r_Error ) +{ + if( !valueType ) + { + RMInit::logOut << "r_Structure::operator[](" << index << ") const value type is NULL" << endl; + throw r_Error( r_Error::r_Error_TypeInvalid ); + } + + if( index > numElements ) + { + RMInit::logOut << "r_Structure::operator[](" << index << ") const index is out of bounds (" << numElements - 1 << ")" << endl; + throw r_Eindex_violation( 0, numElements, index ); + } + + return *(elements[index]); +} + + + +const r_Scalar& +r_Structure::operator[]( const char* name ) const throw( r_Error ) +{ + if( !valueType ) + { + RMInit::logOut << "r_Structure::operator[](" << name << ") value type is NULL" << endl; + r_Error err( r_Error::r_Error_TypeInvalid ); + throw( err ); + } + + r_Structure_Type* structType = (r_Structure_Type*)valueType; + + r_Structure_Type::attribute_iterator iter( structType->defines_attribute_begin() ); + + int index = 0; + for( ; iter != structType->defines_attribute_end() && strcmp((*iter).name(), name); iter++, index++ ); + + if( iter == structType->defines_attribute_end() ) + { + RMInit::logOut << "r_Structure::operator[](" << name << ") name is not valid" << endl; + r_Error err( r_Error::r_Error_NameInvalid ); + throw( err ); + } + + return *(elements[index]); +} + + +void +r_Structure::print_status( std::ostream& s ) const +{ + if( valueType ) + { + s << "{ " << std::flush; + + for( unsigned int i =0; i < numElements; i++ ) + { + s << *(elements[i]) << std::flush; + + if( i < numElements-1 ) + s << ", " << std::flush; + } + + s << " }" << std::flush; + } + else + s << "<nn>" << std::flush; +} + + + +std::ostream& operator<<( std::ostream& s, const r_Structure& obj ) +{ + obj.print_status( s ); + return s; +} + diff --git a/raslib/structure.hh b/raslib/structure.hh new file mode 100644 index 0000000..a41cdbf --- /dev/null +++ b/raslib/structure.hh @@ -0,0 +1,111 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: structure.hh + * + * MODULE: raslib + * CLASS: r_Structure + * + * COMMENTS: + * + * The class represents a structured value. + * +*/ + +#ifndef _D_STRUCTURE_ +#define _D_STRUCTURE_ + +#include <iostream> + +class r_Error; + +#include "raslib/scalar.hh" + +class r_Structure_Type; + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + + Class \Ref{r_Structure} represents a structured value. + +*/ + +class r_Structure : public r_Scalar +{ + public: + /// constructs a structured type value + r_Structure( const char* newBuffer, const r_Structure_Type* newType ); + + /// copy constructor + r_Structure( const r_Structure& obj ); + + /// destructor + virtual ~r_Structure(); + + /// clone operator + virtual r_Scalar* clone() const; + + /// operator for assigning a structure + virtual const r_Structure& operator= ( const r_Structure& ); + + /// debug output + virtual void print_status(std::ostream& s) const; + + /// returns true to indicate that this is a structured value + virtual bool isStructure() const; + + /// get number of elements + unsigned int count_elements() const; + + /// get buffer + const char* get_buffer() const; + + /// access an element by name + /// throws TypeInvalid and r_Eindex_violation + const r_Scalar& operator[]( const char* name ) const throw( r_Error ); + + /// access an element by number + /// throws TypeInvalid and NameInvalid + const r_Scalar& operator[]( unsigned int ) const throw( r_Error ); + + private: + /// number of elements + unsigned int numElements; + + /// array of pointers to elements + r_Scalar** elements; + + /// char representation + char* valueBuffer; +}; + + + +//@ManMemo: Module: {\bf raslib} +/** + Output stream operator for objects of type {\tt const} \Ref{r_Structure}. +*/ +extern std::ostream& operator<<( std::ostream& s, const r_Structure& oid ); +#endif + diff --git a/raslib/structuretype.cc b/raslib/structuretype.cc new file mode 100644 index 0000000..ddfd9fb --- /dev/null +++ b/raslib/structuretype.cc @@ -0,0 +1,276 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +static const char rcsid[] = "@(#)raslib, r_Structure_Type: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/structuretype.cc,v 1.23 2003/12/27 23:01:21 rasdev Exp $"; + +#include <malloc.h> +#include <string.h> + +#include "raslib/structuretype.hh" +#include "raslib/attribute.hh" +#include "raslib/rminit.hh" +#include "raslib/error.hh" + +r_Structure_Type::r_Structure_Type() + : r_Base_Type(), + myAttributes(NULL), + numAttrs(0) +{ +} + +r_Structure_Type::r_Structure_Type( char* newTypeName, + unsigned int newNumAttrs, + r_Attribute* newAttrs, int offset ) + : r_Base_Type(newTypeName, 0), + numAttrs(newNumAttrs), + myAttributes(new r_Attribute[newNumAttrs]) +{ + for(unsigned int i = 0; i < numAttrs; i++) + { + myAttributes[i] = newAttrs[i]; + myAttributes[i].set_offset( typeSize ); + myAttributes[i].set_global_offset( typeSize + offset ); + typeSize += myAttributes[i].type_of().size(); + } +} + +r_Structure_Type::r_Structure_Type( const r_Structure_Type& oldObj ) + : r_Base_Type(oldObj), myAttributes(NULL), numAttrs(oldObj.numAttrs) +{ + + if( oldObj.myAttributes ) + { + myAttributes = new r_Attribute[numAttrs]; + for( unsigned int i = 0; i < numAttrs; i++) + myAttributes[i] = oldObj.myAttributes[i]; + } +} + +const r_Structure_Type& +r_Structure_Type::operator=( const r_Structure_Type& oldObj ) +{ + // Gracefully handle self assignment + if (this == &oldObj) return *this; + + r_Base_Type::operator=( oldObj ); + numAttrs = oldObj.numAttrs; + if( myAttributes ) + { + delete[] myAttributes; + myAttributes=NULL; + } + + if( oldObj.myAttributes ) + { + myAttributes = new r_Attribute[numAttrs]; + for(unsigned int i = 0; i < numAttrs; i++) + myAttributes[i] = oldObj.myAttributes[i]; + } + + return *this; +} + +r_Structure_Type::~r_Structure_Type() +{ + if( myAttributes ) + delete[] myAttributes; +} + +r_Type* +r_Structure_Type::clone() const +{ + return new r_Structure_Type( *this ); +} + + +r_Type::r_Type_Id +r_Structure_Type::type_id() const +{ + return STRUCTURETYPE; +} + +bool +r_Structure_Type::isStructType() const +{ + return true; +} + +bool +r_Structure_Type::compatibleWith(const r_Structure_Type* myType) const +{ + if(myType == NULL) + return false; + if( count_elements() != myType->count_elements()) + return false; + + r_Structure_Type::attribute_iterator myIter(defines_attribute_begin()); + r_Structure_Type::attribute_iterator myTypeIter(myType->defines_attribute_begin()); + r_Structure_Type::attribute_iterator myIterEnd(defines_attribute_end()); + // FIXME not used in curr implementation + // r_Structure_Type::attribute_iterator myTypeIterEnd(myType->defines_attribute_end()); + while(myIter != myIterEnd) { + if((*myIter).type_of().type_id() != (*myTypeIter).type_of().type_id()) + return false; + myIter++; + myTypeIter++; + } + + return true; +} + +r_Structure_Type::attribute_iterator +r_Structure_Type::defines_attribute_begin() const +{ + return attribute_iterator(myAttributes + numAttrs, myAttributes); +} + +r_Structure_Type::attribute_iterator +r_Structure_Type::defines_attribute_end() const +{ + return attribute_iterator(myAttributes + numAttrs - 1, myAttributes, + myAttributes + numAttrs); +} + +r_Attribute +r_Structure_Type::resolve_attribute(const char* name) const throw( r_Error ) +{ + r_Structure_Type::attribute_iterator iter(defines_attribute_begin()); + + while( iter != defines_attribute_end() && strcmp((*iter).name(), name) != 0 ) + iter++; + + if( iter == defines_attribute_end() ) + { + RMInit::logOut << "r_Structure_Type::resolve_attribute(" << name << ") not a valid atribute name" << endl; + r_Error err(r_Error::r_Error_NameInvalid); + throw err; + } + + return (*iter); +} + +r_Attribute +r_Structure_Type::resolve_attribute(unsigned int number) const throw( r_Error ) +{ + r_Structure_Type::attribute_iterator iter(defines_attribute_begin()); + unsigned int i = 0; + while( iter != defines_attribute_end() && i < number ) + { + i++; + iter++; + } + + if( iter == defines_attribute_end() || i < number ) + { + RMInit::logOut << "r_Structure_Type::resolve_attribute(" << number << ") index out of bounds (" << i << ")" << endl; + throw r_Eindex_violation( 0, numAttrs-1, number ); + } + + return (*iter); +} + +r_Attribute +r_Structure_Type::operator[]( unsigned int number ) const throw( r_Error ) +{ + return resolve_attribute( number ); +} + +unsigned int +r_Structure_Type::count_elements() const +{ + return numAttrs; +} + +void +r_Structure_Type::convertToLittleEndian(char* cells, r_Area noCells) const +{ + r_Area i = 0; + unsigned int j = 0; + + for(i=0; i<noCells; i++) { + for(j=0; j<numAttrs; j++) { + myAttributes[j].type_of().convertToLittleEndian( + &cells[i*typeSize + myAttributes[j].offset()], 1); + } + } +} + +void +r_Structure_Type::convertToBigEndian(char* cells, r_Area noCells) const +{ + r_Area i = 0; + unsigned int j = 0; + + for(i=0; i<noCells; i++) { + for(j=0; j<numAttrs; j++) { + myAttributes[j].type_of().convertToBigEndian( + &cells[i*typeSize + myAttributes[j].offset()], 1); + } + } +} + +void +r_Structure_Type::print_status( std::ostream& s ) const +{ + r_Structure_Type::attribute_iterator iter(defines_attribute_begin()); + + s << "struct{ "; + + while(iter != defines_attribute_end()) + { + (*iter).print_status( s ); + + iter++; + + if( iter != defines_attribute_end() ) + s << ", "; + } + + s << " }"; +} + +void +r_Structure_Type::print_value( const char* storage, std::ostream& s ) const +{ + s << "{ "; + + r_Structure_Type::attribute_iterator iter( defines_attribute_begin() ); + + while( iter != defines_attribute_end() ) + { + (*iter).type_of().print_value( storage + (*iter).offset(), s ); + + iter++; + + if( iter != defines_attribute_end() ) + s << ", "; + } + s << "} "; +} + + +std::ostream &operator<<( std::ostream &str, const r_Structure_Type &type ) +{ + type.print_status(str); + return str; +}
\ No newline at end of file diff --git a/raslib/structuretype.hh b/raslib/structuretype.hh new file mode 100644 index 0000000..fae53b4 --- /dev/null +++ b/raslib/structuretype.hh @@ -0,0 +1,118 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: structuretype.hh + * + * MODULE: raslib + * CLASS: r_Structure_Type + * + * COMMENTS: + * +*/ + +#ifndef _D_STRUCTURE_TYPE_ +#define _D_STRUCTURE_TYPE_ + +#if (defined(__VISUALC__) && !defined(__EXECUTABLE__)) + #define __EXECUTABLE__ + #include "raslib/itertype.hh" + #undef __EXECUTABLE__ +#else + #include "raslib/itertype.hh" +#endif + +class r_Error; +#include "raslib/basetype.hh" +#include "raslib/attribute.hh" + + +//@ManMemo: Module: {\bf raslib} + +/*@Doc: + This class represents all user defined structured types in the + ODMG conformant representation of the RasDaMan type system. +*/ + +class r_Structure_Type : public r_Base_Type +{ +public: + /// typedef for iterator iterating through all attributes; + typedef r_IterType<r_Attribute> attribute_iterator; + /// default constructor. + r_Structure_Type(); + /// constructor getting name of type and type id. + r_Structure_Type( char* newTypeName, unsigned int newNumAttrs, r_Attribute* newAttrs, int offset = 0 ); + /// copy constructor + r_Structure_Type( const r_Structure_Type& oldObj ); + /// assignment operator. + const r_Structure_Type& operator=( const r_Structure_Type& oldObj ); + /// destructor. + virtual ~r_Structure_Type(); + + /// clone operation + virtual r_Type* clone() const; + + /// retrieve id of the type. + virtual r_Type::r_Type_Id type_id() const; + + /// check, if type is primitive or structured. + virtual bool isStructType() const; + + /// check, if this type is compatible with myType (e.g. check the structure ignoring then names of atributtes) + virtual bool compatibleWith(const r_Structure_Type* myType) const; + + /// returns attribute iterator at begin position. + attribute_iterator defines_attribute_begin() const; + /// returns attribute iterator at end position (behind last attribute). + attribute_iterator defines_attribute_end() const; + /// return attribute specified by name. + r_Attribute resolve_attribute(const char* name) const throw( r_Error ); + /// return attribute specified by number starting with zero. + r_Attribute resolve_attribute(unsigned int number) const throw( r_Error ); + /// subscript operator to access attributes by index + r_Attribute operator[]( unsigned int number ) const throw( r_Error ); + + /// get number of attributes + unsigned int count_elements() const; + + /// converts array of cells from NT byte order to Unix byte order. + virtual void convertToLittleEndian(char* cells, r_Area noCells) const; + + /// converts array of cells from Unix byte order to NT byte order. + virtual void convertToBigEndian(char* cells, r_Area noCells) const; + + /// writes state of object to specified stream + virtual void print_status( std::ostream& s = std::cout ) const; + + /// prints values of a structured type + virtual void print_value( const char* storage, std::ostream& s = std::cout ) const; + +protected: + unsigned int numAttrs; + r_Attribute* myAttributes; +}; + +//@Doc: write the status of a structure type to a stream +extern std::ostream &operator<<( std::ostream &str, const r_Structure_Type &type ); + +#endif diff --git a/raslib/template_inst.hh b/raslib/template_inst.hh new file mode 100644 index 0000000..63874c6 --- /dev/null +++ b/raslib/template_inst.hh @@ -0,0 +1,78 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +// This version was created based on rview. Let's see if the other programs compile +// also. + +#ifndef _TEMPLATE_INST_RASLIB_ +#define _TEMPLATE_INST_RASLIB_ + +#include <vector> + +#include <raslib/attribute.hh> +#include <raslib/itertype.hh> +#include <raslib/dlist.hh> +#include <raslib/minterval.hh> + +#include <rasodmg/tiling.hh> +#include <rasodmg/stattiling.hh> +#include <rasodmg/iterator.hh> +#include <rasodmg/ref.hh> +#include <rasodmg/object.hh> +#include <rasodmg/set.hh> +#include <rasodmg/collection.hh> +#include <rasodmg/gmarray.hh> +#include <rasodmg/transaction.hh> +#include <rasodmg/marray.hh> +#include <rasodmg/dirdecompose.hh> + +template class r_Ref<r_Object>; +template class r_Ref<r_Minterval>; +template class r_Collection<r_Transaction::GenRefElement *>; +template class r_Set<r_Transaction::GenRefElement *>; +template class r_Iterator<r_GMarray *>; +template class r_Iterator<r_Ref<r_GMarray > >; +template class r_Collection<r_Ref<r_GMarray> >; +template class r_Collection<r_GMarray *>; +template class r_Set<r_GMarray *>; +template class r_Iterator<r_Ref<r_Object> >; +template class r_IterType<r_Attribute>; +template class r_Collection<r_Ref<r_Object> >; +template class r_Set<r_Ref<r_Object> >; +template class r_Iterator<r_Ref_Any>; +template class r_Ref<r_GMarray>; +template class r_Collection<r_Ref_Any>; +template class std::vector<r_Minterval>; +template class r_Iterator<r_Transaction::GenRefElement *>; +template class r_Set<r_Ref<r_GMarray> >; +template class r_Ref<r_Set<r_Ref<r_GMarray> > >; +template class r_Set<r_Ref_Any>; +template class r_Marray<r_ULong>; +template class r_Marray<r_Char>; + +template std::ostream& operator << (std::ostream& os, const std::vector<r_Minterval>& list); +template std::ostream& operator << (std::ostream& os, const std::vector<r_Dir_Decompose>& list); +template std::ostream& operator << (std::ostream& os, const std::vector<r_Access>& list); +template std::ostream& operator << (std::ostream& os, const std::vector<double>& list); + +#endif diff --git a/raslib/test/Makefile b/raslib/test/Makefile new file mode 100644 index 0000000..379b344 --- /dev/null +++ b/raslib/test/Makefile @@ -0,0 +1,192 @@ +# -*-Makefile-*- +# +# This file is part of rasdaman community. +# +# Rasdaman community is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Rasdaman community 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +# +# Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +# rasdaman GmbH. +# +# For more information please see <http://www.rasdaman.org> +# or contact Peter Baumann via <baumann@rasdaman.com>. # Top Level makefile. This points to the various modules that have to be build +# and/or deployed +# +# MAKEFILE FOR: +# test programs of module raslib +# +# +# COMMENTS: +# +################################################################## +# +# This is just an example Makefile for a test program. +# The dependency of the test program on the lib of the +# corresponding module is in the Makefile of the module. +# + +######################### Definitions ############################ + +# standard include with general options +include $(RMANBASE)/Makefile.inc + +# uses our own mem management routine: +MYMALLOC_H := ../../mymalloc/mymalloc.hh +MYMALLOC_O := ../../mymalloc/mymalloc_cln.o + +# use client specific flags +CXXFLAGS := $(CLIENTCXXFLAGS) $(I_SYM)$(MYMALLOC_H) +LDFLAGS := $(CLIENTLDFLAGS) $(L_SYM)$(MYMALLOC_O) + +# raslib has its own template directory because of the name clashes with O2 + +ifneq ($(OSTYPE),linux-gnu) + CXXFLAGS := -ptr$(RMANBASE)/rasodmg/ptrepository $(CXXFLAGS) + LDFLAGS := -ptr$(RMANBASE)/rasodmg/ptrepository $(LDFLAGS) +endif + +# all test programs +ALLTESTS = test_error + +# test_sinterval test_point test_minterval test_rmdebug \ +# test_metaobject test_oid test_timer test_miter test_miterf \ +# test_params + +########################### Targets ############################## + +# test target for class r_Minterval +.PHONY : minterval +minterval: test_module test_minterval + +# test target for class r_Miter +.PHONY : miterd +miterd: test_module test_miterd + +# test target for class r_Miter +.PHONY : miter +miter: test_module test_miter + +# test target for class r_MiterFloat +.PHONY : miterf +miterf: test_module test_miterf + +# test target for class r_Sinterval +.PHONY : sinterval +sinterval: test_module test_sinterval + +# test target for class r_Point +.PHONY : point +point: test_module test_point + +# test target for class r_Error and its subclasses +.PHONY : error +error: test_module test_error + +# test target for class RMDebug +.PHONY : rmdebug +rmdebug: test_module test_rmdebug + +# test target for class r_Meta_Object and its subclasses +.PHONY : metaobject +metaobject: test_module test_metaobject + +# test target for class r_OId +.PHONY : oid +oid: test_module test_oid + +# test target for RMTimer +.PHONY : timer +timer: test_module test_timer + +# test target for lincomstreams +.PHONY : params +params: test_module test_params + +.PHONY : test_module +test_module: + cd $(RMANBASE)/raslib; $(MAKE) + +test_minterval: test_minterval.o $(RASLIB) + $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ + +test_miterd: test_miterd.o $(RASLIB) + $(PURIFY) $(CXX) $(LDFLAGS) -lm -o $@ $^ + +test_miter: test_miter.o $(RASLIB) + $(PURIFY) $(CXX) $(LDFLAGS) -lm -o $@ $^ + +test_miterf: test_miterf.o $(RASLIB) + $(PURIFY) $(CXX) $(LDFLAGS) -lm -o $@ $^ + +test_sinterval: test_sinterval.o $(RASLIB) + $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ + +test_point: test_point.o $(RASLIB) + $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ + +test_error: test_error.o $(RASLIB) + $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ + +test_rmdebug: test_rmdebug.o $(RASLIB) + $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ + +test_metaobject: test_metaobject.o $(RASLIB) + $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ + +test_oid: test_oid.o $(RASLIB) + $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ + +test_timer: test_timer.o $(RASLIB) + $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ + +test_params: test_params.o $(RASLIB) $(CLIENTCOMM) + $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ + +.PHONY : clean +clean: + -rm $(ALLTESTS) + -rm *.o + +# deletes all non modified, but checked out files +.PHONY : rcsclean +rcsclean: + -rcsclean + +# perform all tests as part of general systemtest +.PHONY: systemtest +systemtest: $(ALLTESTS) + cp $(RMANBASE)/bin/errtxts . # needed by test_error + for PROG in $^; \ + do \ + $$PROG; \ + done + +######################## Dependencies ############################ + +test_minterval.o: test_minterval.cc $(RMANBASE)/raslib/minterval.hh + +test_miter.o: test_miter.cc $(RMANBASE)/raslib/miter.hh + +test_miterf.o: test_miterf.cc $(RMANBASE)/raslib/miterf.hh + +test_sinterval.o: test_sinterval.cc $(RMANBASE)/raslib/sinterval.hh + +test_point.o: test_point.cc $(RMANBASE)/raslib/point.hh + +test_error.o: test_error.cc $(RMANBASE)/raslib/error.hh + +test_oid.o: test_oid.cc $(RMANBASE)/raslib/oid.hh + +test_timer.o: test_timer.cc $(RMANBASE)/raslib/ + +test_params.o: test_params.cc $(RMANBASE)/raslib/parseparams.hh diff --git a/raslib/test/errtxts b/raslib/test/errtxts new file mode 100644 index 0000000..0004f30 --- /dev/null +++ b/raslib/test/errtxts @@ -0,0 +1,244 @@ +190 +# Increment the number above every time you add a new exception +# +# +# This file contains types and textual descriptions of RasDaMan errors. +# The ascending error numbers are used as index to the descriptions. Each +# line follows the following syntax: +# +# number^type^description. +# +# The character '^' is used as delimiter and with '#' a comment line is +# started. Empty lines are not allowed. +# +# +# +# +66^E^Exception: Memory allocation failed. +100^E^Exception: Internal error: DL parse error. +200^E^Exception: The result is no point. +201^E^Exception: The result is no interval. +202^E^Exception: Index violation ( index range [$low,$high], index $index ). +203^E^Exception: Dimension mismatch between $dim1 and $dim2. +204^E^Exception: Stream initialization overflow. +205^E^Exception: Result is no cell. +206^E^Serialisable exception r_Ebase_dbms: error in base DBMS. +207^E^Internal client exception in class $class, method $method: $code. +208^E^Exception: Access type $aType does not fit base type $bType. +209^E^Exception: RasType $type is unknown. +210^E^Exception: Base type $type is not supported yet. +211^E^Exception: Database is not open. +212^E^Exception: RPC layer connection to RasDaMan failed. +213^E^Exception: Wrong URL format (should be http://address:port) +214^E^Exception: Illegal java long value $val for server base type ULong. +215^E^Exception: Illegal java integer value $val for server base type UShort. +216^E^Exception: System collection is not writable. +217^E^Exception: System collection has no OID. +218^E^Exception: Conversion format is not supported. +219^E^Exception: The specified tile size is smaller than the length of the base type of the mdd object. +220^E^Exception: The tiling strategy in the storage layout is not compatible with the marray. +221^E^Exception: The domain passed as an argument was not initialised correctly (dimension is 0). +222^E^Exception: The type name or type structure does not represent a marray type. +223^E^Exception: The rc index requires a marray type that has a specified domain (with fixed borders in all dimensions). +224^E^Exception: The tile configuration is incompatible to the marray domain. +229^E^Exception: The parameterized query has invalid parameter format. +230^E^Exception: The r_Object was already assigned a type. +231^E^Exception: The Marray has no base type. +232^E^Exception: The interval has at least one open bound. +233^E^Exception: The intervals don't have the same dimension. +234^E^Exception: The string passed to the tiling object was not correct. +235^E^Exception: Connection to server already closed. +236^E^Exception: Error in compression engine +237^E^Exception: Client communication failure +# +300^E^Parsing error $errorNo in line $lineNo, column $columnNo: Unexpected name $token. +301^E^Parsing error $errorNo in line $lineNo, column $columnNo, token $token: All cell values of an MDD must be of the same type. +302^E^Parsing error $errorNo in line $lineNo, column $columnNo, token $token: Number of cells specified does not match the number of cells of the given spatial domain. +303^E^Parsing error $errorNo in line $lineNo, column $columnNo, token $token: OId is not valid. +308^E^Parsing error: Unexpected end of query. +309^E^Parsing error: Unknown error. +310^E^Lexical analysing error $errorNo in line $lineNo, column $columnNo: Unexpected characters $token. +311^E^Parsing error $errorNo in line $lineNo, column $columnNo, token $token: Complex constructor must have both arguments of the same type (i.e. float or double). +312^E^Parsing error $errorNo in line $lineNo, column $columnNo, token $token: Variable already defined. +313^E^Parsing error $errorNo in line $lineNo, column $columnNo, token $token: Only constant interval bounds allowed. +# +330^E^Preprocessing error $errorNo in line $lineNo, column $columnNo: Unexpected name $token: +331^E^Preprocessing error $errorNo in line $lineNo, column $columnNo, token $token: attempt to redefine function. +332^E^Preprocessing error $errorNo in line $lineNo, column $columnNo, token $token: number of actual arguments for the called function differs from the number of formal arguments. +333^E^Preprocessing error $errorNo in line $lineNo, column $columnNo, token $token: the called function name is ambiguous, try the full qualified name. +# +349^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Operand out of range. +350^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: General. +351^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Spatial domains of the binary induce operands are incompatible. +352^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Operand types are incompatible. +353^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Operand of quantifier must be multidimensional. +354^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Operand of quantifier must be of type r_Marray<d_Boolean>. +355^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Collection name is unknown. +356^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Specified domain does not intersect with spatial domain of MDD. +357^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Variable is unknown. +358^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Projection operand is not of type r_Marray<T>. +359^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Result of the where clause must be of type boolean. +360^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Type of operand is not supported. +361^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Multiple query targets are not supported. +362^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Specified domain dimensionality does not equal defined dimensionality of MDD. +# +363^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Cell base types of binary induce operation are incompatible. +364^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Cell base type and scalar type of binary induce operation are incompatible. +365^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Scalar types of binary operation are incompatible. +366^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Cell base type of unary induce operation is not supported. +367^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Scalar type of unary operation is not supported. +368^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Cell base type for induced dot operation must be complex. +369^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Scalar type for dot operation must be complex. +370^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Struct selector is not valid. +371^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Retrieval query must start with a SELECT statement. +372^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Update query must start with an INSERT, UPDATE, DELETE, DROP or CREATE statement. +373^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Unsatisfied MDD constant parameter. +380^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Data type can not be converted to selected data exchange format. +381^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Error in convertor of the selected data exchange format. +382^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Unknown conversion format. +383^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Parameter of oid function must be a persistent object of type MDD. +384^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: OId is not valid. +385^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Operation is not supported on strings. +386^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Base name of oid is not matching the currently opened one. +387^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: System name of oid is not matching the currently used one. +388^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Interval bound must be either an integer expression or an asterisk. +389^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: No interval (in case of fixed bounds, the upper one can not be smaller than the lower one). +390^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Minterval dimension specifications must be either of type interval or integer. +391^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Spatial operation must be either of type minterval, point, or integer. +393^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Operand of operation lo/hi must be of type interval. +394^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Operation lo/hi can not be used for an open bound. +395^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Operand of function sdom() must be of type MDD. +396^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Selection operation is not supported on this data type. +397^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Operand of minterval selection must be of type integer. +398^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Index for minterval selection is out of range. +399^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Operand of point selection must be of type integer. +# +# +# +400^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Domain of MDD constructor has to be defined. +401^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Can not evaluate domain expression to an minterval. +402^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Projected cell is not defined. +403^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Binary operation is not supported on these data types. +404^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Type of cell expression is not supported. +405^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: First operand of shift function must be of type MDD. +406^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Second operand of shift function must be of type Point. +407^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Dimensionality of MDD and point expression are not matching. +408^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Second operand of shift function must be a constant expression. +409^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Spatial domain shift of open bounds is not supported. +# +# +# +410^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Operand of point expression must be of type integer. +411^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Index for point selection is out of range. +412^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Value expression must be either of type atomic or complex. +413^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Condition expression must be of type boolean. +415^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Operand of count_cells must be of type r_Marray<d_Boolean>. +# +416^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: First operand of scale function must be of type MDD. +417^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Second operand of scale function must be either of type Point, Integer or Float. +# +418^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Second operand of bit function must be of integral type. +419^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Could not scale the domain. +# +499^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: Language feature is not supported. +# +510^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: The argument is outside the function domain. +511^E^Execution error $errorNo in line $lineNo, column $columnNo, near token $token: The function result exceeds the allowed range. +# +# 7XX errors for problems with Administration (some Oracle specific) +# +700^E^Admin error: General error creating RasDaMan database. +701^E^Admin error: Error creating table in tablespace RAS_DB_SCHEMA. +702^E^Admin error: Error inserting into table RAS_COUNTERS. +703^E^Admin error: Error creating table in tablespace RAS_DB_BLOB. +704^E^Admin error: Error creating index in tablespace RAS_DB_INDEX. +705^E^Admin error: Error inserting into table RAS_BASETYPENAMES. +706^E^Admin error: Error creating table in default tablespace. +707^E^Admin error: Error on COMMIT creating RasDaMan database. +708^E^Admin error: Database to be created already exists. +# +# 8xx errors for RasManager problems +# +800^E^RasManager Error: Could not connect to RasServer $url. +801^E^RasManager Error: System overloaded, please try again later. +802^E^RasManager Error: Acces denied, incorect user/password. +803^E^RasManager Error: Acces denied, no permission for operation. +804^E^RasManager Error: Acces denied, capability refused. +805^E^RasManager Error: No suitable servers started, call rasadmin. +806^E^RasManager Error: Write transaction in progress, please retry again later. +807^E^RasManager Error: Requested database unknown. +808^E^RasManager Error: Request format error. +# +# 9xx errors: Evaluation errors +# +900^E^Evaluation error $errorNo in line $lineNo, column $columnNo, near token $token: Type in typedef definition not supported. +901^E^Evaluation error $errorNo in line $lineNo, column $columnNo, near token $token: Set template type has to be a type reference. +902^E^Evaluation error $errorNo in line $lineNo, column $columnNo, near token $token: Type reference not found. +903^E^Evaluation error $errorNo in line $lineNo, column $columnNo, near token $token: MDD base type has to be a type reference or an atomic type. +904^E^Evaluation error $errorNo in line $lineNo, column $columnNo, near token $token: MDD type must have a domain specification. +905^E^Evaluation error $errorNo in line $lineNo, column $columnNo, near token $token: Struct type name exists already. +906^E^Evaluation error $errorNo in line $lineNo, column $columnNo, near token $token: MDD type name exists already. +907^E^Evaluation error $errorNo in line $lineNo, column $columnNo, near token $token: Set type name exists already. +# +950^E^Update error $errorNo in line $lineNo, column $columnNo, near token $token: Update target must be an iterator variable. +951^E^Update error $errorNo in line $lineNo, column $columnNo, near token $token: Update source must be an expression resulting in an r_Marray<>. +952^E^Update error $errorNo in line $lineNo, column $columnNo, near token $token: Update base type does not match MDD base type. +953^E^Update error $errorNo in line $lineNo, column $columnNo, near token $token: Update domain is not within MDD definition domain. +954^E^Update error $errorNo in line $lineNo, column $columnNo, near token $token: Update target expression must be an assignable value (l-value). +955^E^Update error $errorNo in line $lineNo, column $columnNo, near token $token: Collection name exists already. +956^E^Update error $errorNo in line $lineNo, column $columnNo, near token $token: Unknown collection type. +957^E^Update error $errorNo in line $lineNo, column $columnNo, near token $token: Unknown collection name. +958^E^Update error $errorNo in line $lineNo, column $columnNo, near token $token: Allocation of new oid failed. +959^E^Update error $errorNo in line $lineNo, column $columnNo, near token $token: MDD and collection types are incompatible. +960^E^Update error $errorNo in line $lineNo, column $columnNo, near token $token: Insert expression must be of type MDD. +961^E^Update error $errorNo in line $lineNo, column $columnNo, near token $token: Update domain must be of type Minterval. +962^E^Update error $errorNo in line $lineNo, column $columnNo, near token $token: Number of update intervals must match source dimensionaltiy. +963^E^Update error $errorNo in line $lineNo, column $columnNo, near token $token: Update domain dimensionality must match target MDD dimensionaltiy. +964^E^Update error $errorNo in line $lineNo, column $columnNo, near token $token: Type is not persistent. +965^E^Update error $errorNo: MDD type $token unknown. +966^E^Update error $errorNo: MDD type is missing. +# +# 1xxx errors: General errors +# +1000^E^General error: RasDaMan tables inconsistent. +1001^E^General error: RasDaMan server incompatible with database. +1002^E^General error: Blob with zero length encountered. +1003^E^General error: Tile container for TC index not found. +1004^E^General error: Index of MDD Object is not defined. +1005^E^General error: Storage structure of MDD Object is not defined. +1006^E^General error: Unknown index type requested. +1007^E^General error: Illegal index type choosen. +1008^E^General error: No valid collection type passed to MDD collection. +1009^E^General error: MDD object not valid or not persistent. +1010^E^General error: No valid MDD type passed to MDD object. +1011^E^General error: An illegal state has been reached. This is caused by a compiler bug or a library bug. +1012^E^General error: Invalid collection type passed to MDD collection. +1013^E^General error: The name of the type is too long. +1014^E^General error: Invalid name of the object, should contain only [a-zA-Z0-9_] +# +# 2xxx errors: Internal errors +# +2000^E^Internal error: There seems to be another database open. +2001^E^Internal error: Invalid OId type encountered. +2002^E^Internal error: Entry in user defined type not found. +2003^E^Internal error: Entry in user defined type out of bounds. +2004^E^Internal error: Transient index used instead of persistent index. +2005^E^Internal error: Index returned tiles multiple times. +2006^E^Internal error: Tile was not inserted into index. +2007^E^Internal error: Transient index access out of bounds. +2008^E^Internal error: MDD object exists multiple times in cache. +2009^E^Internal error: Some tile(s) were not inserted into the MDD object. +2010^E^Internal error: A conversion module returned an incorrect base type. +2011^E^Internal error: The collection type has no element type. +2012^E^Internal error: The marray type has no base type. +2013^E^Internal error: The property has no base type. +2014^E^Internal error: The scalar was passed a NULL value. +2015^E^Internal error: The index node that had to be split was not found in its parent. +2016^E^Internal error: The index found more cells than allowed. +2017^E^Internal error: The storage layout is incompatible with the index entries. +2018^E^Internal error: Object does not support swaping. +2019^E^Internal error: Error encountered during swaping. +# +# The last, the unexpected error in server +# +10000^E^Unexpected internal server error. diff --git a/raslib/test/test_endian.cc b/raslib/test/test_endian.cc new file mode 100644 index 0000000..250892a --- /dev/null +++ b/raslib/test/test_endian.cc @@ -0,0 +1,156 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * INCLUDE: test_endian.cc + * + * MODULE: raslib + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <iostream> + + +#ifdef EARLY_TEMPLATE +#define __EXECUTABLE__ +#endif + +#include "raslib/basetype.hh" +#include "raslib/primitivetype.hh" +#include "raslib/minterval.hh" +#include "raslib/rminit.hh" +#include "raslib/endian.hh" + + +RMINITGLOBALS('C') + + +static void print_numbers(const unsigned char *data, int size) +{ + int i; + + for (i=0; i<size; i++) + { + if ((i & 15) == 0) + { + if (i != 0) + printf("\n"); + + printf("%04x: ", i); + } + printf("%02x ", data[i]); + } + printf("\n"); fflush(stdout); +} + +static void test_endian(const char *schema, const r_Minterval &dom) +{ + r_Base_Type *type; + r_Primitive_Type *primType; + unsigned char *srcArray; + unsigned char *testArray; + unsigned char *smallArray; + unsigned long size; + unsigned long smallSize; + unsigned long i; + + cout << "test type <" << schema << ">" << endl; + + type = (r_Base_Type*)r_Type::get_any_type(schema); + primType = (r_Primitive_Type*)r_Type::get_any_type("long"); + + size = type->size() * dom.cell_count(); + + srcArray = new unsigned char[size]; + + for (i=0; i<size; i++) + srcArray[i] = (unsigned char)(i & 0xff); + + r_Minterval iterDom(dom.dimension()); + for (i=0; i<dom.dimension(); i++) + iterDom << r_Sinterval(dom[i].low(), (r_Range)(dom[i].low() + (dom[i].high() - dom[i].low() + 1) / 2)); + + cout << "dom = " << dom << ", iterDom = " << iterDom << endl; + + print_numbers(srcArray, 64); + + smallSize = type->size() * iterDom.cell_count(); + + testArray = new unsigned char[size]; + memset(testArray, 0, size); + smallArray = new unsigned char[smallSize]; + memset(smallArray, 0, smallSize); + + cout << "Linear change..." << endl; + r_Endian::swap_array(primType, size, srcArray, testArray); + print_numbers(testArray, 64); + + cout << "Semi-generic change, full..." << endl; + r_Endian::swap_array(type, dom, dom, srcArray, testArray); + print_numbers(testArray, 64); + + cout << "Semi-generic change, half..." << endl; + r_Endian::swap_array(type, dom, iterDom, srcArray, testArray); + print_numbers(testArray, 64); + + cout << "Fully generic change, full..." << endl; + r_Endian::swap_array(type, dom, dom, dom, dom, srcArray, testArray); + print_numbers(testArray, 64); + + cout << "Fully generic change, half..." << endl; + r_Endian::swap_array(type, dom, iterDom, iterDom, iterDom, srcArray, smallArray); + print_numbers(smallArray, 64); + + delete type; + delete primType; + + delete [] smallArray; + delete [] testArray; + delete [] srcArray; +} + + +int main(int argc, char *argv[]) +{ + r_Minterval dom(2); + + dom << r_Sinterval((r_Range)0, (r_Range)123) + << r_Sinterval((r_Range)10, (r_Range)456); + + test_endian("char", dom); + test_endian("short", dom); + test_endian("long", dom); + test_endian("float", dom); + test_endian("double", dom); + test_endian("struct {short, short, long}", dom); + + return 0; +} diff --git a/raslib/test/test_error.cc b/raslib/test/test_error.cc new file mode 100644 index 0000000..1f5fdb9 --- /dev/null +++ b/raslib/test/test_error.cc @@ -0,0 +1,223 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * SOURCE: test_error.cc + * + * MODULE: raslib + * + * PURPOSE: + * + * Test program to test class r_Error and its subclasses. + * + * + * COMMENTS: + * + ************************************************************/ + +#include <iostream> +#include <malloc.h> +#include "raslib/error.hh" + +#include "raslib/rminit.hh" + +RMINITGLOBALS('C') + +int main() +{ + cout << endl << "0. reading from errortxts table ----------------------------------" << endl; + try + { + throw r_Error( 10000 ); + } + catch( r_Error &err ) + { + cout << err.what() << endl; + } + + cout << endl << "1. Throwing r_Error() -------------------------------------------" << endl; + try + { + throw r_Error(); + } + catch( r_Error &err ) + { + cout << err.what() << endl; + } + + cout << endl << "2. Throwing r_Error( r_Error::r_Error_DatabaseUnknown ) ---------" << endl; + try + { + throw r_Error( r_Error::r_Error_DatabaseUnknown ); + } + catch( r_Error &err ) + { + cout << err.what() << endl; + } + + cout << endl << "3. Throwing r_Eno_interval() ------------------------------------" << endl; + try + { + throw r_Eno_interval(); + } + catch( r_Error &err ) + { + cout << err.what() << endl; + } + + cout << endl << "4. Throwing r_Eindex_violation( 10, 20, 25 ) --------------------" << endl; + try + { + throw r_Eindex_violation( 10, 20, 25 ); + } + catch( r_Error &err ) + { + cout << err.what() << endl; + } + + + cout << endl << "5. Throwing r_Edim_mismatch( 2, 3 ) -----------------------------" << endl; + try + { + throw r_Edim_mismatch( 2, 3 ); + } + catch( r_Error &err ) + { + cout << err.what() << endl; + } + + + cout << endl << "6. Throwing r_Einit_overflow() ----------------------------------" << endl; + try + { + throw r_Einit_overflow(); + } + catch( r_Error &err ) + { + cout << err.what() << endl; + } + + + cout << endl << "7. Throwing r_Eno_cell() ----------------------------------------" << endl; + try + { + throw r_Eno_cell(); + } + catch( r_Error &err ) + { + cout << err.what() << endl; + } + + cout << endl << "8. Throwing r_Equery_execution_failed( 99, 5, 7, 'SELECT' ) -----" << endl; + try + { + throw r_Equery_execution_failed( 99, 5, 7, "SELECT" ); + } + catch( r_Error &err ) + { + cout << err.what() << endl; + } + + cout << endl << "8. Testing r_Ebase_dbms ------------------------------------------" << endl; + cout << endl << "8.1 Throwing (4711, 'This is a test') ----------------------------" << endl; + try + { + throw r_Ebase_dbms( 4711, "This is a test" ); + } + catch( r_Error &err ) + { + cout << "Output of what() catching an r_Error &err" << endl; + cout << err.what() << endl; + } + try + { + throw r_Ebase_dbms( 4711, "This is a test" ); + } + catch( r_Ebase_dbms &err ) + { + cout << "Output of what() catching an r_Ebase_dbms &err" << endl; + cout << err.what() << endl; + } + + cout << endl << "8.2 Testing serialisation of r_Ebase_dbms ------------------------" << endl; + char* serialErr; + try + { + throw r_Ebase_dbms( 4711, "This is a test" ); + } + catch( r_Error &err ) + { + serialErr = err.serialiseError(); + cout << "serialised form: " << serialErr << endl; + } + try + { + cout << "Throwing error constructed from serialised form." << endl; + r_Error* testErr = r_Error::getAnyError(serialErr); + // for some strange reason a simple throw(*testErr) does not work here. It does not work + // if an r_Ebase_dbms is caught (core dump), it works if an r_Error is caught. Hmm, makes + // some sense since *r_Error is not polymorphic anymore. But it should not core dump. + // Well strange, but like this it works and this will be done only once in clientcomm.cc. + if(testErr->get_errorno () == 206) { + r_Ebase_dbms correctErr(*(r_Ebase_dbms*)testErr); + delete testErr; + throw correctErr; + } + else + cout << "Unexpected error read from serialised representation." << endl; + } + catch( r_Ebase_dbms &err ) + { + cout << "Output of what() catching an r_Ebase_dbms &err" << endl; + cout << err.what() << endl; + } + try + { + cout << "Throwing error constructed from serialised form." << endl; + r_Error* testErr = r_Error::getAnyError(serialErr); + if(testErr->get_errorno () == 206) { + r_Ebase_dbms correctErr(*(r_Ebase_dbms*)testErr); + delete testErr; + throw correctErr; + } + else + cout << "Unexpected error read from serialised representation." << endl; + } + catch( r_Error &err ) + { + cout << "Output of what() catching an r_Error &err" << endl; + cout << err.what() << endl; + } + cout << "Done" << endl; + free(serialErr); + + cout << endl; + + cout << "freeing error text table..."; + freeTextTable(); + cout << "ok." << endl; + + cout << endl << "------------------------------------------------------------------" << endl; + + return 0; +} diff --git a/raslib/test/test_metaobject.cc b/raslib/test/test_metaobject.cc new file mode 100644 index 0000000..4f93882 --- /dev/null +++ b/raslib/test/test_metaobject.cc @@ -0,0 +1,332 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * SOURCE: test_metaobject.cc + * + * MODULE: raslib + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +#include <iostream> + +#ifdef __VISUALC__ + #define __EXECUTABLE__ + #include "raslib/itertype.hh" + #include "raslib/structuretype.hh" + #include "raslib/attribute.hh" + #include "raslib/primitivetype.hh" + #include "raslib/rminit.hh" + #include "raslib/basetype.hh" + #include "raslib/marraytype.hh" + #undef __EXECUTABLE__ +#else + #include "raslib/itertype.hh" + #include "raslib/structuretype.hh" + #include "raslib/attribute.hh" + #include "raslib/primitivetype.hh" + #include "raslib/rminit.hh" + #include "raslib/basetype.hh" + #include "raslib/marraytype.hh" +#endif + +#include "raslib/error.hh" +#include "raslib/type.hh" +#include "raslib/structure.hh" +#include "raslib/primitive.hh" + +RMINITGLOBALS('C') + + +void testType( const char* stringType ) +{ + r_Type* type = NULL; + + cout << "Create " << stringType << endl; + + try + { + type = r_Type::get_any_type( stringType ); + } + catch( r_Error& errorObj ) + { + cout << errorObj.what() << endl << endl; + } + + cout << " Type: "; + + if( type ) + { + type->print_status( cout ); + cout << endl; + cout << type->type_id() << endl; + } + else + { + cout << "<not available>" << endl; + } + cout << endl; + delete type; + +} + +/* +void testEndian() +{ + r_Primitive_Type boolType("Bool", r_Primitive_Type::BOOL); + r_Primitive_Type shortType("Short", r_Primitive_Type::SHORT); + r_Primitive_Type uLongType("ULong", r_Primitive_Type::ULONG); + r_Type* structType; + structType = r_Type::get_any_type( "struct{bool e1, short e2, ulong e3}" ); + + char cChar = 47; + short cShort = 1065; + unsigned long cULong = 92753; + + char *boolCell = (char*)&cChar; + char *shortCell = (char*)&cShort; + char *uLongCell = (char*)&cULong; + char structCell[7] = { 1, 2, 3, 4, 5, 6, 7 }; + + cout << "Before convertToLittleEndian:" << endl; + cout << "Char: " << (long)*boolCell << endl + << "Short: " << (long)*shortCell << " " << (long)*(shortCell+1) << endl + << "ULong: " << (long)*uLongCell << " " << (long)*(uLongCell+1) << " " + << (long)*(uLongCell+2) << " " << (long)*(uLongCell+3) + << endl + << "Struct: " << (long)*structCell << " " << (long)*(structCell+1) + << " " << (long)*(structCell+2) << " " + << (long)*(structCell+3) << " " + << (long)*(structCell+4) << " " + << (long)*(structCell+5) << " " + << (long)*(structCell+6) << " " + << endl; + + boolType.convertToLittleEndian(boolCell, 1); + shortType.convertToLittleEndian(shortCell, 1); + uLongType.convertToLittleEndian(uLongCell, 1); + structType->convertToLittleEndian(structCell, 1); + + cout << "After convertToLittleEndian:" << endl; + cout << "Char: " << (long)*boolCell << endl + << "Short: " << (long)*shortCell << " " << (long)*(shortCell+1) << endl + << "ULong: " << (long)*uLongCell << " " << (long)*(uLongCell+1) << " " + << (long)*(uLongCell+2) << " " << (long)*(uLongCell+3) + << endl + << "Struct: " << (long)*structCell << " " << (long)*(structCell+1) + << " " << (long)*(structCell+2) << " " + << (long)*(structCell+3) << " " + << (long)*(structCell+4) << " " + << (long)*(structCell+5) << " " + << (long)*(structCell+6) << " " + << endl; + + boolType.convertToBigEndian(boolCell, 1); + shortType.convertToBigEndian(shortCell, 1); + uLongType.convertToBigEndian(uLongCell, 1); + structType->convertToLittleEndian(structCell, 1); + + cout << "After convertToBigEndian:" << endl; + cout << "Char: " << (long)*boolCell << endl + << "Short: " << (long)*shortCell << " " << (long)*(shortCell+1) << endl + << "ULong: " << (long)*uLongCell << " " << (long)*(uLongCell+1) << " " + << (long)*(uLongCell+2) << " " << (long)*(uLongCell+3) + << endl + << "Struct: " << (long)*structCell << " " << (long)*(structCell+1) + << " " << (long)*(structCell+2) << " " + << (long)*(structCell+3) << " " + << (long)*(structCell+4) << " " + << (long)*(structCell+5) << " " + << (long)*(structCell+6) << " " + << endl; + + delete structType; +} +*/ + +int main() +{ + cout << "Creating definining primitive types ..." << endl; + r_Primitive_Type myBool("Bool", r_Primitive_Type::BOOL); + myBool.print_status( cout ); cout << endl; + r_Primitive_Type myULong("ULong", r_Primitive_Type::ULONG); + myULong.print_status( cout ); cout << endl; + + r_Primitive_Type tmp = myBool; + tmp.print_status( cout ); cout << endl; + + r_Attribute tmpAtt("tmpAtt",tmp ); + tmpAtt.print_status( cout ); cout << endl; + + cout << "Creating a struct out of them ..." << endl; + r_Attribute myAttrs[2]; + myAttrs[0] = r_Attribute("Attr1", myBool ); + myAttrs[1] = r_Attribute("Attr2", myULong ); + + r_Structure_Type myStruct("aStruct", 2, myAttrs); + myStruct.print_status( cout ); cout << endl; + + cout << "Iterating attributes of struct:" << endl; + r_Structure_Type::attribute_iterator + iter(myStruct.defines_attribute_begin()); + while(iter != myStruct.defines_attribute_end()) + { + cout << " Name of Attribute: " << (*iter).name() << endl; + cout << " Offset of Attribute: " << (*iter).offset() << endl; + cout << " Size of type of Attribute: " + << (*iter).type_of().size() << endl; + cout << " Name of type of Attribute: " + << (*iter).type_of().name() << endl; + ++iter; + } + + testType("char"); + + testType("octet"); + testType("short"); + testType("ushort"); + testType("long"); + testType("ulong"); + testType("bool"); + testType("float"); + testType("double"); + + testType("struct{ char }"); + testType("struct{ char band1 }"); + + testType("struct{ char, octet, ulong, short }"); + + testType("struct{ char elem1, octet elem2, ulong elem3, short elem4 }"); + testType("struct{ char red, char green, char blue }" ); + testType("struct{char red, char green, char blue}" ); + + testType("struct{ struct{ char, char, char }, ulong }"); + testType("struct{ struct{ char elem1, char elem2, char elem3 } record, ulong value }"); + + + testType("marray< char >"); + testType("marray< char green>"); + testType("marray< struct{ char red} >"); + + testType("marray< struct{char red, char green, char blue} >" ); + + testType("set< marray< char > >"); + testType("set< marray< struct{ char red, char green, char blue } > >" ); + + testType("interval"); + testType("minterval"); + testType("point"); + testType("oid"); + + testType("set< interval >"); + testType("set< minterval >"); + testType("set< point >"); + testType("set< oid >"); + + /* shouldn't work */ + cout << endl << "Testing combinations which are not allowed..." << endl; + testType("set< marray< interval > >"); + testType("set< marray< minterval > >"); + testType("set< marray< point > >"); + testType("set< marray< oid > >"); + + testType("interval<set< marray< char > > >"); + testType("interval<struct{ point blue, interval green}>"); + testType("set< marray{ char > >"); + testType("struct<char>"); + + + + r_Type* type = NULL; + char* stringType = "marray< char blue>"; + + cout << "Create " << stringType << endl; + + try + { + type = r_Type::get_any_type( stringType ); + } + catch( r_Error& errorObj ) + { + cout << errorObj.what() << endl << endl; + } + + cout << " Type: "; + + if( type ) + { + type->print_status( cout ); + } + else + { + cout << "<not available>" << endl; + } + cout << endl; + + // cout << ((r_Marray_Type*)type)->getBaseType() << endl; + + cout << "Erzeugen einer Kopie und Ausgabe..." << endl; + r_Marray_Type my_marray; + + my_marray = *((r_Marray_Type*)(type)); + my_marray.print_status( cout ); + + cout << endl; + // cout << my_marray.getBaseType() << endl; + + delete type; + + r_Type* type2 = r_Type::get_any_type("struct{ short band1, char band2 }"); + + if( type2->isBaseType() ) + { + r_Base_Type* baseType2 = (r_Base_Type*)type2; + + cout << "Type: " << flush; + baseType2->print_status(); + cout << endl; + cout << "Size: " << baseType2->size() << endl; + } + + struct structType{ short band1r; char band2i; }; + + structType structValue = { 1, 2 }; + + r_Structure structObject( (const char*)&structValue, (const r_Structure_Type*)type2 ); + + structObject.print_status( cout ); + + cout << endl; + + delete type2; + + /* testEndian(); */ + return 0; +} + + diff --git a/raslib/test/test_minterval.cc b/raslib/test/test_minterval.cc new file mode 100644 index 0000000..f8f388f --- /dev/null +++ b/raslib/test/test_minterval.cc @@ -0,0 +1,118 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * SOURCE: test_sinterval.cc + * + * MODULE: raslib + * + * PURPOSE: + * + * COMMENTS: + * + ************************************************************/ + +#include <iostream> +#include <malloc.h> + +#include "raslib/minterval.hh" +#include "raslib/sinterval.hh" + +#include "raslib/rminit.hh" +RMINITGLOBALS('C') + +int main() +{ + cout << endl << endl; + cout << "Minterval Examples" << endl; + cout << "===================" << endl << endl; + + cout << "initializing interval [1:2,3:3] : " << endl; + r_Minterval m1 = r_Minterval(2); + m1 << r_Sinterval(1l,2l) << 3; + cout << m1 << endl << endl; + + cout << "copy the interval with copy constructor" << endl; + r_Minterval copy( m1 ); + cout << copy << endl << endl; + + cout << "test for equality: "; + if( copy == m1 ) + cout << "OK" << endl << endl; + else + cout << "FAILED" << endl << endl; + + cout << "union of [1:4,3:6] and [3:6,1:4] :" << endl; + r_Minterval m2 = r_Minterval(2) << r_Sinterval(1l,4l) << r_Sinterval(3l,6l); + r_Minterval m3 = r_Minterval(2) << r_Sinterval(3l,6l) << r_Sinterval(1l,4l); + try + { + m2 += m3; + } + catch( r_Error& ex1 ) + { + cerr << ex1.what() << endl; + } + cout << m2 << endl << endl; + + cout << "union of [1:4,3:6] and [3:6,8:9] : " << endl; + r_Minterval m4 = r_Minterval(2) << r_Sinterval(1l,4l) << r_Sinterval(3l,6l); + r_Minterval m5 = r_Minterval(2) << r_Sinterval(3l,6l) << r_Sinterval(8l,9l); + try + { + m4 += m5; + } + catch( r_Error& ex2 ) + { + cerr << ex2.what() << endl; + } + cout << m4 << endl << endl; + + cout << "closure of [1:4,3:6] and [7:9,1:2] : " << endl; + r_Minterval m6 = r_Minterval(2) << r_Sinterval(1l,4l) << r_Sinterval(3l,6l); + r_Minterval m7 = r_Minterval(2) << r_Sinterval(7l,9l) << r_Sinterval(1l,2l); + try + { + m6.closure_with( m7 ); + } + catch( r_Error& ex2 ) + { + cerr << ex2.what() << endl; + } + cout << m6 << endl << endl; + + cout << "intersection of [7:9,1:2] and [ " << m6[0].low() << ":" << m6[0].high() << "," << m6[1].low() << ":" << m6[1].high() << "]" << endl; + cout << m7.intersects_with( m6 ); + cout << endl; + + cout << "initializing domain [1:4,*:6,7:*]" << endl; + r_Minterval m8 = r_Minterval(3) << r_Sinterval(1l,4l) << r_Sinterval('*',6l) << r_Sinterval(7l,'*'); + char* stringRepresentation = m8.get_string_representation(); + cout << "string representation " << stringRepresentation << " should be " << m8 << endl; + + r_Minterval m9 = r_Minterval( stringRepresentation ); + cout << "recreation of the string delivers " << m9 << endl; + free( stringRepresentation ); + + return 0; +} diff --git a/raslib/test/test_miter.cc b/raslib/test/test_miter.cc new file mode 100644 index 0000000..55b2930 --- /dev/null +++ b/raslib/test/test_miter.cc @@ -0,0 +1,334 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * SOURCE: test_miter.cc + * + * MODULE: raslib + * + ************************************************************/ + +#include <iostream> +#include <math.h> +#include <stdlib.h> + +#include "raslib/miter.hh" +#include "raslib/minterval.hh" +#include "raslib/rminit.hh" +#include "raslib/rmdebug.hh" +RMINITGLOBALS('C') + +// structure storing information on iteration for each dimension +// (perhaps add dimension for reordering later) +typedef struct { + int repeat; // total number of repeats + int inc; // increment per repeat + int curr; // current repeat +} incArrElem; + +// for repeating inside the test functions +const int numRepeat = 100; + +r_Minterval +createCube(int size, int dim) +{ + int i; + long c = pow((double)size, 1.0/(double)dim); + + r_Minterval res(dim); + + for(i=0; i<dim; i++) + res << r_Sinterval(0l, c-1); + + i = 0; + while(res.cell_count() < size) { + res[i].set_high(res[i].high() + 1); + i++; + } + if(res.cell_count() > size) + res[i-1].set_high(res[i-1].high() - 1); + + return res; +} + +void +test_Miter( r_Minterval& m1, r_Minterval& m2, char* data ) +{ + char* currCell; + + // just to do something inside the loop + unsigned long sum = 0; + + cout <<"Iteration r_Miter: "; + + // for performance measurement + RMTimer mIterTimer("Iterator","r_Miter" ); + mIterTimer.start( ); + + r_Miter iter(&m2, &m1, 4, (char*)data); + for(int i=0; i<numRepeat; i++) { + iter.reset(); + while(!iter.isDone()) { + currCell = iter.nextCell(); + sum += *(long*)currCell; + } + } + + mIterTimer.stop( ); + cout << sum << endl; +} + +void +test_DirectIter( r_Minterval& m1, r_Minterval& m2, char* data ) +{ + int opSize = 4; + int dim = m1.dimension(); + int i; + char* currCell; + + // just to do something inside the loop + unsigned long sum = 0; + + incArrElem* incArrIter; + + cout <<"Iteration direct: "; + + // for performance measurement + RMTimer iterTimer("Iterator","directIter" ); + iterTimer.start( ); + + for(int r=0; r<numRepeat; r++) { + + // stores the increments + incArrIter = new incArrElem[dim]; + + currCell = (char*)data; + + // the following initializes incArrIter and calculates the first offset + int tIncIter = 1; // total increment for current dimension + int prevTIncIter = 1; // total increment for previous dimension + int incIter = 4; // current increment, corresponds to cell size + int firstOff = 0; + + for( i=0; i<dim; i++ ) { + // in RasDaMan the order of dimensions is the other way round! + int r = dim - i - 1; + // used for counting in iteration, initialize with 0 + incArrIter[i].curr = 0; + // how often is the increment added? + incArrIter[i].repeat = m2[r].high() - m2[r].low() + 1; + // the increment for the result tile (higher dimensions calculated + // further down) + incArrIter[i].inc = incIter; + + // calculate starting offset and increments for higher dimensions + // firstOff is the offset in chars of the first cell + firstOff += (m2[r].low()-m1[r].low()) * prevTIncIter * 4; + // tInc is the increment if the dimension would be skipped + tIncIter = (m1[r].high() - m1[r].low()+1) * prevTIncIter; + // inc is the real increment, after some cells in the dimensions + // have been iterated through. + incIter = (tIncIter - incArrIter[i].repeat*prevTIncIter) * 4; + // remember total increment of last dimension + prevTIncIter = tIncIter; + } + + currCell += firstOff; + + int done = 0; + // get first adresses + + while(!done) { + // iterate through lowest dimension + for(i=0; i<incArrIter[0].repeat; i++) { + // execute operation + sum += *(long*)currCell; + // increment adresses + currCell += incArrIter[0].inc; + } + // increment other dimensions + for(i=1; i<dim; i++) { + incArrIter[i].curr++; + currCell += incArrIter[i].inc; + if(incArrIter[i].curr < incArrIter[i].repeat) { + // no overflow in this dimension + break; + } else { + // overflow in this dimension + incArrIter[i].curr = 0; + } + } + if( i == dim ) { + // overflow in last dimension + done = 1; + } + } + delete [] incArrIter; + } + iterTimer.stop(); + cout << sum << endl; +} + +void +test_OldIter( r_Minterval& m1, r_Minterval& m2, char* data ) +{ + // just to do something inside the loop + unsigned long sum = 0; + + cout <<"Iteration oldIter: "; + // for performance measurement + RMTimer oldIterTimer("Iterator","oldIter" ); + oldIterTimer.start( ); + + r_Point pOp(m2.dimension()); + int done; + int recalc; + int i, j; + const int opSize = 4; + int dim = m2.dimension(); + int innerExtent = (m2.get_extent())[dim-1]; + char* cellOp; + + // initialize points + for(i = 0; i < dim; i++) + { + pOp << 0; + } + + for(int r=0; r<numRepeat; r++) { + done = 0; + recalc = 0; + + // initialize points + for(i = 0; i < dim; i++) + { + pOp[i] = m2[i].low(); + } + + cellOp = (char*)data + m1.cell_offset(pOp)*4; + + // iterate over all cells + while(!done) + { + if( recalc ) + { + cellOp = (char*)data + m1.cell_offset(pOp)*4; + recalc = 0; + } + + // iterate through innermost dimension + for(j = 0; j < innerExtent; j++ ) { + // execute operation on cell + sum += *(long*)cellOp; + cellOp += opSize; + } + + // increment coordinates + i = dim - 2; + // special case! 1-D operands! + if( i < 0 ) + break; + ++pOp[i]; + recalc = 1; + while( pOp[i] > m2[i].high() ) + { + pOp[i] = m2[i].low(); + i--; + if(i < 0) + { + done = 1; + break; + } + ++pOp[i]; + } + } + } + + oldIterTimer.stop(); + cout << sum << endl; +} + +void +test_CppIter( unsigned long cells, char* data ) +{ + unsigned long sum = 0; + RMTimer cppIterTimer("Iterator", "cppIter"); + cppIterTimer.start(); + + for(int r=0; r<numRepeat; r++) { + for(int i = 0; i<1048576; i++) { + sum += data[i]; + } + } + + cppIterTimer.stop(); + cout <<"Iteration C++: " << sum << endl; +} + +int main() +{ + const unsigned long noCells = 1048576; + unsigned long* data; + + for(int dim=1; dim<=7; dim++) { + r_Minterval m2; + r_Minterval m1(dim); + + m2 = createCube(noCells, dim); + + for(int i=0; i<dim; i++) { + m1 << r_Sinterval(m2[i].low()-1, m2[i].high()+1); + } + + // as basis for the operations + data = new unsigned long[m1.cell_count()]; + for(int i=0; i < m1.cell_count(); i++) { + data[i] = i; + } + + cout <<"Iterate through " << m2 << " in "<< m1 << endl; + + RMInit::bmOut << "Dimensionality: " << dim << ", cells: " + << m2.cell_count() << endl; + + for(int i=0; i<5; i++) { + test_Miter( m1, m2, (char*)data ); + test_OldIter( m1, m2, (char*)data ); + test_DirectIter( m1, m2, (char*)data ); + } + delete [] data; + } + + RMInit::bmOut << "1-D Iteration in C++:" << endl; + + data = new unsigned long[noCells]; + + for(int i=0; i < noCells; i++) { + data[i] = i; + } + + for(int i=0; i<5; i++) { + test_CppIter( noCells, (char*)data ); + } + delete [] data; +} diff --git a/raslib/test/test_miterd b/raslib/test/test_miterd Binary files differnew file mode 100644 index 0000000..7ee9a45 --- /dev/null +++ b/raslib/test/test_miterd diff --git a/raslib/test/test_miterd.cc b/raslib/test/test_miterd.cc new file mode 100644 index 0000000..e664aec --- /dev/null +++ b/raslib/test/test_miterd.cc @@ -0,0 +1,75 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * SOURCE: test_miter.cc + * + * MODULE: raslib + * + ************************************************************/ + +#include <iostream> +#include <math.h> +#include <stdlib.h> + +#include "raslib/miterd.hh" +#include "raslib/minterval.hh" +#include "raslib/rminit.hh" +#include "raslib/rmdebug.hh" +RMINITGLOBALS('C') + +int +main(int i, char** argv) + { + unsigned short src[][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}}; + for (r_Dimension i = 0; i < 4; i++) + { + for (r_Dimension c = 0; c < 4; c++) + { + cout << src[i][c] << " "; + } + cout << endl; + } + for (r_Dimension i = 0; i < 4; i++) + { + for (r_Dimension c = 0; c < 4; c++) + { + cout << src[c][i] << " "; + } + cout << endl; + } + /* + r_MiterDirect iter(src, r_Minterval("[0:3,0:3]"), r_Minterval("[0:3,0:3]"), 2, 0); + r_Dimension order[] = {1,1}; + unsigned int step[] = {1,0}; + r_Dimension order2[] = {0}; + while (!iter.isDone()) + { + iter.iterateUserOrder(order, step); + cout << *(unsigned short*)(iter.getData()) << " " << endl;; + cout << "pos " << iter << endl; + // cout << *(unsigned short*)(iter.getData()) << " "; + iter.operator++(); + } + */ + } diff --git a/raslib/test/test_miterf.cc b/raslib/test/test_miterf.cc new file mode 100644 index 0000000..43660f9 --- /dev/null +++ b/raslib/test/test_miterf.cc @@ -0,0 +1,118 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * SOURCE: test_miterf.cc + * + * MODULE: raslib + * + * PURPOSE: + * + * COMMENTS: + * + ************************************************************/ + + +#include <iostream> +#include <math.h> +#include <stdlib.h> + +#include "raslib/mddtypes.hh" +#include "raslib/miterf.hh" +#include "raslib/minterval.hh" +#include "raslib/rminit.hh" +#include "raslib/rmdebug.hh" + + + +RMINITGLOBALS('C') + + +int main(int argc, char *argv[]) +{ + r_Dimension dim = 3; + r_Minterval iv(dim); + r_Dimension i; + double *iterMin, *iterMax, *iterStep; + int typeLength = 1; + long totalSize = typeLength; + long totalSteps = 1; + double stepBy = 1.5; + + i = 1; + while (i < argc) + { + if (strcmp(argv[i], "-s") == 0) + { + stepBy = atof(argv[++i]); + } + i++; + } + + cout << "Step by " << stepBy << endl; + + iterMin = new double[dim]; iterMax = new double[dim]; + iterStep = new double[dim]; + for (i=0; i<dim; i++) + { + int steps; + + iterStep[i] = stepBy; + iterMin[i] = 0; + iterMax[i] = (1<<(4+i)) - 1; + iv << r_Sinterval((r_Range)(iterMin[i]), (r_Range)(iterMax[i])); + totalSize *= (r_Range)(iterMax[i]) - (r_Range)(iterMin[i]) + 1; + steps = (int)((iterMax[i] - iterMin[i]) / iterStep[i]); + totalSteps *= (steps + 1); + iterMax[i] = iterMin[i] + (steps + 0.5)*iterStep[i]; // rounding effects + } + + char *srcData = new char[totalSize]; + + cout << "Total size: 0x" << hex << totalSize + << ", base address " << (void*)srcData << endl; + + r_MiterFloat iter(&iv, iterMin, iterMax, iterStep, typeLength, srcData); + + long steps = 0; + while (!iter.isDone()) + { + char *cell = iter.nextCell(); + + if (cell + typeLength > srcData + totalSize) + { + cout << dec << "Overflow by " << (cell - srcData) - totalSize << endl; + } + steps++; + } + + cout << dec << "Did " << steps << " steps out of " << totalSteps << endl; + if (steps != totalSteps) + cout << "!!! WRONG NUMBER OF STEPS !!!" << endl; + + delete [] srcData; + + delete [] iterMin; delete [] iterMax; delete [] iterStep; + + return 0; +} diff --git a/raslib/test/test_oid.cc b/raslib/test/test_oid.cc new file mode 100644 index 0000000..d7c3170 --- /dev/null +++ b/raslib/test/test_oid.cc @@ -0,0 +1,181 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * SOURCE: test_oid.cc + * + * MODULE: raslib + * + * PURPOSE: + * + * COMMENTS: + * + ************************************************************/ + +#include <iostream> +#include <iomanip.h> +// #include <limits.h> +#include "raslib/oid.hh" + +#include "raslib/rminit.hh" +RMINITGLOBALS('C') + +int main() +{ + cout << endl << endl; + cout << "OId Examples" << endl; + cout << "============" << endl << endl; + + cout << "Create oid1" << endl; + r_OId oid1( "testSystem", "testBase", 99 ); + cout << " oid1........: " << oid1 << endl; + cout << " system name: " << oid1.get_system_name() << endl; + cout << " base name: " << oid1.get_base_name() << endl; + cout << " local oid..: " << oid1.get_local_oid() << endl << endl; + + cout << "Create oid2 with string representation of oid1" << endl; + r_OId oid2( oid1.get_string_representation() ); + cout << " oid2........: " << oid2 << endl; + cout << " system name: " << oid2.get_system_name() << endl; + cout << " base name: " << oid2.get_base_name() << endl; + cout << " local oid..: " << oid2.get_local_oid() << endl << endl; + + cout << "Assign oid1 to oid2" << endl; + oid2 = oid1; + cout << " oid2........: " << oid2 << endl; + cout << " system name: " << oid2.get_system_name() << endl; + cout << " base name: " << oid2.get_base_name() << endl; + cout << " local oid..: " << oid2.get_local_oid() << endl << endl; + + cout << "Assign temporary oid to oid2" << endl; + oid2 = r_OId( "testSystem|testBase|100" ); + cout << " oid2........: " << oid2 << endl; + cout << " system name: " << oid2.get_system_name() << endl; + cout << " base name: " << oid2.get_base_name() << endl; + cout << " local oid..: " << oid2.get_local_oid() << endl << endl; + + cout << "Assign oid1 to oid1" << endl; + oid1 = oid1; + cout << " oid1........: " << oid1 << endl; + cout << " system name: " << oid1.get_system_name() << endl; + cout << " base name: " << oid1.get_base_name() << endl; + cout << " local oid..: " << oid1.get_local_oid() << endl << endl; + + cout << "Create oid3 as a copy of oid1 with the copy constructor" << endl; + r_OId oid3( oid1 ); + cout << " oid3........: " << oid3 << endl; + cout << " system name: " << oid3.get_system_name() << endl; + cout << " base name: " << oid3.get_base_name() << endl; + cout << " local oid..: " << oid3.get_local_oid() << endl << endl; + + cout << "Create oid4 with string testSystem|testBase|100" << endl; + r_OId oid4( "testSystem|testBase|100" ); + cout << " oid4........: " << oid4 << endl; + cout << " system name: " << oid4.get_system_name() << endl; + cout << " base name: " << oid4.get_base_name() << endl; + cout << " local oid..: " << oid4.get_local_oid() << endl << endl; + + cout << "Create oid5 with string |testBase|100" << endl; + r_OId oid5( "|testBase|100" ); + cout << " oid5........: " << oid5 << endl; + cout << " system name: " << oid5.get_system_name() << endl; + cout << " base name: " << oid5.get_base_name() << endl; + cout << " local oid..: " << oid5.get_local_oid() << endl << endl; + + cout << "Create oid6 with string ||100" << endl; + r_OId oid6( "||100" ); + cout << " oid6........: " << oid6 << endl; + cout << " system name: " << oid6.get_system_name() << endl; + cout << " base name: " << oid6.get_base_name() << endl; + cout << " local oid..: " << oid6.get_local_oid() << endl << endl; + + cout << "Create oid7 with string |||" << endl; + r_OId oid7( "|||" ); + cout << " oid7........: " << oid7 << endl; + cout << " system name: " << oid7.get_system_name() << endl; + cout << " base name: " << oid7.get_base_name() << endl; + cout << " local oid..: " << oid7.get_local_oid() << endl << endl; + + cout << "Create oid8 with an empty string" << endl; + r_OId oid8( "" ); + cout << " oid8........: " << oid8 << endl; + cout << " system name: " << oid8.get_system_name() << endl; + cout << " base name: " << oid8.get_base_name() << endl; + cout << " local oid..: " << oid8.get_local_oid() << endl << endl; + + cout << "Create oid9 with just a local oid" << endl; + r_OId oid9( 0, 0, 100 ); + cout << " oid8........: " << oid9 << endl; + cout << " system name: " << oid9.get_system_name() << endl; + cout << " base name: " << oid9.get_base_name() << endl; + cout << " local oid..: " << oid9.get_local_oid() << endl << endl; + + cout << "Create oid10 with copy constructor from oid1" << endl; + r_OId oid10( oid1 ); + cout << " oid10.......: " << oid10 << endl; + cout << " system name: " << oid10.get_system_name() << endl; + cout << " base name: " << oid10.get_base_name() << endl; + cout << " local oid..: " << oid10.get_local_oid() << endl << endl; + + cout << "Compare r_OId( \"testSystem1|testBase|99\") < r_OId( \"testSystem2|testBase|99\")" << endl; + cout << (r_OId( "testSystem1|testBase|99") < r_OId( "testSystem2|testBase|99")) << endl << endl; + + cout << "Compare r_OId( \"testSystem|testBase1|99\") < r_OId( \"testSystem|testBase2|99\")" << endl; + cout << (r_OId( "testSystem|testBase1|99") < r_OId( "testSystem|testBase2|99")) << endl << endl; + + cout << "Compare r_OId( \"testSystem|testBase|99\") < r_OId( \"testSystem|testBase|100\")" << endl; + cout << (r_OId( "testSystem1|testBase|99") < r_OId( "testSystem2|testBase|100")) << endl << endl; + + cout << "Compare r_OId( \"testSystem1|testBase|99\") > r_OId( \"testSystem2|testBase|99\")" << endl; + cout << (r_OId( "testSystem1|testBase|99") > r_OId( "testSystem2|testBase|99")) << endl << endl; + + cout << "Compare r_OId( \"testSystem|testBase1|99\") > r_OId( \"testSystem|testBase2|99\")" << endl; + cout << (r_OId( "testSystem|testBase1|99") > r_OId( "testSystem|testBase2|99")) << endl << endl; + + cout << "Compare r_OId( \"testSystem|testBase|99\") > r_OId( \"testSystem|testBase|100\")" << endl; + cout << (r_OId( "testSystem1|testBase|99") > r_OId( "testSystem2|testBase|100")) << endl << endl; + + cout << "Create oid11" << endl; + // cout << "Double limit: " << DBL_MAX << "= 0x" << hex << DBL_MAX << dec << endl; + double maxDouble = 0xffffffffffff; + cout << "48bit : " << setprecision(30) << maxDouble << endl; + cout << "48bit - 1 : " << setprecision(30) << maxDouble-1 << endl; + cout << "48bit + 1 : " << setprecision(30) << maxDouble+1 << endl; + r_OId oid11( "testSystem", "testBase", maxDouble ); + cout << " oid11.......: " << oid11 << endl; + cout << " system name: " << oid11.get_system_name() << endl; + cout << " base name: " << oid11.get_base_name() << endl; + cout << " local oid..: " << oid11.get_local_oid() << endl << endl; + + cout << endl; + + cout << "Create oid12 with string ''" << endl; + r_OId oid12( "" ); + cout << " oid12.......: " << oid12 << endl; + cout << " system name: " << oid12.get_system_name() << endl; + cout << " base name: " << oid12.get_base_name() << endl; + cout << " local oid..: " << oid12.get_local_oid() << endl << endl; + + return 0; +} + diff --git a/raslib/test/test_params.cc b/raslib/test/test_params.cc new file mode 100644 index 0000000..4be15df --- /dev/null +++ b/raslib/test/test_params.cc @@ -0,0 +1,101 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * INCLUDE: test_params.cc + * + * MODULE: raslib + * + * PURPOSE: + * + * COMMENTS: + * + ************************************************************/ + +#include <stdio.h> +#include <iostream> +#include <string.h> +#include <stdlib.h> + +#include "raslib/rminit.hh" +#include "raslib/parseparams.hh" + + +RMINITGLOBALS('C') + + +typedef struct test_params_s { + r_Parse_Params *pp; + int zlevel; + double fidelity; + char *lstream; +} test_params_t; + + +static void test_params(test_params_t ¶ms, char *str) +{ + cout << "Processing (" << str << ") ..." << endl; + + params.pp->process(str); + + cout << "zlevel = " << params.zlevel + << ", fidelity = " << params.fidelity + << ", stream = <" << params.lstream << ">" << endl; + + // string was allocated with strdup, free now + free(str); +} + + +int main(int argc, char *argv[]) +{ + r_Parse_Params pp; + test_params_t params = {&pp, -1, -1.0, NULL}; + + pp.add("zlevel", ¶ms.zlevel, r_Parse_Params::param_type_int); + pp.add("fidelity", ¶ms.fidelity, r_Parse_Params::param_type_double); + pp.add("stream", ¶ms.lstream, r_Parse_Params::param_type_string); + + // Note: must use strdup() because Purify doesn't find reads over the end of + // static strings! + test_params(params, strdup("0123")); + test_params(params, strdup("zlevel, fidelity=0.1")); + test_params(params, strdup("zlevel=a")); + test_params(params, strdup("zlevel=6")); + test_params(params, strdup("\"zlevel=6\"")); + test_params(params, strdup("fidelity=0.90")); + test_params(params, strdup("stream=rle")); + test_params(params, strdup("stream=eee ")); + test_params(params, strdup("stream=\"rle\"")); + test_params(params, strdup("zlevel=9, fidelity=0.75, stream=zlib")); + test_params(params, strdup("stream=rle, zlevel=5")); + test_params(params, strdup("zlevel=1, foobar=hello")); + test_params(params, strdup("foobar=hello, zlevel=2")); + test_params(params, strdup(" stream=\"zlib\" ")); + test_params(params, strdup(" foobar=\"hello, you there\", stream=\"rle\"")); + + if (params.lstream != NULL) + delete [] params.lstream; + + return 0; +} diff --git a/raslib/test/test_point.cc b/raslib/test/test_point.cc new file mode 100644 index 0000000..63b2f05 --- /dev/null +++ b/raslib/test/test_point.cc @@ -0,0 +1,90 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * SOURCE: test_point.cc + * + * MODULE: raslib + * + * PURPOSE: + * + * COMMENTS: + * + ************************************************************/ + +#include <iostream> +#include <stdlib.h> + +#include "raslib/point.hh" + +#include "raslib/rminit.hh" +RMINITGLOBALS('C') + +int main() +{ + cout << endl << endl; + cout << "Point Examples" << endl; + cout << "===============" << endl << endl; + + cout << "initialize 1D-point: " << flush; + r_Point d1(1); + cout << d1 << endl; + + cout << "set value to 9 : " << flush; + d1[0] = 9; + cout << d1 << endl; + + r_Point a(3); + a << 1 << 2 << 3; + cout << "stream initializing point (1,2,3) : " << a << endl << endl; + + try{ + cout << "read out of range : " << a[3] << endl; + } + catch( r_Eindex_violation& ex ){ + cout << ex.what(); + } + cout << endl << endl; + + r_Point b = r_Point(3) << 1 << 2 << 3; + cout << "assignment point (1,2,3) : " << b << endl << endl; + + cout << "temp. obj. (1,2,3), access second coord. : " << ( r_Point(3) << 1 << 2 << 3 )[1] << endl << endl; + + a[1] = 4; + cout << "assignment a[1]=4 to a(1,2,3) : " << a << endl << endl; + + r_Point c = b; + cout << "equal operator test: " << flush; + if( c == b ) + cout << "OK" << endl; + else + cout << "FALSE" << endl; + + char* stringRep = b.get_string_representation(); + cout << endl << "String representation of point " << b << ": " << stringRep << endl; + cout << "Result of string constructor: " << r_Point( stringRep ) << endl; + free( stringRep ); + + cout << "Result of r_Point(\"[ 0, 5, 3]\"): " << r_Point("[ 0, 5, 3]") << endl; +} diff --git a/raslib/test/test_rmdebug.cc b/raslib/test/test_rmdebug.cc new file mode 100644 index 0000000..c6f29ca --- /dev/null +++ b/raslib/test/test_rmdebug.cc @@ -0,0 +1,179 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * SOURCE: test_rmdebug.cc + * + * MODULE: raslib + * + * PURPOSE: + * + * COMMENTS: + * + ************************************************************/ + +#include <iostream> +#include "raslib/rmdebug.hh" + +#include "raslib/rminit.hh" + +// number of repetitions for performance tests +static const int repeat = 100000; + +RMINITGLOBALS('C') + +void testFunc1() +{ + RMDebug localRMDebug = RMDebug("Class1", "testFunc1", "Module1", + __FILE__, __LINE__); +} + +void testFunc2(int reclevel) +{ + RMDebug localRMDebug = RMDebug("Class1", "testFunc2", "Module1", + __FILE__, __LINE__); + + if(reclevel > 1) + testFunc2(reclevel - 1); +} + +void testFunc3(void) +{ + RMDebug localRMDebug("Class1", "testFunc3", "server", + __FILE__, __LINE__); + + RMDBGMOUT( 2, RMDebug::module_server, NULL, "D: testing 1" ); + RMDBGMOUT( 3, RMDebug::module_server, "Class1", "D: testing 2" ); + RMDBGMINOUT( 4, RMDebug::module_server, "Class1", "D: testing 3" ); +} + +void testFunc4(int reclevel) +{ + RMDebug localRMDebug(1, "Class2", "testFunc4", RMDebug::module_raslib, + __FILE__, __LINE__); + + if (reclevel > 1) + testFunc4(reclevel - 1); +} + +// this was used to test correctness + +void oldMain() +{ + int i; + + for(i = 1; i<=5; i++) + testFunc1(); + + testFunc2(5); + + testFunc3(); + + testFunc4(4); + + cout << "Test of RMTimer" << endl; + + cout << "The following should hold approximately: timer2 + timer3 = timer1" << endl << endl; + + RMTimer* timer1 = new RMTimer("main","timer1"); + RMTimer* timer2 = new RMTimer("main","timer2"); + + timer2->pause(); + + RMTimer* timer3 = new RMTimer("main","timer3"); + for( long busy=0; busy <= 50000000; busy++ ); + delete timer3; + + timer2->resume(); + + for( busy=0; busy <= 30000000; busy++ ); + + delete timer2; + delete timer1; + + cout << "Benchmark level set to " << RManBenchmark << endl; + + RMInit::bmOut << "test output in benchmark stream" << endl; +} + +double testStatic(double dummy) +{ + RMTIMER("test_rmdebug", "testStatic"); + + for(int i=0; i<repeat; i++) + dummy = dummy*4711.4712; + return dummy; +} + +double testDynamic(double dummy) +{ +#ifdef RMANBENCHMARK + RMTimer* localRMTimer = 0; + + if( RManBenchmark >= 3 ) + localRMTimer = new RMTimer("test_rmdebug", "testDynamic"); +#endif + + for(int i=0; i<repeat; i++) + dummy = dummy*4711.4712; + +#ifdef RMANBENCHMARK + if( localRMTimer ) delete localRMTimer; +#endif + + return dummy; +} + +// Evaluating time needed for measurement with different uses +// of RMTimer. + +void testPerf() +{ + double dummy = 3.14; + + cout << "Testing dynamic RMTimer vs. static RMTimer." << endl; + + // to put in cache + dummy = testStatic(dummy); + cout << "Static:" << endl; + dummy = testStatic(dummy); + + // to put in cache + dummy = testDynamic(dummy); + cout << "Dynamic:" << endl; + dummy = testDynamic(dummy); +} + +int main() +{ + RMDebug::initRMDebug(); + RManBenchmark = 4; + RMInit::bmOut = cout.rdbuf(); + + oldMain(); + // testPerf(); + + return 0; +} + + diff --git a/raslib/test/test_sinterval.cc b/raslib/test/test_sinterval.cc new file mode 100644 index 0000000..fa2fbc5 --- /dev/null +++ b/raslib/test/test_sinterval.cc @@ -0,0 +1,164 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * SOURCE: test_sinterval.cc + * + * MODULE: raslib + * + * PURPOSE: + * + * COMMENTS: + * + ************************************************************/ + +#include <iostream> +#include <stdlib.h> + +#include "raslib/sinterval.hh" + +#include "raslib/rminit.hh" +RMINITGLOBALS('C') + +int main() +{ + r_Sinterval interval1, interval2; + + char Buffer[256]; + + cout << "lower bound ? "; + cin >> Buffer; + cout << endl; + + if( Buffer[0] == '*' ) + interval1.set_low('*'); + else + interval1.set_low( atol( Buffer ) ); + + cout << "upper bound ? "; + cin >> Buffer; + cout << endl; + + if( Buffer[0] == '*' ) + interval1.set_high('*'); + else + interval1.set_high( atol( Buffer ) ); + + cout << "interval1 = ["; + interval1.print_status( cout ); + cout << "]" << endl << endl; + + cout << "lower bound ? "; + cin >> Buffer; + cout << endl; + + if( Buffer[0] == '*' ) + interval2.set_low('*'); + else + interval2.set_low( atol( Buffer ) ); + + cout << "upper bound ? "; + cin >> Buffer; + cout << endl; + + if( Buffer[0] == '*' ) + interval2.set_high('*'); + else + interval2.set_high( atol( Buffer ) ); + + cout << "interval1 = ["; + interval2.print_status( cout ); + cout << "]" << endl << endl; + + r_Sinterval result; + + try{ + result.union_of( interval1, interval2 ); + + cout << "union = ["; + result.print_status( cout ); + cout << "]" << endl; + } + catch( r_Eno_interval error ) + { + cerr << "union " << error.what() << endl; + } + + try{ + result.difference_of( interval1, interval2 ); + + cout << "difference = ["; + result.print_status( cout ); + cout << "]" << endl; + } + catch( r_Eno_interval error ) + { + cerr << "difference " << error.what() << endl; + } + + try{ + result.intersection_of( interval1, interval2 ); + + cout << "intersection = ["; + result.print_status( cout ); + cout << "]" << endl; + } + catch( r_Eno_interval error ) + { + cerr << "intersection " << error.what() << endl; + } + + try{ + result.closure_of( interval1, interval2 ); + + cout << "closure = ["; + result.print_status( cout ); + cout << "]" << endl; + } + catch( r_Eno_interval error ) + { + cerr << "closure " << error.what() << endl; + } + + if( interval1.intersects_with( interval2 ) ) + cerr << "The intervals intersect." << endl; + else + cerr << "The intervals do not intersect." << endl; + + cerr << endl; + + r_Sinterval b( 4l, 10l ); + char* stringRep = b.get_string_representation(); + cout << endl << "String representation of interval " << b << ": " << stringRep << endl; + cout << "Result of string constructor: " << r_Sinterval( stringRep ) << endl; + free( stringRep ); + + cout << "Result of r_Sinterval(\" 10 : 100\"): " << r_Sinterval(" 10 : 100") << endl; + cout << "Result of r_Sinterval(\" * : 100\"): " << r_Sinterval(" * : 100") << endl; + cout << "Result of r_Sinterval(\" 10 : * \"): " << r_Sinterval(" 10 : * ") << endl; + cout << "Result of r_Sinterval(\" * : * \"): " << r_Sinterval(" * : * ") << endl; + + return 0; +} + + diff --git a/raslib/test/test_timer.cc b/raslib/test/test_timer.cc new file mode 100644 index 0000000..797c0fa --- /dev/null +++ b/raslib/test/test_timer.cc @@ -0,0 +1,101 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * SOURCE: test_timer.cc + * + * MODULE: raslib + * + * PURPOSE: + * + * Test program to test class RMTimer. + * + * + * COMMENTS: + * + ************************************************************/ + +#include <iostream> +#include "raslib/rmdebug.hh" + + +RMINITGLOBALS('C') + +class Exp { + +public: + Exp( char* name ); + + void useTimer( ); + + ~Exp( ); + + RMTimer* t1; + RMTimer t2; + char* name; +}; + +Exp::Exp( char* n) + :t2("Test Timer ", "t2" ), name( n ) +{ + t1 = new RMTimer( "Test Timer ", "t1" ); +} + +void Exp::useTimer( ) +{ + cout << "useTimer "<< name << " t1 ... "<<endl; + t1->start( ); + t1->stop( ); + cout << "and t2"<<endl; + t2.start( ); + t2.stop( ); +} + +Exp::~Exp( ) +{ + cout << "Exp::~Exp( " << name << " ) "<< endl; + delete t1; +} + +static const Exp exp1("Static Exp Object"); + +int main() +{ + + /* + RMTimer tt( "Test Timer ", "tt" ); + + cout << "RMTimer start( )" <<endl; + tt.start( ); + tt.stop( ); + */ + + Exp e( "Exp Object" ); + e.useTimer( ); + + Exp* ep = new Exp("Pointer to Exp Object"); + ep->useTimer( ); + delete ep; + + return 0; +} diff --git a/raslib/type.cc b/raslib/type.cc new file mode 100644 index 0000000..690160c --- /dev/null +++ b/raslib/type.cc @@ -0,0 +1,671 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ + +static const char rcsid[] = "@(#)raslib, r_Type: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/type.cc,v 1.17 2003/12/27 23:01:21 rasdev Exp $"; + +#include <ctype.h> // for isalpha() +#include <string.h> // for strncmp() + +#include "raslib/type.hh" +#include "raslib/collectiontype.hh" +#include "raslib/primitivetype.hh" +#include "raslib/complextype.hh" +#include "raslib/structuretype.hh" +#include "raslib/marraytype.hh" +#include "raslib/sintervaltype.hh" +#include "raslib/mintervaltype.hh" +#include "raslib/pointtype.hh" +#include "raslib/oidtype.hh" +#include "raslib/attribute.hh" +#include "raslib/error.hh" +#include "raslib/rminit.hh" + +r_Type::r_Type() + : r_Meta_Object() +{ +} + +r_Type::r_Type(const char* newTypeName) + : r_Meta_Object(newTypeName) +{ +} + +r_Type::r_Type(const r_Type& oldObj) + : r_Meta_Object(oldObj) +{ +} + +const r_Type& +r_Type::operator=(const r_Type& oldObj) +{ + // Gracefully handle self assignment + if (this == &oldObj) return *this; + + r_Meta_Object::operator=(oldObj); + + return *this; +} + +r_Type::~r_Type() +{ +} + +bool +r_Type::isStructType() const +{ + return false; +} + +bool +r_Type::isComplexType() const +{ + return false; +} + +bool +r_Type::isBaseType() const +{ + return false; +} + +bool +r_Type::isCollectionType() const +{ + return false; +} + +bool +r_Type::isMarrayType() const +{ + return false; +} + +bool +r_Type::isPrimitiveType() const +{ + return false; +} + +bool +r_Type::isSintervalType() const +{ + return false; +} + +bool +r_Type::isMintervalType() const +{ + return false; +} + +bool +r_Type::isPointType() const +{ + return false; +} + +bool +r_Type::isOidType() const +{ + return false; +} + +r_Type* +r_Type::get_any_type(const char* type_string) +{ + char* pos = (char*)type_string; + char* identifier = NULL; + r_Type* returnValue = NULL; + DLTOKEN token = DLUNKNOWN; + + // one token look ahead + char* oldPos = pos; + token = getNextToken(pos, identifier); + pos = oldPos; + + switch(token) + { + case DLMARRAY: + returnValue = getMarrayType(pos); + break; + case DLSET: + returnValue = getCollectionType(pos); + break; + default: + returnValue = getType(pos); + } + + return returnValue; +} + +r_Type::DLTOKEN +r_Type::getNextToken(char* &pos, char* &identifier) +{ + DLTOKEN token = DLUNKNOWN; + + while(*pos == ' ') pos ++; + + if(!strncmp(pos, "marray", 6)) + { + token = DLMARRAY; + pos += 6; + } + else if(!strncmp(pos, "set", 3)) + { + token = DLSET; + pos += 3; + } + else if(!strncmp(pos, "struct", 6)) + { + token = DLSTRUCT; + pos += 6; + } + else if(*pos == '[') + { + token = DLLEP; + pos += 1; + } + else if(*pos == ']') + { + token = DLREP; + pos += 1; + } + else if(*pos == '<') + { + token = DLLAP; + pos += 1; + } + else if(*pos == '>') + { + token = DLRAP; + pos += 1; + } + else if(*pos == '{') + { + token = DLLCP; + pos += 1; + } + else if(*pos == '}') + { + token = DLRCP; + pos += 1; + } + else if(*pos == ',') + { + token = DLCOMMA; + pos += 1; + } + else if(!strncmp(pos, "octet", 5)) + { + token = DLOCTET; + pos += 5; + } + else if(!strncmp(pos, "char", 4)) + { + token = DLCHAR; + pos += 4; + } + else if(!strncmp(pos, "ulong", 5)) + { + token = DLULONG; + pos += 5; + } + else if(!strncmp(pos, "long", 4)) + { + token = DLLONG; + pos += 4; + } + else if(!strncmp(pos, "short", 5)) + { + token = DLSHORT; + pos += 5; + } + else if(!strncmp(pos, "ushort", 6)) + { + token = DLUSHORT; + pos += 6; + } + else if(!strncmp(pos, "float", 5)) + { + token = DLFLOAT; + pos += 5; + } + else if(!strncmp(pos, "double", 6)) + { + token = DLDOUBLE; + pos += 6; + } + else if(!strncmp(pos, "bool", 4)) + { + token = DLBOOL; + pos += 4; + } + else if(!strncmp(pos, "complexd", 8)) + { + token = DLCOMPLEXTYPE2; + pos += 8; + } + // the order of testing it's important here + // (complex is a proper prefix of complexd!) + else if(!strncmp(pos, "complex", 7)) + { + token = DLCOMPLEXTYPE1; + pos += 7; + } + else if(!strncmp(pos, "interval", 8)) + { + token = DLINTERVAL; + pos += 8; + } + else if(!strncmp(pos, "minterval", 9)) + { + token = DLMINTERVAL; + pos += 9; + } + else if(!strncmp(pos, "point", 5)) + { + token = DLPOINT; + pos += 5; + } + else if(!strncmp(pos, "oid", 3)) + { + token = DLOID; + pos += 3; + } + else + { + token = DLIDENTIFIER; // identifier + + char* beginPos = pos; + + // read identifier + while(isalnum(*pos) || *pos == '-' || *pos == '_') pos++; + + identifier = new char[pos-beginPos+1]; + strncpy(identifier, beginPos, pos-beginPos); + identifier[pos-beginPos] = '\0'; + } + + while(*pos == ' ') pos ++; + + return token; +} + +r_Collection_Type* +r_Type::getCollectionType(char* &pos) +{ + char* identifier = NULL; + r_Collection_Type* returnValue = NULL; + r_Type* elementType = NULL; + DLTOKEN token = DLUNKNOWN; + + // get 'set' + getNextToken(pos, identifier); + + // get '<' + if(getNextToken(pos, identifier) != DLLAP) + { + RMInit::logOut << "r_Type::getCollectionType(" << pos << ") expected DLLAP" << endl; + throw r_Error(INTERNALDLPARSEERROR); + } + + // one token look ahead + char* oldPos = pos; + token = getNextToken(pos, identifier); + pos = oldPos; + + switch(token) + { + case DLMARRAY: + elementType = getMarrayType(pos); + break; + default: + elementType = getType(pos); + } + + returnValue = new r_Collection_Type(*elementType); + delete elementType; + + return returnValue; +} + +r_Type* +r_Type::getType(char* &pos) +{ + DLTOKEN token = DLUNKNOWN; + char* identifier = 0; + r_Type* returnValue = 0; + + // one token look ahead + char* oldPos = pos; + token = getNextToken(pos, identifier); + pos = oldPos; + + if(token == DLSTRUCT) + returnValue = getStructureType(pos); + else if(token == DLINTERVAL) + returnValue = getSintervalType(pos); + else if(token == DLMINTERVAL) + returnValue = getMintervalType(pos); + else if(token == DLPOINT) + returnValue = getPointType(pos); + else if(token == DLOID) + returnValue = getOidType(pos); + else + returnValue = getPrimitiveType(pos); + + return returnValue; +} + +r_Marray_Type* +r_Type::getMarrayType(char* &pos) +{ + char* identifier = NULL; + r_Marray_Type* returnValue = NULL; + r_Base_Type* basetype = NULL; + + // get 'marray' + getNextToken(pos, identifier); + // get '<' + if(getNextToken(pos, identifier) != DLLAP) + { + RMInit::logOut << "r_Type::getMarrayType(" << pos << ") expected DLLAP" << endl; + throw r_Error(INTERNALDLPARSEERROR); + } + + // get base type (structure or primitive type) + basetype = getBaseType(pos); + + returnValue = new r_Marray_Type(*basetype); + + delete basetype; + + return returnValue; +} + +r_Base_Type* +r_Type::getBaseType(char* &pos, int offset) +{ + DLTOKEN token = DLUNKNOWN; + char* identifier = NULL; + r_Base_Type* returnValue = NULL; + + // one token look ahead + char* oldPos = pos; + token = getNextToken(pos, identifier); + pos = oldPos; + + if(token == DLSTRUCT) + returnValue = getStructureType(pos, offset); + else + returnValue = getPrimitiveType(pos); + + return returnValue; +} + +r_Primitive_Type* +r_Type::getPrimitiveType(char* &pos) +{ + char* dummy = NULL; + r_Primitive_Type* returnValue = NULL; + + switch(getNextToken(pos, dummy)) + { + case DLCHAR: + returnValue = new r_Primitive_Type("Char", r_Type::CHAR); + break; + case DLOCTET: + returnValue = new r_Primitive_Type("Octet", r_Type::OCTET); + break; + case DLSHORT: + returnValue = new r_Primitive_Type("Short", r_Type::SHORT); + break; + case DLUSHORT: + returnValue = new r_Primitive_Type("UShort", r_Type::USHORT); + break; + case DLLONG: + returnValue = new r_Primitive_Type("Long", r_Type::LONG); + break; + case DLULONG: + returnValue = new r_Primitive_Type("ULong", r_Type::ULONG); + break; + case DLBOOL: + returnValue = new r_Primitive_Type("Bool", r_Type::BOOL); + break; + case DLFLOAT: + returnValue = new r_Primitive_Type("Float", r_Type::FLOAT); + break; + case DLDOUBLE: + returnValue = new r_Primitive_Type("Double", r_Type::DOUBLE); + break; + case DLCOMPLEXTYPE1: + returnValue = new r_Complex_Type("Complex1", r_Type::COMPLEXTYPE1); + break; + case DLCOMPLEXTYPE2: + returnValue = new r_Complex_Type("Complex2", r_Type::COMPLEXTYPE2); + break; + default: + { + RMInit::logOut << "r_Type::getPrimitiveType(" << pos << ") unknown token" << endl; + throw r_Error(INTERNALDLPARSEERROR); + } + } + + return returnValue; +} + +r_Structure_Type* +r_Type::getStructureType(char* &pos, int offset) +{ + r_Structure_Type* returnValue = NULL; + char* identifier = NULL; + DLTOKEN token = DLUNKNOWN; + r_Attribute* attributes = NULL; + int noAttributes=0; + + // get 'struct' + getNextToken(pos, identifier); + + // get '{' + if(getNextToken(pos, identifier) != DLLCP) + { + RMInit::logOut << "r_Type::getStructureType(" << pos << ", " << offset << ") expected DLLCP" << endl; + throw r_Error(INTERNALDLPARSEERROR); + } + + int localOffset = offset; + + while(token != DLRCP) + { + // get type + r_Base_Type* type = getBaseType(pos, localOffset); + + // adjust local offset + localOffset += type->size(); + + // get optional name + token = getNextToken(pos, identifier); + + // allocate another attribute (very inefficient) + noAttributes++; + r_Attribute* oldAttributes = attributes; + attributes = new r_Attribute[noAttributes]; + for(int i=0; i < noAttributes-1; i++) + attributes[i] = oldAttributes[i]; + if(oldAttributes) + delete[] oldAttributes; + oldAttributes = NULL; + + if(token == DLIDENTIFIER) + { + // with identifier + attributes[noAttributes-1] = r_Attribute(identifier, *type); + delete[] identifier; + identifier = NULL; + // read next token + token = getNextToken(pos, identifier); + } + else + { + // without identifier + attributes[noAttributes-1] = r_Attribute("", *type); + } + + delete type; + type = NULL; + + if(token != DLCOMMA && token != DLRCP) + { + RMInit::logOut << "r_Type::getStructureType(" << pos << ", " << offset << ") expected DLRCP or DLCOMMA" << endl; + throw r_Error(INTERNALDLPARSEERROR); + } + } + + returnValue = new r_Structure_Type("Structure", noAttributes, attributes, offset); + + if(attributes) + delete[] attributes; + attributes = NULL; + return returnValue; +} + +r_Sinterval_Type* +r_Type::getSintervalType(char* &pos) +{ + char* dummy = NULL; + r_Sinterval_Type* returnValue = NULL; + + getNextToken(pos, dummy); + + returnValue = new r_Sinterval_Type(); + + return returnValue; +} + +r_Minterval_Type* +r_Type::getMintervalType(char* &pos) +{ + char* dummy = NULL; + r_Minterval_Type* returnValue = NULL; + + getNextToken(pos, dummy); + + returnValue = new r_Minterval_Type(); + + return returnValue; +} + +r_Point_Type* +r_Type::getPointType(char* &pos) +{ + char* dummy = NULL; + r_Point_Type* returnValue = NULL; + + getNextToken(pos, dummy); + + returnValue = new r_Point_Type(); + + return returnValue; +} + +r_Oid_Type* +r_Type::getOidType(char* &pos) +{ + char* dummy = NULL; + r_Oid_Type* returnValue = NULL; + + getNextToken(pos, dummy); + + returnValue = new r_Oid_Type(); + + return returnValue; +} + +std::ostream& operator<<( std::ostream& s, r_Type::r_Type_Id t ) +{ + switch( t ) + { + case r_Type::ULONG: + s << "ulong"; + break; + case r_Type::USHORT: + s << "ushort"; + break; + case r_Type::BOOL: + s << "bool"; + break; + case r_Type::LONG: + s << "long"; + break; + case r_Type::SHORT: + s << "short"; + break; + case r_Type::OCTET: + s << "octet"; + break; + case r_Type::DOUBLE: + s << "double"; + break; + case r_Type::FLOAT: + s << "float"; + break; + case r_Type::CHAR: + s << "char"; + break; + case r_Type::COMPLEXTYPE1: + s << "complextype1"; + break; + case r_Type::COMPLEXTYPE2: + s << "complextype2"; + break; + case r_Type::STRUCTURETYPE: + s << "structuretype"; + break; + case r_Type::MARRAYTYPE: + s << "marraytype"; + break; + case r_Type::COLLECTIONTYPE: + s << "collectiontype"; + break; + case r_Type::SINTERVALTYPE: + s << "sintervaltype"; + break; + case r_Type::MINTERVALTYPE: + s << "mintervaltype"; + break; + case r_Type::POINTTYPE: + s << "pointtype"; + break; + case r_Type::OIDTYPE: + s << "oidtype"; + break; + case r_Type::UNKNOWNTYPE: + s << "unknowntype"; + break; + default: + s << "UNKNOWN r_Type_Id" << t; + break; + } + + return s; +} diff --git a/raslib/type.hh b/raslib/type.hh new file mode 100644 index 0000000..da2272c --- /dev/null +++ b/raslib/type.hh @@ -0,0 +1,167 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * INCLUDE: type.hh + * + * MODULE: raslib + * CLASS: r_Type + * + * COMMENTS: + * +*/ + +#ifndef _D_TYPE_ +#define _D_TYPE_ + +#include "raslib/metaobject.hh" +#include "raslib/mddtypes.hh" + +class r_Primitive_Type; +class r_Structure_Type; +class r_Marray_Type; +class r_Sinterval_Type; +class r_Minterval_Type; +class r_Point_Type; +class r_Oid_Type; +class r_Base_Type; +class r_Collection_Type; + +//@ManMemo: Module: {\bf raslib} + +/** + This class the superclass for all types in the ODMG conformant + representation of the RasDaMan type system. +*/ + +class r_Type : public r_Meta_Object +{ +public: + /// typedef for the enum specifying a primitive type, structure type, marray type, + /// interval type, minterval type, point type or oid type + enum r_Type_Id { ULONG, USHORT, BOOL, LONG, SHORT, OCTET, + DOUBLE, FLOAT, CHAR, COMPLEXTYPE1, COMPLEXTYPE2, + STRUCTURETYPE, MARRAYTYPE, COLLECTIONTYPE, + SINTERVALTYPE, MINTERVALTYPE, POINTTYPE, OIDTYPE, + UNKNOWNTYPE }; + /// default constructor. + r_Type(); + /// constructor getting name of type. + r_Type( const char* newTypeName); + /// copy constructor + r_Type( const r_Type& oldObj ); + /// assignment operator. + const r_Type& operator=( const r_Type& oldObj ); + /// destructor. + virtual ~r_Type(); + + /// clone operation + virtual r_Type* clone() const = 0; + + /// retrieve id of the type. + virtual r_Type::r_Type_Id type_id() const = 0; + + /// check, if type is primitive or structured. + virtual bool isStructType() const; + + /// check, if type is a base type ( primitive type or structure type). + virtual bool isBaseType() const; + + /// check, if type is a base type ( primitive type or structure type). + virtual bool isComplexType() const; + + /// check, if type is a marray type. + virtual bool isMarrayType() const; + + /// check, if type is a primitive type. + virtual bool isPrimitiveType() const; + + /// check, if type is a Sinterval + virtual bool isSintervalType() const; + + /// check, if type is a Minterval + virtual bool isMintervalType() const; + + /// check, if type is a Colelction type + virtual bool isCollectionType() const; + + /// check, if type is a Point + virtual bool isPointType() const; + + /// check, if type is a oid + virtual bool isOidType() const; + + /// build type schema from string representation + static r_Type* get_any_type( const char* type_string ); + + /// converts array of cells from NT byte order to Unix byte order. + virtual void convertToLittleEndian(char* cells, r_Area noCells) const = 0; + + /// converts array of cells from Unix byte order to NT byte order. + virtual void convertToBigEndian(char* cells, r_Area noCells) const = 0; + + /// token enumeration for parser + enum DLTOKEN { DLMARRAY, DLSET, DLSTRUCT, DLCOMMA, + DLLEP, DLREP, DLLAP, DLRAP, DLLCP, DLRCP, + DLIDENTIFIER, DLCHAR, DLOCTET, DLSHORT, DLUSHORT, + DLLONG, DLULONG, DLFLOAT, DLDOUBLE, DLBOOL, DLCOMPLEXTYPE1, DLCOMPLEXTYPE2, + DLINTERVAL, DLMINTERVAL, DLPOINT, DLOID, DLUNKNOWN }; + + +private: + + //@Man: Methodes and structures for dl parser: + //@{ + /// + + /// + static DLTOKEN getNextToken( char* &pos, char* &identifier ); + /// + static r_Collection_Type* getCollectionType( char* &pos ); + /// + static r_Type* getType( char* &pos ); + /// + static r_Marray_Type* getMarrayType( char* &pos ); + /// + static r_Base_Type* getBaseType( char* &pos, int offset=0 ); + /// + static r_Primitive_Type* getPrimitiveType( char* &pos ); + /// + static r_Structure_Type* getStructureType( char* &pos, int offset=0 ); + /// + static r_Sinterval_Type* getSintervalType( char* &pos ); + /// + static r_Minterval_Type* getMintervalType( char* &pos ); + /// + static r_Point_Type* getPointType( char* &pos ); + /// + static r_Oid_Type* getOidType( char* &pos ); + + /// + //@} + + +}; + +extern std::ostream& operator<<( std::ostream& s, r_Type::r_Type_Id t ); + +#endif |