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<int>(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   d->format = fmt;
00627 }
00628 
00629 Value Value::element( unsigned column, unsigned row ) const
00630 {
00631   if( (uint)d->type != Array ) return *this;
00632   if( !d->pa ) return *this;
00633   Value* v = d->pa->at (column % columns(), row % rows());
00634   return v ? Value( *v ) : empty();
00635 }
00636 
00637 void Value::setElement( unsigned column, unsigned row, const Value& v )
00638 {
00639   if( (uint)d->type != Array ) return;
00640   if( !d->pa ) return;
00641   detach();
00642   d->pa->set( column, row, new Value( v ) );
00643 }
00644 
00645 unsigned Value::columns() const
00646 {
00647   if( (uint)d->type != Array ) return 1;
00648   if( !d->pa ) return 1;
00649   return d->pa->columns;
00650 }
00651 
00652 unsigned Value::rows() const
00653 {
00654   if( (uint)d->type != Array ) return 1;
00655   if( !d->pa ) return 1;
00656   return d->pa->rows;
00657 }
00658 
00659 // reference to empty value
00660 const Value& Value::empty()
00661 {
00662   return ks_value_empty;
00663 }
00664 
00665 // reference to #DIV/0! error
00666 const Value& Value::errorDIV0()
00667 {
00668   if( !ks_error_div0.isError() )
00669     ks_error_div0.setError( "#DIV/0!" );
00670   return ks_error_div0;
00671 }
00672 
00673 // reference to #N/A error
00674 const Value& Value::errorNA()
00675 {
00676   if( !ks_error_na.isError() )
00677     ks_error_na.setError( "#N/A" );
00678   return ks_error_na;
00679 }
00680 
00681 // reference to #NAME? error
00682 const Value& Value::errorNAME()
00683 {
00684   if( !ks_error_name.isError() )
00685     ks_error_name.setError( "#NAME?" );
00686   return ks_error_name;
00687 }
00688 
00689 // reference to #NUM! error
00690 const Value& Value::errorNUM()
00691 {
00692   if( !ks_error_num.isError() )
00693     ks_error_num.setError( "#NUM!" );
00694   return ks_error_num;
00695 }
00696 
00697 // reference to #NULL! error
00698 const Value& Value::errorNULL()
00699 {
00700   if( !ks_error_null.isError() )
00701     ks_error_null.setError( "#NULL!" );
00702   return ks_error_null;
00703 }
00704 
00705 // reference to #REF! error
00706 const Value& Value::errorREF()
00707 {
00708   if( !ks_error_ref.isError() )
00709     ks_error_ref.setError( "#REF!" );
00710   return ks_error_ref;
00711 }
00712 
00713 // reference to #VALUE! error
00714 const Value& Value::errorVALUE()
00715 {
00716   if( !ks_error_value.isError() )
00717     ks_error_value.setError( "#VALUE!" );
00718   return ks_error_value;
00719 }
00720 
00721 // detach, create deep copy of ValueData
00722 void Value::detach()
00723 {
00724   if( d->isNull() || ( d->count > 1 ) )
00725   {
00726     ValueData* n;
00727     n = new ValueData;
00728 
00729     n->type = d->type;
00730     switch( n->type )
00731     {
00732     case Empty: break;
00733     case Boolean: n->b = d->b; break;
00734     case Integer: n->i = d->i; break;
00735     case Float:   n->f = d->f; break;
00736     case String:  n->ps = new QString( *d->ps ); break;
00737     case Array:   n->pa = new ValueArray; *n->pa = (*d->pa); break;
00738     case Error:   n->ps = new QString( *d->ps ); break;
00739     default: break;
00740     }
00741 
00742     d->unref();
00743     d = n;
00744   }
00745 }
00746 
00747 int Value::compare( double v1, double v2 )
00748 {
00749   double v3 = v1 - v2;
00750   if( v3 > DBL_EPSILON ) return 1;
00751   if( v3 < -DBL_EPSILON ) return -1;
00752   return 0;
00753 }
00754 
00755 bool Value::isZero( double v )
00756 {
00757   return fabs( v ) < DBL_EPSILON;
00758 }
00759 
00760 bool Value::isZero() const
00761 {
00762   if( !isNumber() ) return false;
00763   return isZero( asFloat() );
00764 }
00765 
00766 bool Value::allowComparison( const Value& v ) const
00767 {
00768   Value::Type t1 = d->type;
00769   Value::Type t2 = v.type();
00770   
00771   if( ( t1 == Empty ) && ( t2 == Empty ) ) return true;
00772   if( ( t1 == Empty ) && ( t2 == String ) ) return true;
00773   
00774   if( ( t1 == Boolean ) && ( t2 == Boolean ) ) return true;
00775   if( ( t1 == Boolean ) && ( t2 == Integer ) ) return true;
00776   if( ( t1 == Boolean ) && ( t2 == Float ) ) return true;
00777   if( ( t1 == Boolean ) && ( t2 == String ) ) return true;
00778     
00779   if( ( t1 == Integer ) && ( t2 == Boolean ) ) return true;
00780   if( ( t1 == Integer ) && ( t2 == Integer ) ) return true;
00781   if( ( t1 == Integer ) && ( t2 == Float ) ) return true;
00782   if( ( t1 == Integer ) && ( t2 == String ) ) return true;
00783   
00784   if( ( t1 == Float ) && ( t2 == Boolean ) ) return true;
00785   if( ( t1 == Float ) && ( t2 == Integer ) ) return true;
00786   if( ( t1 == Float ) && ( t2 == Float ) ) return true;
00787   if( ( t1 == Float ) && ( t2 == String ) ) return true;
00788   
00789   if( ( t1 == String ) && ( t2 == Empty ) ) return true;
00790   if( ( t1 == String ) && ( t2 == Boolean ) ) return true;
00791   if( ( t1 == String ) && ( t2 == Integer ) ) return true;
00792   if( ( t1 == String ) && ( t2 == Float ) ) return true;
00793   if( ( t1 == String ) && ( t2 == String ) ) return true;
00794   
00795   // errors can be compared too ...
00796   if ((t1 == Error) && (t2 == Error)) return true;
00797   
00798   return false;
00799 }
00800 
00801 // compare values. looks strange in order to be compatible with Excel
00802 int Value::compare( const Value& v ) const 
00803 {
00804   Value::Type t1 = d->type;
00805   Value::Type t2 = v.type();
00806   
00807   // errors always less than everything else
00808   if( ( t1 == Error ) && ( t2 != Error ) )
00809     return -1;
00810   if( ( t2 == Error ) && ( t1 != Error ) )
00811     return 1;
00812     
00813   // comparing errors only yields 0 if they are the same  
00814   if( ( t1 == Error ) && ( t2 == Error ) )
00815     return errorMessage() != v.errorMessage();
00816   
00817   // empty == empty
00818   if( ( t1 == Empty ) && ( t2 == Empty ) )
00819     return 0;
00820   
00821   // empty value is always less than string
00822   // (except when the string is empty)
00823   if( ( t1 == Empty ) && ( t2 == String ) )
00824     return( v.asString().isEmpty() ) ? 0 : -1;
00825     
00826   // boolean vs boolean
00827   if( ( t1 == Boolean ) && ( t2 == Boolean ) )
00828   {
00829     bool p = asBoolean();
00830     bool q = v.asBoolean();
00831     if( p ) return q ? 0 : 1;
00832     else return q ? -1 : 0;
00833   }
00834   
00835   // boolean is always greater than integer
00836   if( ( t1 == Boolean ) && ( t2 == Integer ) )
00837     return 1;
00838   
00839   // boolean is always greater than float
00840   if( ( t1 == Boolean ) && ( t2 == Float ) )
00841     return 1;
00842   
00843   // boolean is always greater than string
00844   if( ( t1 == Boolean ) && ( t2 == String ) )
00845     return 1;
00846   
00847   // integer is always less than boolean
00848   if( ( t1 == Integer ) && ( t2 == Boolean ) )
00849     return -1;
00850     
00851   // integer vs integer
00852   if( ( t1 == Integer ) && ( t2 == Integer ) )
00853   {
00854     long p = asInteger();
00855     long q = v.asInteger();   
00856     return ( p == q ) ? 0 : ( p < q ) ? -1 : 1;
00857   }  
00858   
00859   // integer vs float
00860   if( ( t1 == Integer ) && ( t2 == Float ) )
00861     return compare( asFloat(), v.asFloat() );
00862   
00863   // integer is always less than string
00864   if( ( t1 == Integer ) && ( t2 == String ) )
00865     return -1;
00866   
00867   // float is always less than boolean
00868   if( ( t1 == Float ) && ( t2 == Boolean ) )
00869     return -1;
00870   
00871   // float vs integer
00872   if( ( t1 == Float ) && ( t2 == Integer ) )
00873     return compare( asFloat(), v.asFloat() );
00874   
00875   // float vs float
00876   if( ( t1 == Float ) && ( t2 == Float ) )
00877     return compare( asFloat(), v.asFloat() );
00878   
00879   // float is always less than string
00880   if( ( t1 == Float ) && ( t2 == String ) )
00881     return -1;
00882 
00883   // string is always greater than empty value
00884   // (except when the string is empty)
00885   if( ( t1 == String ) && ( t2 == Empty ) )
00886     return( asString().isEmpty() ) ? 0 : 1;
00887   
00888   // string is always less than boolean
00889   if( ( t1 == String ) && ( t2 == Boolean ) )
00890     return -1;
00891   
00892   // string is always greater than integer
00893   if( ( t1 == String ) && ( t2 == Integer ) )
00894     return 1;
00895     
00896   // string is always greater than float
00897   if( ( t1 == String ) && ( t2 == Float ) )
00898     return 1;
00899 
00900   // The-Real-String comparison
00901   if( ( t1 == String ) && ( t2 == String ) )
00902     return asString().compare( v.asString() );
00903 
00904   // Undefined, actually allowComparison would return false
00905   return 0;
00906 }
00907 
00908 bool Value::equal( const Value& v ) const
00909 {
00910   if (!allowComparison (v)) return false;
00911   return compare( v ) == 0;
00912 }
00913 
00914 bool Value::less( const Value& v ) const
00915 {
00916   if (!allowComparison (v)) return false;
00917   return compare( v ) < 0;
00918 }
00919 
00920 bool Value::greater( const Value& v ) const
00921 {
00922   if (!allowComparison (v)) return false;
00923   return compare( v ) > 0;
00924 }
00925 
00926 QTextStream& operator<<( QTextStream& ts, Value::Type type ) 
00927 {
00928   switch( type )
00929   {
00930     case Value::Empty:   ts << "Empty"; break;
00931     case Value::Boolean: ts << "Boolean"; break;
00932     case Value::Integer: ts << "Integer"; break;
00933     case Value::Float:   ts << "Float"; break;
00934     case Value::String:  ts << "String"; break;
00935     case Value::Array:   ts << "Array"; break;
00936     case Value::Error:   ts << "Error"; break;
00937     default: ts << "Unknown!"; break;
00938   };
00939   return ts;
00940 }
00941 
00942 QTextStream& operator<<( QTextStream& ts, Value value ) 
00943 {
00944   ts << value.type();
00945   switch( value.type() )
00946   {
00947     case Value::Empty:   break;
00948     
00949     case Value::Boolean: 
00950       ts << ": "; 
00951       if (value.asBoolean()) ts << "TRUE"; 
00952       else ts << "FALSE"; break;
00953       
00954     case Value::Integer: 
00955       ts << ": " << value.asInteger(); break;
00956       
00957     case Value::Float:   
00958       ts << ": " << value.asFloat(); break;
00959       
00960     case Value::String:  
00961       ts << ": " << value.asString(); break;
00962       
00963     case Value::Error: 
00964       ts << "(" << value.errorMessage() << ")"; break;
00965     
00966     default: break;
00967   }
00968   return ts;
00969 }
KDE Home | KDE Accessibility Home | Description of Access Keys