Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
koffice/filters/karbon/ai/aielement.cc

805 wiersze
18 KiB

/* This file is part of the KDE project
Copyright (C) 2002, Dirk Sch<EFBFBD>nberger <dirk.schoenberger@sz-online.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "aielement.h"
#include <tqglobal.h>
AIElement::Private::Private()
{
typ = AIElement::Invalid;
}
AIElement::Private::Private( Private* d )
{
switch( d->typ )
{
case AIElement::Invalid:
break;
case AIElement::String:
case AIElement::Reference:
case AIElement::Operator:
value.ptr = new TQString( *((TQString*)d->value.ptr) );
break;
case AIElement::CString:
// TQCString is explicit shared
value.ptr = new TQCString( *((TQCString*)d->value.ptr) );
break;
/* case AIElement::List:
value.ptr = new TQValueList<AIElement>( *((TQValueList<AIElement>*)d->value.ptr) );
break; */
case AIElement::ElementArray:
value.ptr = new TQValueVector<AIElement>( *((TQValueVector<AIElement>*)d->value.ptr) );
break;
case AIElement::Block:
value.ptr = new TQValueVector<AIElement>( *((TQValueVector<AIElement>*)d->value.ptr) );
break;
case AIElement::ByteArray:
value.ptr = new TQByteArray( *((TQByteArray*)d->value.ptr) );
break;
case AIElement::Int:
value.i = d->value.i;
break;
case AIElement::UInt:
value.u = d->value.u;
break;
case AIElement::Double:
value.d = d->value.d;
break;
case AIElement::Byte:
value.b = d->value.b;
break;
default:
Q_ASSERT( 0 );
}
typ = d->typ;
}
AIElement::Private::~Private()
{
clear();
}
void AIElement::Private::clear()
{
switch( typ )
{
case AIElement::String:
case AIElement::Operator:
case AIElement::Reference:
delete (TQString*)value.ptr;
break;
case AIElement::CString:
delete (TQCString*)value.ptr;
break;
/* case AIElement::List:
delete (TQValueList<AIElement>*)value.ptr;
break; */
case AIElement::ElementArray:
delete (TQValueVector<AIElement>*)value.ptr;
break;
case AIElement::Block:
delete (TQValueVector<AIElement>*)value.ptr;
break;
case AIElement::ByteArray:
delete (TQByteArray*)value.ptr;
break;
case AIElement::Invalid:
case AIElement::Int:
case AIElement::UInt:
case AIElement::Double:
case AIElement::Byte:
break;
}
typ = AIElement::Invalid;
}
/*!
Constructs an invalid aielement.
*/
AIElement::AIElement()
{
d = new Private;
}
/*!
Destroys the AIElement and the contained object.
Note that subclasses that reimplement clear() should reimplement
the destructor to call clear(). This destructor calls clear(), but
because it is the destructor, AIElement::clear() is called rather than
a subclass's clear().
*/
AIElement::~AIElement()
{
if ( d->deref() )
delete d;
}
/*!
Constructs a copy of the aielement, \a p, passed as the argument to this
constructor. Usually this is a deep copy, but a shallow copy is made
if the stored data type is explicitly shared, as e.g. TQImage is.
*/
AIElement::AIElement( const AIElement& p )
{
d = new Private;
*this = p;
}
/*!
Constructs a new aielement with a string value, \a val.
*/
AIElement::AIElement( const TQString& val, Type type )
{
d = new Private;
d->typ = type;
d->value.ptr = new TQString( val );
}
/*!
Constructs a new aielement with a C-string value, \a val.
If you want to modify the TQCString after you've passed it to this
constructor, we recommend passing a deep copy (see
TQCString::copy()).
*/
AIElement::AIElement( const TQCString& val )
{
d = new Private;
d->typ = CString;
d->value.ptr = new TQCString( val );
}
/*!
Constructs a new aielement with a C-string value of \a val if \a val
is non-null. The aielement creates a deep copy of \a val.
If \a val is null, the resulting aielement has type Invalid.
*/
AIElement::AIElement( const char* val )
{
d = new Private;
if ( val == 0 )
return;
d->typ = CString;
d->value.ptr = new TQCString( val );
}
/*!
Constructs a new aielement with an integer value, \a val.
*/
AIElement::AIElement( int val )
{
d = new Private;
d->typ = Int;
d->value.i = val;
}
/*!
Constructs a new aielement with an unsigned integer value, \a val.
*/
AIElement::AIElement( uint val )
{
d = new Private;
d->typ = UInt;
d->value.u = val;
}
/*!
Constructs a new aielement with an byte value, \a val.
*/
AIElement::AIElement( uchar val )
{
d = new Private;
d->typ = Byte;
d->value.b = val;
}
/*!
Constructs a new aielement with a floating point value, \a val.
*/
AIElement::AIElement( double val )
{
d = new Private;
d->typ = Double;
d->value.d = val;
}
/*!
Constructs a new aielement with a list value, \a val.
*/
/* AIElement::AIElement( const TQValueList<AIElement>& val )
{
d = new Private;
d->typ = List;
d->value.ptr = new TQValueList<AIElement>( val );
} */
AIElement::AIElement( const TQValueVector<AIElement>& val, Type type )
{
d = new Private;
d->typ = type;
d->value.ptr = new TQValueVector<AIElement>( val );
}
AIElement::AIElement( const TQByteArray& val )
{
d = new Private;
d->typ = ByteArray;
d->value.ptr = new TQByteArray( val );
}
/*!
Assigns the value of the aielement \a aielement to this aielement.
This is a deep copy of the aielement, but note that if the aielement
holds an explicitly shared type such as TQImage, a shallow copy
is performed.
*/
AIElement& AIElement::operator= ( const AIElement& aielement )
{
AIElement& other = (AIElement&)aielement;
other.d->ref();
if ( d->deref() )
delete d;
d = other.d;
return *this;
}
/*!
\internal
*/
void AIElement::detach()
{
if ( d->count == 1 )
return;
d->deref();
d = new Private( d );
}
/*!
Returns the name of the type stored in the aielement.
The returned strings describe the C++ datatype used to store the
data: for example, "TQFont", TQSTRING_OBJECT_NAME_STRING, or "TQValueList<AIElement>".
An Invalid aielement returns 0.
*/
const char* AIElement::typeName() const
{
return typeToName( d->typ );
}
/*! Convert this aielement to type Invalid and free up any resources
used.
*/
void AIElement::clear()
{
if ( d->count > 1 )
{
d->deref();
d = new Private;
return;
}
d->clear();
}
static const int ntypes = 11;
static const char* const type_map[ntypes] =
{
0,
// "TQValueList<AIElement>",
TQSTRING_OBJECT_NAME_STRING,
"int",
"uint",
"double",
"TQCString",
"Operator",
"Reference",
"TQValueVector<AIElement>",
TQBYTEARRAY_OBJECT_NAME_STRING,
"uchar",
};
/*!
Converts the enum representation of the storage type, \a typ, to its
string representation.
*/
const char* AIElement::typeToName( Type typ )
{
if ( typ >= ntypes )
return 0;
return type_map[typ];
}
/*!
Converts the string representation of the storage type gven in \a
name, to its enum representation.
If the string representation cannot be converted to any enum
representation, the aielement is set to \c Invalid.
*/
AIElement::Type AIElement::nameToType( const char* name )
{
for ( int i = 0; i < ntypes; i++ ) {
if ( !qstrcmp( type_map[i], name ) )
return (Type) i;
}
return Invalid;
}
/*!
Returns the aielement as a TQString if the aielement has type()
String, CString, ByteArray, Int, Uint, Double,
or TQString() otherwise.
\sa asString()
*/
const TQString AIElement::toString() const
{
if ( d->typ == CString )
return TQString::fromLatin1( toCString() );
if ( d->typ == Int )
return TQString::number( toInt() );
if ( d->typ == UInt )
return TQString::number( toUInt() );
if ( d->typ == Double )
return TQString::number( toDouble() );
if ( d->typ == Byte )
return TQString::number( toByte() );
if ( d->typ != String )
return TQString();
return *((TQString*)d->value.ptr);
}
const TQString AIElement::toReference() const
{
if ( d->typ != Reference )
return TQString();
return *((TQString*)d->value.ptr);
}
const TQString AIElement::toOperator() const
{
if ( d->typ != Operator )
return TQString();
return *((TQString*)d->value.ptr);
}
/*!
Returns the aielement as a TQCString if the aielement has type()
CString or String, or a 0 otherwise.
\sa asCString()
*/
const TQCString AIElement::toCString() const
{
if ( d->typ == CString )
return *((TQCString*)d->value.ptr);
if ( d->typ == String )
return ((TQString*)d->value.ptr)->latin1();
if ( d->typ == Operator )
return ((TQString*)d->value.ptr)->latin1();
if ( d->typ == Reference )
return ((TQString*)d->value.ptr)->latin1();
return 0;
}
/*!
Returns the aielement as an int if the aielement has type()
String, CString, Int, UInt, Double, Byte, or 0 otherwise.
If \a ok is non-null, \a *ok is set to TRUE if the value could be
converted to an int and FALSE otherwise.
\sa asInt() canCast()
*/
int AIElement::toInt( bool * ok ) const
{
if( d->typ == String )
return ((TQString*)d->value.ptr)->toInt( ok );
if ( d->typ == CString )
return ((TQCString*)d->value.ptr)->toInt( ok );
if ( ok )
*ok = canCast( UInt );
if( d->typ == Int )
return d->value.i;
if( d->typ == UInt )
return (int)d->value.u;
if( d->typ == Byte )
return (int)d->value.b;
if ( d->typ == Double )
return (int)d->value.d;
return 0;
}
uchar AIElement::toByte( bool * ok ) const
{
if( d->typ == String )
return ((TQString*)d->value.ptr)->toShort( ok );
if ( d->typ == CString )
return ((TQCString*)d->value.ptr)->toShort( ok );
if ( ok )
*ok = canCast( UInt );
if( d->typ == Byte )
return d->value.b;
if( d->typ == Int )
return (uchar)d->value.i;
if( d->typ == UInt )
return (uchar)d->value.u;
if ( d->typ == Double )
return (uchar)d->value.d;
return 0;
}
/*!
Returns the aielement as an unsigned int if the aielement has type()
String, CString, UInt, Int, Double, Byte, or 0 otherwise.
If \a ok is non-null, \a *ok is set to TRUE if the value could be
converted to a uint and FALSE otherwise.
\sa asUInt()
*/
uint AIElement::toUInt( bool * ok ) const
{
if( d->typ == String )
return ((TQString*)d->value.ptr)->toUInt( ok );
if ( d->typ == CString )
return ((TQCString*)d->value.ptr)->toUInt( ok );
if ( ok )
*ok = canCast( UInt );
if( d->typ == Int )
return d->value.i;
if( d->typ == UInt )
return (int)d->value.u;
if( d->typ == Byte )
return (int)d->value.b;
if ( d->typ == Double )
return (int)d->value.d;
return 0;
}
/*!
Returns the aielement as a double if the aielement has type()
String, CString, Double, Int, UInt, Byte, or 0.0 otherwise.
If \a ok is non-null, \a *ok is set to TRUE if the value could be
converted to a double and FALSE otherwise.
\sa asDouble()
*/
double AIElement::toDouble( bool * ok ) const
{
if( d->typ == String )
return ((TQString*)d->value.ptr)->toDouble( ok );
if ( d->typ == CString )
return ((TQCString*)d->value.ptr)->toDouble( ok );
if ( ok )
*ok = canCast( Double );
if ( d->typ == Double )
return d->value.d;
if ( d->typ == Int )
return (double)d->value.i;
if ( d->typ == UInt )
return (double)d->value.u;
if ( d->typ == Byte )
return (double)d->value.b;
return 0.0;
}
/*!
Returns the aielement as a TQValueList<AIElement> if the aielement has type()
List or StringList, or an empty list otherwise.
Note that if you want to iterate over the list, you should
iterate over a copy, e.g.
\code
TQValueList<AIElement> list = myAIElement.toList();
TQValueList<AIElement>::Iterator it = list.begin();
while( it != list.end() ) {
myProcessing( *it );
++it;
}
\endcode
\sa asList()
*/
/* const TQValueList<AIElement> AIElement::toList() const
{
if ( d->typ == List )
return *((TQValueList<AIElement>*)d->value.ptr);
return TQValueList<AIElement>();
} */
const TQValueVector<AIElement> AIElement::toElementArray() const
{
if ( d->typ == ElementArray )
return *((TQValueVector<AIElement>*)d->value.ptr);
return TQValueVector<AIElement>();
}
const TQValueVector<AIElement> AIElement::toBlock() const
{
if ( d->typ == Block )
return *((TQValueVector<AIElement>*)d->value.ptr);
return TQValueVector<AIElement>();
}
const TQByteArray AIElement::toByteArray() const
{
if ( d->typ == ByteArray )
return *((TQByteArray*)d->value.ptr);
return TQByteArray();
}
#define TQ_VARIANT_AS( f ) TQ##f& AIElement::as##f() { \
if ( d->typ != f ) *this = AIElement( to##f() ); else detach(); return *((TQ##f*)d->value.ptr);}
TQ_VARIANT_AS(String)
TQ_VARIANT_AS(CString)
/*!
Returns the aielement's value as int reference.
*/
int& AIElement::asInt()
{
detach();
if ( d->typ != Int ) {
int i = toInt();
d->clear();
d->value.i = i;
d->typ = Int;
}
return d->value.i;
}
/*!
Returns the aielement's value as unsigned int reference.
*/
uint& AIElement::asUInt()
{
detach();
if ( d->typ != UInt ) {
uint u = toUInt();
d->clear();
d->value.u = u;
d->typ = UInt;
}
return d->value.u;
}
/*!
Returns the aielement's value as double reference.
*/
double& AIElement::asDouble()
{
if ( d->typ != Double ) {
double dbl = toDouble();
d->clear();
d->value.d = dbl;
d->typ = Double;
}
return d->value.d;
}
/*!
Returns the aielement's value as byte reference.
*/
uchar& AIElement::asByte()
{
detach();
if ( d->typ != Byte ) {
uchar b = toByte();
d->clear();
d->value.b = b;
d->typ = Byte;
}
return d->value.b;
}
/*!
Returns the aielement's value as aielement list reference.
Note that if you want to iterate over the list, you should
iterate over a copy, e.g.
\code
TQValueList<AIElement> list = myAIElement.asList();
TQValueList<AIElement>::Iterator it = list.begin();
while( it != list.end() ) {
myProcessing( *it );
++it;
}
\endcode
*/
/* TQValueList<AIElement>& AIElement::asList()
{
if ( d->typ != List )
*this = AIElement( toList() );
return *((TQValueList<AIElement>*)d->value.ptr);
} */
TQValueVector<AIElement>& AIElement::asElementArray()
{
if ( d->typ != ElementArray )
*this = AIElement( toElementArray() );
return *((TQValueVector<AIElement>*)d->value.ptr);
}
TQValueVector<AIElement>& AIElement::asBlock()
{
if ( d->typ != Block )
*this = AIElement( toBlock() );
return *((TQValueVector<AIElement>*)d->value.ptr);
}
TQByteArray& AIElement::asByteArray()
{
if ( d->typ != ByteArray )
*this = AIElement( toByteArray() );
return *((TQByteArray*)d->value.ptr);
}
/*!
Returns TRUE if the aielement's type can be cast to the requested
type, \p t. Such casting is done automatically when calling the
toInt(), ... or asInt(), ... methods.
The following casts are done automatically:
<ul>
<li> CString => String
<li> Double => String, Int, UInt
<li> Int => String, Double, UInt
<li> String => CString, Int, Uint, Double
<li> UInt => String, Double, Int
</ul>
*/
bool AIElement::canCast( Type t ) const
{
if ( d->typ == t )
return TRUE;
if ( t == Int && ( d->typ == String || d->typ == Double || d->typ == UInt || d->typ == Byte) )
return TRUE;
if ( t == UInt && ( d->typ == String || d->typ == Double || d->typ == Int || d->typ == Byte) )
return TRUE;
if ( t == Double && ( d->typ == String || d->typ == Int || d->typ == UInt || d->typ == Byte) )
return TRUE;
if ( t == CString && d->typ == String )
return TRUE;
if ( t == String && ( d->typ == CString || d->typ == Int || d->typ == UInt || d->typ == Double || d->typ == Byte) )
return TRUE;
return FALSE;
}
/*!
\brief Casts the aielement to the requested type.
If the cast cannot be
done, the aielement is set to the default value of the requested type
(e.g. an empty string if the requested type \p t is
AIElement::String, an empty point array if the requested type \p t is
AIElement::PointArray, etc).
\returns TRUE if the current type of the
aielement was successfully casted; otherwise returns FALSE.
\see canCast()
*/
bool AIElement::cast( Type t )
{
switch ( t ) {
/* case AIElement::List:
asList();
break; */
case AIElement::ElementArray:
asElementArray();
break;
case AIElement::Block:
asBlock();
break;
case AIElement::String:
asString();
break;
case AIElement::Int:
asInt();
break;
case AIElement::UInt:
asUInt();
break;
case AIElement::Double:
asDouble();
break;
case AIElement::CString:
asCString();
break;
case AIElement::Byte:
asByte();
break;
case AIElement::ByteArray:
asByteArray();
break;
default:
case AIElement::Invalid:
(*this) = AIElement();
}
return canCast( t );
}
/*! Compares this AIElement with \a v and returns TRUE if they are
equal; otherwise returns FALSE.
*/
bool AIElement::operator==( const AIElement &v ) const
{
if ( !v.canCast( type() ) )
return FALSE;
switch( d->typ ) {
/* case List:
return v.toList() == toList(); */
case ElementArray:
return v.toElementArray() == toElementArray();
case Block:
return v.toBlock() == toBlock();
case ByteArray:
return v.toByteArray() == toByteArray();
case String:
return v.toString() == toString();
case Operator:
return v.toOperator() == toOperator();
case Reference:
return v.toReference() == toReference();
case CString:
return v.toCString() == toCString();
case Int:
return v.toInt() == toInt();
case UInt:
return v.toUInt() == toUInt();
case Byte:
return v.toByte() == toByte();
case Invalid:
break;
}
return FALSE;
}
/*! Compares this AIElement with \a v and returns TRUE if they are
not equal; otherwise returns FALSE.
*/
bool AIElement::operator!=( const AIElement &v ) const
{
return !( v == *this );
}