20#include "kspread_value.h"
25#include <tqtextstream.h>
37 arrayChunk (
int c,
int r) {
39 ptr =
new Value* [c*r];
40 for (
int i = 0; i < c*r; ++i) ptr[i] = 0;
45 unsigned count = cols * rows;
46 for (
unsigned i = 0; i < count; i++)
51 arrayChunk(
const arrayChunk& ac )
56 arrayChunk& operator= (
const arrayChunk& ac )
58 cols = ac.cols; rows = ac.rows;
59 ptr =
new Value* [cols*rows];
60 unsigned count = cols * rows;
61 for(
unsigned i = 0; i < count; i++ )
63 ptr[i] =
new Value( *ac.ptr[i] );
82 unsigned chunkCols, chunkRows;
84 ValueArray(): chunks(0), columns(0), rows(0), chunkCols(0), chunkRows(0) {};
91 ValueArray(
const ValueArray& va )
92 : chunks(0), columns(0), rows(0), chunkCols(0), chunkRows(0)
97 ValueArray& operator= (
const ValueArray& va )
99 init( va.columns, va.rows );
100 unsigned count = chunkCols * chunkRows;
101 for(
unsigned i = 0; i < count; i++ )
103 chunks[i] =
new arrayChunk (*va.chunks[i]);
111 int c = columns / CHUNK_COLS;
112 int r = rows / CHUNK_ROWS;
113 if (columns % CHUNK_COLS != 0) c++;
114 if (rows % CHUNK_ROWS != 0) r++;
115 if( !chunks )
return;
116 unsigned count = c*r;
118 for (
unsigned i = 0; i < count; i++)
122 columns = rows = chunkCols = chunkRows = 0;
125 void init(
unsigned c,
unsigned r )
128 columns = c; rows = r;
129 int cc = columns / CHUNK_COLS;
130 int rr = rows / CHUNK_ROWS;
131 if (columns % CHUNK_COLS != 0) cc++;
132 if (rows % CHUNK_ROWS != 0) rr++;
135 unsigned count = cc*rr;
136 chunks =
new arrayChunk* [count];
137 for(
unsigned i = 0; i < count; i++ )
141 Value* at(
unsigned c,
unsigned r )
const
143 if( !chunks )
return 0;
144 if( c >= columns )
return 0;
145 if( r >= rows )
return 0;
147 int col = c / CHUNK_COLS;
148 int row = r / CHUNK_ROWS;
149 int cpos = c % CHUNK_COLS;
150 int rpos = r % CHUNK_ROWS;
151 arrayChunk *chunk = chunks[row * chunkCols + col];
152 if (!chunk)
return 0;
153 return chunk->ptr[rpos * chunk->cols + cpos];
156 void set(
unsigned c,
unsigned r, Value* v )
159 if( c >= columns )
return;
160 if( r >= rows )
return;
161 unsigned col = c / CHUNK_COLS;
162 unsigned row = r / CHUNK_ROWS;
163 unsigned cpos = c % CHUNK_COLS;
164 unsigned rpos = r % CHUNK_ROWS;
165 arrayChunk *chunk = chunks[row * chunkCols + col];
167 unsigned cc = (col==chunkCols-1) ? (columns % CHUNK_COLS) : CHUNK_COLS;
168 unsigned rr = (row==chunkRows-1) ? (rows % CHUNK_ROWS) : CHUNK_ROWS;
169 chunk =
new arrayChunk (cc, rr);
170 chunks[row * chunkCols + col] = chunk;
172 delete chunk->ptr[rpos * chunk->cols + cpos];
173 chunk->ptr[rpos * chunk->cols + cpos] = v;
176 bool operator==(
const ValueArray& other )
const
178 if ( columns != other.columns || rows != other.rows )
180 for (
unsigned r = 0; r < rows; ++r )
181 for (
unsigned c = 0; c < columns; ++c ) {
182 Value* v1 = at( c, r );
183 Value* v2 = other.at( c, r );
184 if ( ( v1 && !v2 ) || ( !v1 && v2 ) )
186 if ( !( v1 && v2 && *v1 == *v2 ) )
196class KSpread::ValueData
201 Value::Format format:4;
204 unsigned int count:24;
216 ValueData(): type( Value::Empty ),
217 format (Value::fmt_None), count( 1 ), ps( 0 ) { };
220 ~ValueData(){
if(
this == s_null ) s_null = 0;
221 if( type == Value::Array )
delete pa;
222 if( type == Value::String )
delete ps;
223 if( type == Value::Error )
delete ps;
227 static ValueData* null()
228 {
if( !s_null) s_null =
new ValueData;
else s_null->ref();
return s_null; }
231 void ref() { count++; }
235 { --count;
if( !count )
delete this; }
238 bool isNull(){
return this == s_null; }
241 void setFormatByType ();
245 static ValueData* s_null;
248void KSpread::ValueData::setFormatByType ()
252 format = Value::fmt_None;
255 format = Value::fmt_Boolean;
258 format = Value::fmt_Number;
261 format = Value::fmt_Number;
264 format = Value::fmt_String;
267 format = Value::fmt_None;
269 case Value::CellRange:
270 format = Value::fmt_None;
273 format = Value::fmt_String;
279ValueData* ValueData::s_null = 0;
294 d = ValueData::null();
308 d->setFormatByType ();
314 d = ValueData::null();
325bool Value::operator==(
const Value& v )
const
327 const ValueData* n = v.d;
328 if ( (uint)d->type != n->type )
332 case Empty:
return true;
333 case Boolean:
return n->b == d->b;
334 case Integer:
return n->i == d->i;
335 case Float:
return compare( n->f, d->f ) == 0;
336 case String:
return *n->ps == *d->ps;
337 case Array:
return *n->pa == *d->pa;
338 case Error:
return *n->ps == *d->ps;
341 kdWarning() <<
"Unhandled type in Value::operator==: " << d->type << endl;
348 d = ValueData::null();
355 d = ValueData::null();
362 d = ValueData::null();
369 d = ValueData::null();
376 d = ValueData::null();
383 d = ValueData::null();
390 d = ValueData::null();
397 d = ValueData::null();
404 d = ValueData::null();
413 d->format = fmt_None;
414 d->pa =
new ValueArray;
431 return d ? d->type : Empty;
440 d->format = fmt_Boolean;
448 if(
type() == Value::Boolean )
460 d->format = fmt_Number;
468 d->i =
static_cast<long>( i );
469 d->format = fmt_Number;
477 if(
type() == Value::Integer )
480 if(
type() == Value::Float )
481 result =
static_cast<long>(d->f);
497 d->format = fmt_Number;
505 if(
type() == Value::Float )
508 if(
type() == Value::Integer )
509 result =
static_cast<double>(d->i);
519 d->ps =
new TQString( s );
520 d->format = fmt_String;
528 if(
type() == Value::String )
530 result = TQString( *d->ps );
540 d->ps =
new TQString( msg );
548 if(
type() == Value::Error )
550 result = TQString( *d->ps );
561 TQDate refDate( 1899, 12, 31 );
562 TQTime refTime( 0, 0 );
564 int i = refDate.daysTo( dt.date() ) + 1;
565 i += refTime.secsTo( dt.time() ) / 86400;
568 d->format = fmt_DateTime;
574 TQTime refTime( 0, 0 );
575 int i = refTime.msecsTo( time ) ;
578 d->format = fmt_Time;
584 TQDate refDate = TQDate( 1899, 12, 31 );
585 int i = refDate.daysTo( date ) + 1;
588 d->format = fmt_Date;
600 TQDate dt( 1899, 12, 30 );
603 dt = dt.addDays( i );
614 dt = dt.addMSecs(i) ;
621 return d ? d->format : fmt_None;
632 if( (uint)d->type != Array )
return *
this;
633 if( !d->pa )
return *
this;
640 if( (uint)d->type != Array )
return;
643 d->pa->set( column, row,
new Value( v ) );
648 if( (uint)d->type != Array )
return 1;
649 if( !d->pa )
return 1;
650 return d->pa->columns;
655 if( (uint)d->type != Array )
return 1;
656 if( !d->pa )
return 1;
663 return ks_value_empty;
669 if( !ks_error_div0.isError() )
670 ks_error_div0.
setError(
"#DIV/0!" );
671 return ks_error_div0;
677 if( !ks_error_na.isError() )
685 if( !ks_error_name.isError() )
687 return ks_error_name;
693 if( !ks_error_num.isError() )
701 if( !ks_error_null.isError() )
703 return ks_error_null;
709 if( !ks_error_ref.isError() )
717 if( !ks_error_value.isError() )
718 ks_error_value.
setError(
"#VALUE!" );
719 return ks_error_value;
725 if( d->isNull() || ( d->count > 1 ) )
734 case Boolean: n->b = d->b;
break;
735 case Integer: n->i = d->i;
break;
736 case Float: n->f = d->f;
break;
737 case String: n->ps =
new TQString( *d->ps );
break;
738 case Array: n->pa =
new ValueArray; *n->pa = (*d->pa);
break;
739 case Error: n->ps =
new TQString( *d->ps );
break;
751 if( v3 > DBL_EPSILON )
return 1;
752 if( v3 < -DBL_EPSILON )
return -1;
756bool Value::isZero(
double v )
758 return fabs( v ) < DBL_EPSILON;
761bool Value::isZero()
const
769 Value::Type t1 = d->type;
770 Value::Type t2 = v.
type();
772 if( ( t1 == Empty ) && ( t2 == Empty ) )
return true;
773 if( ( t1 == Empty ) && ( t2 == String ) )
return true;
775 if( ( t1 == Boolean ) && ( t2 == Boolean ) )
return true;
776 if( ( t1 == Boolean ) && ( t2 == Integer ) )
return true;
777 if( ( t1 == Boolean ) && ( t2 == Float ) )
return true;
778 if( ( t1 == Boolean ) && ( t2 == String ) )
return true;
780 if( ( t1 == Integer ) && ( t2 == Boolean ) )
return true;
781 if( ( t1 == Integer ) && ( t2 == Integer ) )
return true;
782 if( ( t1 == Integer ) && ( t2 == Float ) )
return true;
783 if( ( t1 == Integer ) && ( t2 == String ) )
return true;
785 if( ( t1 == Float ) && ( t2 == Boolean ) )
return true;
786 if( ( t1 == Float ) && ( t2 == Integer ) )
return true;
787 if( ( t1 == Float ) && ( t2 == Float ) )
return true;
788 if( ( t1 == Float ) && ( t2 == String ) )
return true;
790 if( ( t1 == String ) && ( t2 == Empty ) )
return true;
791 if( ( t1 == String ) && ( t2 == Boolean ) )
return true;
792 if( ( t1 == String ) && ( t2 == Integer ) )
return true;
793 if( ( t1 == String ) && ( t2 == Float ) )
return true;
794 if( ( t1 == String ) && ( t2 == String ) )
return true;
797 if ((t1 == Error) && (t2 == Error))
return true;
805 Value::Type t1 = d->type;
806 Value::Type t2 = v.
type();
809 if( ( t1 == Error ) && ( t2 != Error ) )
811 if( ( t2 == Error ) && ( t1 != Error ) )
815 if( ( t1 == Error ) && ( t2 == Error ) )
819 if( ( t1 == Empty ) && ( t2 == Empty ) )
824 if( ( t1 == Empty ) && ( t2 == String ) )
825 return( v.
asString().isEmpty() ) ? 0 : -1;
828 if( ( t1 == Boolean ) && ( t2 == Boolean ) )
832 if( p )
return q ? 0 : 1;
833 else return q ? -1 : 0;
837 if( ( t1 == Boolean ) && ( t2 == Integer ) )
841 if( ( t1 == Boolean ) && ( t2 == Float ) )
845 if( ( t1 == Boolean ) && ( t2 == String ) )
849 if( ( t1 == Integer ) && ( t2 == Boolean ) )
853 if( ( t1 == Integer ) && ( t2 == Integer ) )
857 return ( p == q ) ? 0 : ( p < q ) ? -1 : 1;
861 if( ( t1 == Integer ) && ( t2 == Float ) )
865 if( ( t1 == Integer ) && ( t2 == String ) )
869 if( ( t1 == Float ) && ( t2 == Boolean ) )
873 if( ( t1 == Float ) && ( t2 == Integer ) )
877 if( ( t1 == Float ) && ( t2 == Float ) )
881 if( ( t1 == Float ) && ( t2 == String ) )
886 if( ( t1 == String ) && ( t2 == Empty ) )
890 if( ( t1 == String ) && ( t2 == Boolean ) )
894 if( ( t1 == String ) && ( t2 == Integer ) )
898 if( ( t1 == String ) && ( t2 == Float ) )
902 if( ( t1 == String ) && ( t2 == String ) )
927TQTextStream&
operator<<( TQTextStream& ts, Value::Type type )
931 case Value::Empty: ts <<
"Empty";
break;
932 case Value::Boolean: ts <<
"Boolean";
break;
933 case Value::Integer: ts <<
"Integer";
break;
934 case Value::Float: ts <<
"Float";
break;
935 case Value::String: ts <<
"String";
break;
936 case Value::Array: ts <<
"Array";
break;
937 case Value::Error: ts <<
"Error";
break;
938 default: ts <<
"Unknown!";
break;
946 switch( value.
type() )
948 case Value::Empty:
break;
953 else ts <<
"FALSE";
break;
959 ts <<
": " << value.
asFloat();
break;
962 ts <<
": " << value.
asString();
break;
Provides a wrapper for cell value.
unsigned columns() const
If this value is an array, return the number of columns.
static const Value & empty()
Returns constant reference to empty value.
Value element(unsigned column, unsigned row) const
Return an element in the array value.
static const Value & errorDIV0()
Returns constant reference to DIV/0!
void setError(const TQString &msg)
Sets this value to hold error message.
void setFormat(Format fmt)
Sets format information for this value.
bool greater(const Value &v) const
Returns true if this value is greater than v.
static const Value & errorNULL()
Returns constant reference to NULL!
Format format() const
Returns the format of the value (i.e.
void setValue(const Value &v)
Sets this value to another value.
virtual ~Value()
Destroys the value.
unsigned rows() const
If this value is an array, return the number of rows.
static const Value & errorNAME()
Returns constant reference to NAME?
Value & assign(const Value &_value)
Assigns from another value.
bool isEmpty() const
Returns true if empty.
bool isNumber() const
Returns true if the type of this value is either integer or floating-point.
bool equal(const Value &v) const
Returns true if this value is equal to v.
static const Value & errorNUM()
Returns constant reference to NUM!
TQDate asDate() const
Returns the date representation of this value.
bool allowComparison(const Value &v) const
Returns true if it is OK to compare this value with v.
Type type() const
Returns the type of the value.
static const Value & errorREF()
Returns constant reference to REF!
double asFloat() const
Returns the floating-point value of this value.
long asInteger() const
Returns the integer value of this value.
Value & operator=(const Value &_value)
Assigns from another value.
TQString errorMessage() const
Returns error message associated with this value.
TQDateTime asDateTime() const
Returns the date/time representation of this value.
TQString asString() const
Returns the string value of this value.
Value()
Creates an empty value, i.e holds nothing.
void setElement(unsigned column, unsigned row, const Value &value)
Sets an element in the array value.
static const Value & errorVALUE()
Returns constant reference to VALUE!
void detach()
Detaches itself from shared value data, i.e make a private, deep copy of the data.
int compare(const Value &v) const
Returns -1, 0, 1, depends whether this value is less than, equal to, or greater than v.
bool less(const Value &v) const
Returns true if this value is less than v.
TQTime asTime() const
Returns the time representation of this value.
bool asBoolean() const
Returns the boolean value of this value.
static const Value & errorNA()
Returns constant reference to N/A error.
TQTextStream & operator<<(TQTextStream &ts, Formula formula)
Dumps the formula, should be used only to assist debugging.