kspread

kspread_value.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2003,2004 Ariya Hidayat <ariya@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "kspread_value.h"
00021 
00022 #include <kdebug.h>
00023 
00024 #include <qstring.h>
00025 #include <qtextstream.h>
00026 
00027 #include <float.h>
00028 #include <math.h>
00029 #include <limits.h>
00030 
00031 using namespace KSpread;
00032 
00033 // helper struct for array implementation
00034 // this struct holds one piece of an array of size CHUNK_COLS x CHUNK_ROWS
00035 // or less
00036 struct arrayChunk {
00037   arrayChunk (int c, int r) {
00038     cols = c; rows = r;
00039     ptr = new Value* [c*r];
00040     for (int i = 0; i < c*r; ++i) ptr[i] = 0;
00041   }
00042   
00043   ~arrayChunk () {
00044     if (!ptr) return;
00045     unsigned count = cols * rows;
00046     for (unsigned i = 0; i < count; i++)
00047       delete ptr[i];
00048     delete [] ptr;
00049   }
00050 
00051   arrayChunk( const arrayChunk& ac )
00052   {
00053     operator=( ac );
00054   }
00055   
00056   arrayChunk& operator= ( const arrayChunk& ac )
00057   {
00058     cols = ac.cols; rows = ac.rows;
00059     ptr = new Value* [cols*rows];
00060     unsigned count = cols * rows;
00061     for( unsigned i = 0; i < count; i++ )
00062       if( ac.ptr[i] )
00063         ptr[i] = new Value( *ac.ptr[i] );
00064       else
00065         ptr[i] = 0;
00066     return *this;
00067   }
00068   
00069   Value **ptr;
00070   unsigned cols, rows;
00071 };
00072 
00073 #define CHUNK_COLS 128
00074 #define CHUNK_ROWS 128
00075 // helper class for array implementation
00076 class ValueArray
00077 {
00078 public:
00079   arrayChunk **chunks;
00080   unsigned columns;
00081   unsigned rows;
00082   unsigned chunkCols, chunkRows;
00083   
00084   ValueArray(): chunks(0), columns(0), rows(0), chunkCols(0), chunkRows(0) {};
00085   
00086   ~ValueArray()
00087   { 
00088     clear();
00089   };
00090    
00091   ValueArray( const ValueArray& va )
00092     : chunks(0), columns(0), rows(0), chunkCols(0), chunkRows(0)
00093   {
00094     operator=( va );
00095   }
00096   
00097   ValueArray& operator= ( const ValueArray& va )
00098   {
00099     init( va.columns, va.rows );
00100     unsigned count = chunkCols * chunkRows;
00101     for( unsigned i = 0; i < count; i++ )
00102       if( va.chunks[i] )
00103         chunks[i] = new arrayChunk (*va.chunks[i]);
00104       else
00105         chunks[i] = 0;
00106     return *this;
00107   }
00108    
00109   void clear()
00110   {
00111     int c = columns / CHUNK_COLS;
00112     int r = rows / CHUNK_ROWS;
00113     if (columns % CHUNK_COLS != 0) c++;
00114     if (rows % CHUNK_ROWS != 0) r++;
00115     if( !chunks ) return;
00116     unsigned count = c*r;
00117     if( !count ) return;
00118     for (unsigned i = 0; i < count; i++)
00119       delete chunks[i];
00120     delete [] chunks;
00121     chunks = 0;
00122     columns = rows = chunkCols = chunkRows = 0;
00123   }
00124   
00125   void init( unsigned c, unsigned r )
00126   {
00127     if (chunks) clear();
00128     columns = c; rows = r;
00129     int cc = columns / CHUNK_COLS;
00130     int rr = rows / CHUNK_ROWS;
00131     if (columns % CHUNK_COLS != 0) cc++;
00132     if (rows % CHUNK_ROWS != 0) rr++;
00133     chunkCols = cc;
00134     chunkRows = rr;
00135     unsigned count = cc*rr;
00136     chunks = new arrayChunk* [count];
00137     for( unsigned i = 0; i < count; i++ )
00138       chunks[i] = 0;
00139   }
00140   
00141   Value* at( unsigned c, unsigned r ) const
00142   {
00143     if( !chunks ) return 0;
00144     if( c >= columns ) return 0;
00145     if( r >= rows ) return 0;
00146     
00147     int col = c / CHUNK_COLS;
00148     int row = r / CHUNK_ROWS;
00149     int cpos = c % CHUNK_COLS;
00150     int rpos = r % CHUNK_ROWS;
00151     arrayChunk *chunk = chunks[row * chunkCols + col];
00152     if (!chunk) return 0;
00153     return chunk->ptr[rpos * chunk->cols + cpos];
00154   };
00155   
00156   void set( unsigned c, unsigned r, Value* v )
00157   {
00158     if (!chunks) return;
00159     if( c >= columns ) return;
00160     if( r >= rows ) return;
00161     unsigned col = c / CHUNK_COLS;
00162     unsigned row = r / CHUNK_ROWS;
00163     unsigned cpos = c % CHUNK_COLS;
00164     unsigned rpos = r % CHUNK_ROWS;
00165     arrayChunk *chunk = chunks[row * chunkCols + col];
00166     if (!chunk) {
00167       unsigned cc = (col==chunkCols-1) ? (columns % CHUNK_COLS) : CHUNK_COLS;
00168       unsigned rr = (row==chunkRows-1) ? (rows % CHUNK_ROWS) : CHUNK_ROWS;
00169       chunk = new arrayChunk (cc, rr);
00170       chunks[row * chunkCols + col] = chunk;
00171     }
00172     delete chunk->ptr[rpos * chunk->cols + cpos];
00173     chunk->ptr[rpos * chunk->cols + cpos] = v;
00174   }
00175 
00176   bool operator==( const ValueArray& other ) const
00177   {
00178     if ( columns != other.columns || rows != other.rows )
00179       return false;
00180     for ( unsigned r = 0; r < rows; ++r )
00181       for ( unsigned c = 0; c < columns; ++c ) {
00182         Value* v1 = at( c, r );
00183         Value* v2 = other.at( c, r );
00184         if ( ( v1 && !v2 ) || ( !v1 && v2 ) )
00185             return false;
00186         if ( !( v1 && v2 && *v1 == *v2 ) )
00187             return false;
00188     }
00189     return true;
00190   }
00191 
00192 };
00193 
00194 
00195 // helper class for Value
00196 class KSpread::ValueData
00197 {
00198   public:
00199 
00200     Value::Type type:4;
00201     Value::Format format:4;
00202 
00203     // reference count, at least one when object exists
00204     unsigned int count:24;
00205 
00206     union
00207     {
00208       bool b;
00209       long i;
00210       double f;
00211       QString* ps;
00212       ValueArray* pa;
00213     };
00214 
00215     // create empty data
00216     ValueData(): type( Value::Empty ),
00217       format (Value::fmt_None), count( 1 ), ps( 0 ) { };
00218 
00219     // destroys data
00220     ~ValueData(){ if( this == s_null ) s_null = 0;
00221        if( type == Value::Array ) delete pa;
00222        if( type == Value::String ) delete ps;
00223        if( type == Value::Error ) delete ps;
00224      }
00225 
00226     // static empty data to be shared
00227     static ValueData* null()
00228       { if( !s_null) s_null = new ValueData; else s_null->ref(); return s_null; }
00229 
00230     // increase reference count
00231     void ref() { count++; }
00232 
00233     // decrease reference count
00234     void unref()
00235       {  --count; if( !count ) delete this; }
00236 
00237     // true if it's null (which is shared)
00238     bool isNull(){ return this == s_null; }
00239 
00241     void setFormatByType ();
00242 
00243   private:
00244 
00245     static ValueData* s_null;
00246 };
00247 
00248 void KSpread::ValueData::setFormatByType ()
00249 {
00250   switch (type) {
00251     case Value::Empty:
00252       format = Value::fmt_None;
00253     break;
00254     case Value::Boolean:
00255       format = Value::fmt_Boolean;
00256     break;
00257     case Value::Integer:
00258       format = Value::fmt_Number;
00259     break;
00260     case Value::Float:
00261       format = Value::fmt_Number;
00262     break;
00263     case Value::String:
00264       format = Value::fmt_String;
00265     break;
00266     case Value::Array:
00267       format = Value::fmt_None;
00268     break;
00269     case Value::CellRange:
00270       format = Value::fmt_None;
00271     break;
00272     case Value::Error:
00273       format = Value::fmt_String;
00274     break;
00275   };
00276 }
00277 
00278 // to be shared between all empty value
00279 ValueData* ValueData::s_null = 0;
00280 
00281 // static things
00282 Value ks_value_empty;
00283 Value ks_error_div0;
00284 Value ks_error_na;
00285 Value ks_error_name;
00286 Value ks_error_null;
00287 Value ks_error_num;
00288 Value ks_error_ref;
00289 Value ks_error_value;
00290 
00291 // create an empty value
00292 Value::Value()
00293 {
00294   d = ValueData::null();
00295 }
00296 
00297 // destructor
00298 Value::~Value()
00299 {
00300   d->unref();
00301 }
00302 
00303 // create value of certain type
00304 Value::Value( Value::Type _type )
00305 {
00306   d = new ValueData;
00307   d->type = _type;
00308   d->setFormatByType ();
00309 }
00310 
00311 // copy constructor
00312 Value::Value( const Value& _value )
00313 {
00314   d = ValueData::null();
00315   assign( _value );
00316 }
00317 
00318 // assignment operator
00319 Value& Value::operator=( const Value& _value )
00320 {
00321   return assign( _value );
00322 }
00323 
00324 // comparison operator - returns true only if strictly identical, unlike equal()/compare()
00325 bool Value::operator==( const Value& v ) const
00326 {
00327   const ValueData* n = v.d;
00328   if ( (uint)d->type != n->type )
00329     return false;
00330   switch( d->type )
00331   {
00332     case Empty: return true;
00333     case Boolean: return n->b == d->b;
00334     case Integer: return n->i == d->i;
00335     case Float:   return compare( n->f, d->f ) == 0;
00336     case String:  return *n->ps == *d->ps;
00337     case Array:   return *n->pa == *d->pa;
00338     case Error:   return *n->ps == *d->ps;
00339     default: break;
00340   }
00341   kdWarning() << "Unhandled type in Value::operator==: " << d->type << endl;
00342   return false;
00343 }
00344 
00345 // create a boolean value
00346 Value::Value( bool b )
00347 {
00348   d = ValueData::null();
00349   setValue( b );
00350 }
00351 
00352 // create an integer value
00353 Value::Value( long i )
00354 {
00355   d = ValueData::null();
00356   setValue ( i );
00357 }
00358 
00359 // create an integer value
00360 Value::Value( int i )
00361 {
00362   d = ValueData::null();
00363   setValue ( i );
00364 }
00365 
00366 // create a floating-point value
00367 Value::Value( double f )
00368 {
00369   d = ValueData::null();
00370   setValue( f );
00371 }
00372 
00373 // create a string value
00374 Value::Value( const QString& s )
00375 {
00376   d = ValueData::null();
00377   setValue( s );
00378 }
00379 
00380 // create a string value
00381 Value::Value (const char *s)
00382 {
00383   d = ValueData::null();
00384   setValue (QString (s));
00385 }
00386 
00387 // create a floating-point value from date/time
00388 Value::Value( const QDateTime& dt )
00389 {
00390   d = ValueData::null();
00391   setValue( dt );
00392 }
00393 
00394 // create a floating-point value from time
00395 Value::Value( const QTime& dt )
00396 {
00397   d = ValueData::null();
00398   setValue( dt );
00399 }
00400 
00401 // create a floating-point value from date
00402 Value::Value( const QDate& dt )
00403 {
00404   d = ValueData::null();
00405   setValue( dt );
00406 }
00407 
00408 // create an array value
00409 Value::Value( unsigned columns, unsigned rows )
00410 {
00411   d = new ValueData;
00412   d->type = Array;
00413   d->format = fmt_None;
00414   d->pa = new ValueArray;
00415   d->pa->init( columns, rows );
00416 }
00417 
00418 // assign value from other
00419 // shallow copy: only copy the data pointer
00420 Value& Value::assign( const Value& _value )
00421 {
00422   d->unref();
00423   d = _value.d;
00424   d->ref();
00425   return *this;
00426 }
00427 
00428 // return type of the value
00429 Value::Type Value::type() const
00430 {
00431   return d ? d->type : Empty;
00432 }
00433 
00434 // set the value to boolean
00435 void Value::setValue( bool b )
00436 {
00437   detach();
00438   d->type = Boolean;
00439   d->b = b;
00440   d->format = fmt_Boolean;
00441 }
00442 
00443 // get the value as boolean
00444 bool Value::asBoolean() const
00445 {
00446   bool result = false;
00447 
00448   if( type() == Value::Boolean )
00449     result = d->b;
00450 
00451   return result;
00452 }
00453 
00454 // set the value to integer
00455 void Value::setValue( long i )
00456 {
00457   detach();
00458   d->type = Integer;
00459   d->i = i;
00460   d->format = fmt_Number;
00461 }
00462 
00463 // set the value to integer
00464 void Value::setValue( int i )
00465 {
00466   detach();
00467   d->type = Integer;
00468   d->i = static_cast<long>( i );
00469   d->format = fmt_Number;
00470 }
00471 
00472 // get the value as integer
00473 long Value::asInteger() const
00474 {
00475   long result = 0;
00476 
00477   if( type() == Value::Integer )
00478     result = d->i;
00479 
00480   if( type() == Value::Float )
00481     result = static_cast<long>(d->f);
00482 
00483   return result;
00484 }
00485 
00486 void Value::setValue( const Value& v )
00487 {
00488   assign( v );
00489 }
00490 
00491 // set the value as floating-point
00492 void Value::setValue( double f )
00493 {
00494   detach();
00495   d->type = Float;
00496   d->f = f;
00497   d->format = fmt_Number;
00498 }
00499 
00500 // get the value as floating-point
00501 double Value::asFloat() const
00502 {
00503   double result = 0.0;
00504 
00505   if( type() == Value::Float )
00506     result = d->f;
00507 
00508   if( type() == Value::Integer )
00509     result = static_cast<double>(d->i);
00510 
00511   return result;
00512 }
00513 
00514 // set the value as string
00515 void Value::setValue( const QString& s )
00516 {
00517   detach();
00518   d->type = String;
00519   d->ps = new QString( s );
00520   d->format = fmt_String;
00521 }
00522 
00523 // get the value as string
00524 QString Value::asString() const
00525 {
00526   QString result;
00527 
00528   if( type() == Value::String )
00529   if( d->ps )
00530     result = QString( *d->ps );
00531 
00532   return result;
00533 }
00534 
00535 // set error message
00536 void Value::setError( const QString& msg )
00537 {
00538   detach();
00539   d->type = Error;
00540   d->ps = new QString( msg );
00541 }
00542 
00543 // get error message
00544 QString Value::errorMessage() const
00545 {
00546   QString result;
00547 
00548   if( type() == Value::Error )
00549   if( d->ps )
00550     result = QString( *d->ps );
00551 
00552   return result;
00553 }
00554 
00555 // set the value as date/time
00556 // NOTE: date/time is stored as serial number
00557 // Day 61 means 1st of March, 1900
00558 void Value::setValue( const QDateTime& dt )
00559 {
00560   // reference is 31 Dec, 1899 midnight
00561   QDate refDate( 1899, 12, 31 );
00562   QTime refTime( 0, 0 );
00563 
00564   int i = refDate.daysTo( dt.date() ) + 1;
00565   i += refTime.secsTo( dt.time() ) / 86400;
00566 
00567   setValue( i );
00568   d->format = fmt_DateTime;
00569 }
00570 
00571 void Value::setValue( const QTime& time )
00572 {
00573   // reference time is midnight
00574   QTime refTime( 0, 0 );
00575   int i = refTime.msecsTo( time ) /* / 86400000 */;
00576 
00577   setValue( i );
00578   d->format = fmt_Time;
00579 }
00580 
00581 void Value::setValue( const QDate& date )
00582 {
00583   // reference date is 31 Dec, 1899
00584   QDate refDate = QDate( 1899, 12, 31 );
00585   int i = refDate.daysTo( date ) + 1;
00586 
00587   setValue( i );
00588   d->format = fmt_Date;
00589 }
00590 
00591 // get the value as date/time
00592 QDateTime Value::asDateTime() const
00593 {
00594   return QDateTime( asDate(), asTime() );
00595 }
00596 
00597 // get the value as date
00598 QDate Value::asDate() const
00599 {
00600   QDate dt( 1899, 12, 30 );
00601 
00602   int i = asInteger();
00603   dt = dt.addDays( i );
00604   
00605   return dt;
00606 }
00607 
00608 // get the value as time
00609 QTime Value::asTime() const
00610 {
00611   QTime dt;
00612   
00613   int i = asInteger();
00614   dt = dt.addMSecs(i) /*( f * 86400 * 1000  )*/;
00615   
00616   return dt;
00617 }
00618 
00619 Value::Format Value::format() const
00620 {
00621   return d ? d->format : fmt_None;
00622 }
00623 
00624 void Value::setFormat (Value::Format fmt)
00625 {
00626   detach();
00627   d->format = fmt;
00628 }
00629 
00630 Value Value::element( unsigned column, unsigned row ) const
00631 {
00632   if( (uint)d->type != Array ) return *this;
00633   if( !d->pa ) return *this;
00634   Value* v = d->pa->at (column % columns(), row % rows());
00635   return v ? Value( *v ) : empty();
00636 }
00637 
00638 void Value::setElement( unsigned column, unsigned row, const Value& v )
00639 {
00640   if( (uint)d->type != Array ) return;
00641   if( !d->pa ) return;
00642   detach();
00643   d->pa->set( column, row, new Value( v ) );
00644 }
00645 
00646 unsigned Value::columns() const
00647 {
00648   if( (uint)d->type != Array ) return 1;
00649   if( !d->pa ) return 1;
00650   return d->pa->columns;
00651 }
00652 
00653 unsigned Value::rows() const
00654 {
00655   if( (uint)d->type != Array ) return 1;
00656   if( !d->pa ) return 1;
00657   return d->pa->rows;
00658 }
00659 
00660 // reference to empty value
00661 const Value& Value::empty()
00662 {
00663   return ks_value_empty;
00664 }
00665 
00666 // reference to #DIV/0! error
00667 const Value& Value::errorDIV0()
00668 {
00669   if( !ks_error_div0.isError() )
00670     ks_error_div0.setError( "#DIV/0!" );
00671   return ks_error_div0;
00672 }
00673 
00674 // reference to #N/A error
00675 const Value& Value::errorNA()
00676 {
00677   if( !ks_error_na.isError() )
00678     ks_error_na.setError( "#N/A" );
00679   return ks_error_na;
00680 }
00681 
00682 // reference to #NAME? error
00683 const Value& Value::errorNAME()
00684 {
00685   if( !ks_error_name.isError() )
00686     ks_error_name.setError( "#NAME?" );
00687   return ks_error_name;
00688 }
00689 
00690 // reference to #NUM! error
00691 const Value& Value::errorNUM()
00692 {
00693   if( !ks_error_num.isError() )
00694     ks_error_num.setError( "#NUM!" );
00695   return ks_error_num;
00696 }
00697 
00698 // reference to #NULL! error
00699 const Value& Value::errorNULL()
00700 {
00701   if( !ks_error_null.isError() )
00702     ks_error_null.setError( "#NULL!" );
00703   return ks_error_null;
00704 }
00705 
00706 // reference to #REF! error
00707 const Value& Value::errorREF()
00708 {
00709   if( !ks_error_ref.isError() )
00710     ks_error_ref.setError( "#REF!" );
00711   return ks_error_ref;
00712 }
00713 
00714 // reference to #VALUE! error
00715 const Value& Value::errorVALUE()
00716 {
00717   if( !ks_error_value.isError() )
00718     ks_error_value.setError( "#VALUE!" );
00719   return ks_error_value;
00720 }
00721 
00722 // detach, create deep copy of ValueData
00723 void Value::detach()
00724 {
00725   if( d->isNull() || ( d->count > 1 ) )
00726   {
00727     ValueData* n;
00728     n = new ValueData;
00729 
00730     n->type = d->type;
00731     switch( n->type )
00732     {
00733     case Empty: break;
00734     case Boolean: n->b = d->b; break;
00735     case Integer: n->i = d->i; break;
00736     case Float:   n->f = d->f; break;
00737     case String:  n->ps = new QString( *d->ps ); break;
00738     case Array:   n->pa = new ValueArray; *n->pa = (*d->pa); break;
00739     case Error:   n->ps = new QString( *d->ps ); break;
00740     default: break;
00741     }
00742 
00743     d->unref();
00744     d = n;
00745   }
00746 }
00747 
00748 int Value::compare( double v1, double v2 )
00749 {
00750   double v3 = v1 - v2;
00751   if( v3 > DBL_EPSILON ) return 1;
00752   if( v3 < -DBL_EPSILON ) return -1;
00753   return 0;
00754 }
00755 
00756 bool Value::isZero( double v )
00757 {
00758   return fabs( v ) < DBL_EPSILON;
00759 }
00760 
00761 bool Value::isZero() const
00762 {
00763   if( !isNumber() ) return false;
00764   return isZero( asFloat() );
00765 }
00766 
00767 bool Value::allowComparison( const Value& v ) const
00768 {
00769   Value::Type t1 = d->type;
00770   Value::Type t2 = v.type();
00771   
00772   if( ( t1 == Empty ) && ( t2 == Empty ) ) return true;
00773   if( ( t1 == Empty ) && ( t2 == String ) ) return true;
00774   
00775   if( ( t1 == Boolean ) && ( t2 == Boolean ) ) return true;
00776   if( ( t1 == Boolean ) && ( t2 == Integer ) ) return true;
00777   if( ( t1 == Boolean ) && ( t2 == Float ) ) return true;
00778   if( ( t1 == Boolean ) && ( t2 == String ) ) return true;
00779     
00780   if( ( t1 == Integer ) && ( t2 == Boolean ) ) return true;
00781   if( ( t1 == Integer ) && ( t2 == Integer ) ) return true;
00782   if( ( t1 == Integer ) && ( t2 == Float ) ) return true;
00783   if( ( t1 == Integer ) && ( t2 == String ) ) return true;
00784   
00785   if( ( t1 == Float ) && ( t2 == Boolean ) ) return true;
00786   if( ( t1 == Float ) && ( t2 == Integer ) ) return true;
00787   if( ( t1 == Float ) && ( t2 == Float ) ) return true;
00788   if( ( t1 == Float ) && ( t2 == String ) ) return true;
00789   
00790   if( ( t1 == String ) && ( t2 == Empty ) ) return true;
00791   if( ( t1 == String ) && ( t2 == Boolean ) ) return true;
00792   if( ( t1 == String ) && ( t2 == Integer ) ) return true;
00793   if( ( t1 == String ) && ( t2 == Float ) ) return true;
00794   if( ( t1 == String ) && ( t2 == String ) ) return true;
00795   
00796   // errors can be compared too ...
00797   if ((t1 == Error) && (t2 == Error)) return true;
00798   
00799   return false;
00800 }
00801 
00802 // compare values. looks strange in order to be compatible with Excel
00803 int Value::compare( const Value& v ) const 
00804 {
00805   Value::Type t1 = d->type;
00806   Value::Type t2 = v.type();
00807   
00808   // errors always less than everything else
00809   if( ( t1 == Error ) && ( t2 != Error ) )
00810     return -1;
00811   if( ( t2 == Error ) && ( t1 != Error ) )
00812     return 1;
00813     
00814   // comparing errors only yields 0 if they are the same  
00815   if( ( t1 == Error ) && ( t2 == Error ) )
00816     return errorMessage() != v.errorMessage();
00817   
00818   // empty == empty
00819   if( ( t1 == Empty ) && ( t2 == Empty ) )
00820     return 0;
00821   
00822   // empty value is always less than string
00823   // (except when the string is empty)
00824   if( ( t1 == Empty ) && ( t2 == String ) )
00825     return( v.asString().isEmpty() ) ? 0 : -1;
00826     
00827   // boolean vs boolean
00828   if( ( t1 == Boolean ) && ( t2 == Boolean ) )
00829   {
00830     bool p = asBoolean();
00831     bool q = v.asBoolean();
00832     if( p ) return q ? 0 : 1;
00833     else return q ? -1 : 0;
00834   }
00835   
00836   // boolean is always greater than integer
00837   if( ( t1 == Boolean ) && ( t2 == Integer ) )
00838     return 1;
00839   
00840   // boolean is always greater than float
00841   if( ( t1 == Boolean ) && ( t2 == Float ) )
00842     return 1;
00843   
00844   // boolean is always greater than string
00845   if( ( t1 == Boolean ) && ( t2 == String ) )
00846     return 1;
00847   
00848   // integer is always less than boolean
00849   if( ( t1 == Integer ) && ( t2 == Boolean ) )
00850     return -1;
00851     
00852   // integer vs integer
00853   if( ( t1 == Integer ) && ( t2 == Integer ) )
00854   {
00855     long p = asInteger();
00856     long q = v.asInteger();
00857     return ( p == q ) ? 0 : ( p < q ) ? -1 : 1;
00858   }  
00859   
00860   // integer vs float
00861   if( ( t1 == Integer ) && ( t2 == Float ) )
00862     return compare( asFloat(), v.asFloat() );
00863   
00864   // integer is always less than string
00865   if( ( t1 == Integer ) && ( t2 == String ) )
00866     return -1;
00867   
00868   // float is always less than boolean
00869   if( ( t1 == Float ) && ( t2 == Boolean ) )
00870     return -1;
00871   
00872   // float vs integer
00873   if( ( t1 == Float ) && ( t2 == Integer ) )
00874     return compare( asFloat(), v.asFloat() );
00875   
00876   // float vs float
00877   if( ( t1 == Float ) && ( t2 == Float ) )
00878     return compare( asFloat(), v.asFloat() );
00879   
00880   // float is always less than string
00881   if( ( t1 == Float ) && ( t2 == String ) )
00882     return -1;
00883 
00884   // string is always greater than empty value
00885   // (except when the string is empty)
00886   if( ( t1 == String ) && ( t2 == Empty ) )
00887     return( asString().isEmpty() ) ? 0 : 1;
00888   
00889   // string is always less than boolean
00890   if( ( t1 == String ) && ( t2 == Boolean ) )
00891     return -1;
00892   
00893   // string is always greater than integer
00894   if( ( t1 == String ) && ( t2 == Integer ) )
00895     return 1;
00896     
00897   // string is always greater than float
00898   if( ( t1 == String ) && ( t2 == Float ) )
00899     return 1;
00900 
00901   // The-Real-String comparison
00902   if( ( t1 == String ) && ( t2 == String ) )
00903     return asString().compare( v.asString() );
00904 
00905   // Undefined, actually allowComparison would return false
00906   return 0;
00907 }
00908 
00909 bool Value::equal( const Value& v ) const
00910 {
00911   if (!allowComparison (v)) return false;
00912   return compare( v ) == 0;
00913 }
00914 
00915 bool Value::less( const Value& v ) const
00916 {
00917   if (!allowComparison (v)) return false;
00918   return compare( v ) < 0;
00919 }
00920 
00921 bool Value::greater( const Value& v ) const
00922 {
00923   if (!allowComparison (v)) return false;
00924   return compare( v ) > 0;
00925 }
00926 
00927 QTextStream& operator<<( QTextStream& ts, Value::Type type ) 
00928 {
00929   switch( type )
00930   {
00931     case Value::Empty:   ts << "Empty"; break;
00932     case Value::Boolean: ts << "Boolean"; break;
00933     case Value::Integer: ts << "Integer"; break;
00934     case Value::Float:   ts << "Float"; break;
00935     case Value::String:  ts << "String"; break;
00936     case Value::Array:   ts << "Array"; break;
00937     case Value::Error:   ts << "Error"; break;
00938     default: ts << "Unknown!"; break;
00939   };
00940   return ts;
00941 }
00942 
00943 QTextStream& operator<<( QTextStream& ts, Value value ) 
00944 {
00945   ts << value.type();
00946   switch( value.type() )
00947   {
00948     case Value::Empty:   break;
00949     
00950     case Value::Boolean: 
00951       ts << ": "; 
00952       if (value.asBoolean()) ts << "TRUE"; 
00953       else ts << "FALSE"; break;
00954       
00955     case Value::Integer: 
00956       ts << ": " << value.asInteger(); break;
00957       
00958     case Value::Float:   
00959       ts << ": " << value.asFloat(); break;
00960       
00961     case Value::String:  
00962       ts << ": " << value.asString(); break;
00963       
00964     case Value::Error: 
00965       ts << "(" << value.errorMessage() << ")"; break;
00966     
00967     default: break;
00968   }
00969   return ts;
00970 }
KDE Home | KDE Accessibility Home | Description of Access Keys