1
2 /*
3 * Math2
4 * Copyright (c) 2003-2006 by Mattias Hultgren <mattias_hultgren@tele2.se>
5 *
6 * See math2.h
7 */
8
9
10 #include "math2.h"
11 #include "keyfile.h"
12 #include <string.h>
13 #include <stdio.h>
14 #include <new>
15
16 namespace math
17 {
18
append_to_string(utf8_string & str,const Format & fmt,bool show_name) const19 void Variable::append_to_string( utf8_string &str, const Format &fmt, bool show_name ) const
20 throw(error_obj)
21 {
22 utf8_string tmp_str;
23
24 try
25 {
26 if( has_name() && show_name )
27 {
28 str.append( *get_name() );
29 tmp_str = " = ";
30 str.append( tmp_str );
31 }
32
33 switch( get_type() )
34 {
35 case VariableType_Matrix:
36 get_matrix()->append_to_string( str, fmt, (has_name() && show_name) );
37 break;
38
39 case VariableType_String:
40 tmp_str = "\"";
41 str.append( tmp_str );
42 str.append( *get_string() );
43 str.append( tmp_str );
44 break;
45
46 case VariableType_Complex:
47 get_complex()->append_to_string( str, fmt );
48 break;
49
50 case VariableType_Picture:
51 {
52 const Picture *pic = get_picture();
53 char tmp[100];
54 snprintf( tmp, 100, "%s %ldx%ld", _("Picture"), pic->pic.get_width(),
55 pic->pic.get_height() );
56 tmp_str = tmp;
57 str.append( tmp_str );
58 }
59 break;
60
61 case VariableType_Array:
62 {
63 const Array *array = get_array();
64
65 if( array->get_size() > 0 )
66 {
67 tmp_str = "( ";
68 str.append( tmp_str );
69 if( array->get_variable(0)->get_type() == VariableType_Complex )
70 array->get_variable(0)->get_complex()->append_to_string( str, fmt );
71 else if( array->get_variable(0)->get_type() == VariableType_Boolean )
72 {
73 tmp_str = (array->get_variable(0)->get_boolean() ? "true" : "false");
74 str.append( tmp_str );
75 }
76 else
77 {
78 tmp_str = VARIABLE_TYPE_NAMES[array->get_variable(0)->get_type()];
79 str.append( tmp_str );
80 }
81 }
82 else
83 {
84 tmp_str = "( ";
85 str.append( tmp_str );
86 tmp_str = _("Empty array");
87 str.append( tmp_str );
88 }
89
90 for( uint32 i=1; i<array->get_size(); i++ )
91 {
92 tmp_str = ", ";
93 str.append( tmp_str );
94 if( array->get_variable(i)->get_type() == VariableType_Complex )
95 array->get_variable(i)->get_complex()->append_to_string( str, fmt );
96 else if( array->get_variable(i)->get_type() == VariableType_Boolean )
97 {
98 tmp_str = (array->get_variable(i)->get_boolean() ? "true" : "false");
99 str.append( tmp_str );
100 }
101 else
102 {
103 tmp_str = VARIABLE_TYPE_NAMES[array->get_variable(i)->get_type()];
104 str.append( tmp_str );
105 }
106 }
107
108 tmp_str = " )";
109 str.append( tmp_str );
110 }
111 break;
112
113 case VariableType_Boolean:
114 tmp_str = (get_boolean() ? "true" : "false");
115 str.append( tmp_str );
116 break;
117
118 case VariableType_Void:
119 str.append( "void" );
120 break;
121 }
122 }
123 catch(error_obj error) { throw error; }
124 catch(...) { THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
125 }
126
127
Variable()128 Variable::Variable()
129 {
130 type = VariableType_Boolean;
131
132 isconstant = false;
133 can_change_type = true;
134
135 inuse = false;
136
137 boolean = true;
138
139 change_func = 0;
140 delete_func = 0;
141 }
Variable(const Variable & src)142 Variable::Variable(const Variable &src) throw(error_obj)
143 {
144 type = VariableType_Boolean;
145
146 isconstant = false;
147 can_change_type = true;
148
149 inuse = false;
150
151 boolean = true;
152
153 change_func = 0;
154 delete_func = 0;
155
156 *this = src;
157 }
158
~Variable()159 Variable::~Variable()
160 {
161 if( delete_func != 0 )
162 (*delete_func)(this);
163 change_func = 0;
164 isconstant = false;
165 clear();
166 }
167
168 // this function only copies the value/Matrix/function/list/string of the Variable
operator =(const Variable & src)169 void Variable::operator=(const Variable &src) throw(error_obj)
170 {
171 if(&src == this)
172 return;
173
174 switch(src.type)
175 {
176 case VariableType_Boolean:
177 set_boolean(src.boolean);
178 break;
179
180 case VariableType_Complex:
181 set_complex( *Complex_ptr(src.complex_buf) );
182 break;
183
184 case VariableType_Matrix:
185 set_matrix(src.matr);
186 break;
187
188 case VariableType_String:
189 if(src.str == 0)
190 set_string("");
191 else
192 {
193 if(src.code_line != 0)
194 set_code_line( src.str->c_str() );
195 else
196 set_string( *src.str );
197 }
198 break;
199
200 case VariableType_Array:
201 set_array(src.array);
202 break;
203
204 case VariableType_Picture:
205 set_picture(src.pic);
206 break;
207
208 case VariableType_Void:
209 set_void();
210 break;
211
212 default: // this should only occur when I've forgotten to add a curtain Variable-type to this function
213 {
214 char tmp_err[ERROR_OBJ_MSG_LEN];
215 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "Variable::operator=" );
216 THROW_ERROR( ErrorType_General, tmp_err );
217 }
218 }
219 }
220
operator ==(const Variable & var) const221 bool Variable::operator==( const Variable &var ) const
222 {
223 if( type != var.type )
224 return false;
225
226 else if( type == VariableType_Complex )
227 return (*get_complex() == *var.get_complex());
228
229 else if( type == VariableType_Boolean )
230 return (get_boolean() == var.get_boolean());
231
232 else if( type == VariableType_Matrix )
233 return (*get_matrix() == *var.get_matrix());
234
235 else if( type == VariableType_String )
236 return (*get_string() == *var.get_string());
237
238 else if( type == VariableType_Picture )
239 return (*get_picture() == *var.get_picture());
240
241 else if( type == VariableType_Array )
242 return (*get_array() == *var.get_array());
243
244 else // if( type == VariableType_Void )
245 return var.is_void();
246 }
247
set_to_constant(void)248 void Variable::set_to_constant(void)
249 {
250 isconstant = true;
251 }
252
set_can_change_type(bool boolean)253 void Variable::set_can_change_type(bool boolean) throw(error_obj)
254 {
255 if(isconstant == true)
256 THROW_ERROR( ErrorType_General, _("Tried to change a constant.") );
257
258 can_change_type = boolean;
259 }
260
set_name(const utf8_string & newname)261 void Variable::set_name(const utf8_string &newname) throw(error_obj)
262 {
263 if(isconstant == true)
264 THROW_ERROR( ErrorType_General, _("Tried to change a constant.") );
265
266 try{ name = newname; }
267 catch(...) { THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
268 }
269
get_matrix(void) const270 const Matrix* Variable::get_matrix(void) const throw(error_obj)
271 {
272 if(type != VariableType_Matrix)
273 THROW_ERROR( ErrorType_General, _("Variable type isn't Matrix") );
274
275 if(matr == 0)
276 THROW_ERROR( ErrorType_Internal, "Variable has a NULL-object" );
277
278 return matr;
279 }
280
get_matrix_rw(void)281 Matrix* Variable::get_matrix_rw(void) throw(error_obj)
282 {
283 if(type != VariableType_Matrix)
284 THROW_ERROR( ErrorType_General, _("Variable type isn't Matrix") );
285
286 if(matr == 0)
287 THROW_ERROR( ErrorType_Internal, "Variable has a NULL-object" );
288
289 if(isconstant == true)
290 THROW_ERROR( ErrorType_General, _("Tried to change a constant.") );
291
292 return matr;
293 }
294
get_array(void) const295 const Array* Variable::get_array(void) const throw(error_obj)
296 {
297 if(type != VariableType_Array)
298 THROW_ERROR( ErrorType_General, _("Variable type isn't Array") );
299
300 if(array == 0)
301 THROW_ERROR( ErrorType_Internal, "Variable has a NULL-object" );
302
303 return array;
304 }
305
get_array_rw(void)306 Array* Variable::get_array_rw(void) throw(error_obj)
307 {
308 if(type != VariableType_Array)
309 THROW_ERROR( ErrorType_General, _("Variable type isn't Array") );
310
311 if(array == 0)
312 THROW_ERROR( ErrorType_Internal, "Variable has a NULL-object" );
313
314 if(isconstant == true)
315 THROW_ERROR( ErrorType_General, _("Tried to change a constant.") );
316
317 return array;
318 }
319
get_picture(void) const320 const Picture* Variable::get_picture(void) const throw(error_obj)
321 {
322 if(type != VariableType_Picture)
323 THROW_ERROR( ErrorType_General, _("Variable type isn't Picture") );
324
325 if(pic == 0)
326 THROW_ERROR( ErrorType_Internal, "Variable has a NULL-object" );
327
328 return pic;
329 }
330
get_picture_rw(void)331 Picture* Variable::get_picture_rw(void) throw(error_obj)
332 {
333 if(type != VariableType_Picture)
334 THROW_ERROR( ErrorType_General, _("Variable type isn't Picture") );
335
336 if(pic == 0)
337 THROW_ERROR( ErrorType_Internal, "Variable has a NULL-object" );
338
339 if(isconstant == true)
340 THROW_ERROR( ErrorType_General, _("Tried to change a constant.") );
341
342 return pic;
343 }
344
clear(void)345 void Variable::clear(void) throw(error_obj)
346 {
347 if(isconstant == true)
348 THROW_ERROR( ErrorType_General, _("Tried to change a constant.") );
349 switch(type)
350 {
351 case VariableType_Boolean:
352 boolean = true;
353 break;
354
355 case VariableType_Complex:
356 if( boolean )
357 Complex_ptr( complex_buf )->~Complex();
358 boolean = false;
359 break;
360
361 case VariableType_String:
362 delete code_line;
363 delete str;
364 code_line = 0;
365 str = 0;
366 break;
367
368 case VariableType_Matrix:
369 delete matr;
370 matr = 0;
371 break;
372
373 case VariableType_Array:
374 delete array;
375 array = 0;
376 break;
377
378 case VariableType_Picture:
379 delete pic;
380 pic = 0;
381 break;
382
383 case VariableType_Void:
384 break;
385
386 default: // this should only occur when I've forgotten to add a curtain Variable-type to this function
387 {
388 char tmp_err[ERROR_OBJ_MSG_LEN];
389 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Data type is unsupported by '%s'"), "Variable::clear" );
390 THROW_ERROR( ErrorType_General, tmp_err );
391 }
392 }
393 if(change_func != 0)
394 (*change_func)(this);
395 }
396
signal_changed(void)397 void Variable::signal_changed(void)
398 {
399 if( change_func != 0 )
400 (*change_func)( this );
401 }
402
set_complex(const Complex & newvalue)403 void Variable::set_complex(const Complex &newvalue) throw(error_obj)
404 {
405 if(isconstant == true)
406 THROW_ERROR( ErrorType_General, _("Tried to change a constant.") );
407
408 if(type != VariableType_Complex)
409 {
410 if(can_change_type == false)
411 THROW_ERROR( ErrorType_General, _("Tried to change type of a type locked variable.") );
412
413 void (*tmp)(Variable *ptr);
414 tmp = change_func;
415 change_func = 0;
416
417 clear();
418
419 type = VariableType_Complex;
420 boolean = false;
421
422 change_func = tmp;
423 }
424
425 if( !boolean )
426 {
427 try{ new (complex_buf) Complex; boolean = true; }
428 catch(...) { THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
429 }
430
431 *Complex_ptr(complex_buf) = newvalue;
432
433 if(change_func != 0)
434 (*change_func)(this);
435 }
436
set_boolean(bool newbool)437 void Variable::set_boolean(bool newbool) throw(error_obj)
438 {
439 if(isconstant == true)
440 THROW_ERROR( ErrorType_General, _("Tried to change a constant.") );
441 if( can_change_type == false && type != VariableType_Boolean )
442 THROW_ERROR( ErrorType_General, _("Tried to change type of a type locked variable.") );
443
444 clear();
445
446 type = VariableType_Boolean;
447 boolean = newbool;
448
449 if(change_func != 0)
450 (*change_func)(this);
451 }
452
set_array(const Array * newarray)453 void Variable::set_array(const Array *newarray) throw(error_obj)
454 {
455 if(isconstant == true)
456 THROW_ERROR( ErrorType_General, _("Tried to change a constant.") );
457 if( can_change_type == false && type != VariableType_Array )
458 THROW_ERROR( ErrorType_General, _("Tried to change type of a type locked variable.") );
459
460 if(type == VariableType_Array)
461 {
462 if(array == newarray) // the array's are the same
463 return;
464 }
465 clear();
466
467 type = VariableType_Array;
468 array = 0;
469
470 if(newarray == 0)
471 return;
472
473 try{ array = new Array; }
474 catch(...) { THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
475
476 try{ *array = *newarray; }
477 catch(...)
478 {
479 clear();
480 throw;
481 }
482
483 if(change_func != 0)
484 (*change_func)(this);
485 }
486
set_matrix(const Matrix * newmatrix)487 void Variable::set_matrix(const Matrix *newmatrix) throw(error_obj)
488 {
489 if(isconstant == true)
490 THROW_ERROR( ErrorType_General, _("Tried to change a constant.") );
491 if( can_change_type == false && type != VariableType_Matrix )
492 THROW_ERROR( ErrorType_General, _("Tried to change type of a type locked variable.") );
493
494 if(type == VariableType_Matrix)
495 {
496 if(matr == newmatrix) // the Matrix' are the same
497 return;
498 }
499 else
500 {
501 clear();
502
503 type = VariableType_Matrix;
504 matr = 0;
505
506 if(newmatrix == 0)
507 return;
508
509 try{ matr = new Matrix; }
510 catch(...) { THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
511 }
512
513 try{ *matr = *newmatrix; }
514 catch(...)
515 {
516 clear();
517 throw;
518 }
519
520 if(change_func != 0)
521 (*change_func)(this);
522 }
523
set_picture(const Picture * newpic)524 void Variable::set_picture(const Picture *newpic) throw(error_obj)
525 {
526 if(isconstant == true)
527 THROW_ERROR( ErrorType_General, _("Tried to change a constant.") );
528 if( can_change_type == false && type != VariableType_Picture )
529 THROW_ERROR( ErrorType_General, _("Tried to change type of a type locked variable.") );
530
531 if(type == VariableType_Picture)
532 {
533 if(pic == newpic) // the Picture's are the same
534 return;
535 }
536 else
537 {
538 clear();
539
540 type = VariableType_Picture;
541 pic = 0;
542
543 if(newpic == 0)
544 return;
545
546 try{ pic = new Picture; }
547 catch(...) { THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
548 }
549
550 try{ *pic = *newpic; }
551 catch(...)
552 {
553 clear();
554 throw;
555 }
556
557 if(change_func != 0)
558 (*change_func)(this);
559 }
560
get_string(void) const561 const utf8_string* Variable::get_string(void) const throw(error_obj)
562 {
563 if(type != VariableType_String)
564 THROW_ERROR( ErrorType_General, _("Variable type isn't String") );
565
566 if(str == 0)
567 THROW_ERROR( ErrorType_Internal, "Variable has a NULL-object" );
568
569 return str;
570 }
571
get_string_rw(void)572 utf8_string* Variable::get_string_rw(void) throw(error_obj)
573 {
574 if(type != VariableType_String)
575 THROW_ERROR( ErrorType_General, _("Variable type isn't String") );
576
577 if(str == 0)
578 THROW_ERROR( ErrorType_Internal, "Variable has a NULL-object" );
579
580 if(isconstant == true)
581 THROW_ERROR( ErrorType_General, _("Tried to change a constant.") );
582
583 return str;
584 }
585
get_name(void) const586 const utf8_string* Variable::get_name(void) const throw(error_obj)
587 {
588 if( name.get_length() == 0 )
589 THROW_ERROR( ErrorType_General, _("Variable has no name.") );
590
591 return &name;
592 }
593
calc_code_line(Variable * res)594 void Variable::calc_code_line( Variable *res ) throw(error_obj)
595 {
596 bool tmp_isconstant;
597
598 if(type != VariableType_String)
599 THROW_ERROR( ErrorType_General, _("Variable isn't String") );
600
601 if(code_line == 0)
602 {
603 if(str == 0)
604 THROW_ERROR( ErrorType_Internal, "Variable has a NULL-object" );
605
606 try{ code_line = new CodeLine; }
607 catch(...) { THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
608
609 code_line->set_code_line( str->c_str() );
610 }
611
612 if(inuse)
613 {
614 char tmp_err[ERROR_OBJ_MSG_LEN];
615 snprintf( tmp_err, ERROR_OBJ_MSG_LEN, _("Circle reference of variable %s"), name.c_str() );
616 THROW_ERROR( ErrorType_General, tmp_err );
617 }
618
619 if( has_name() ) // a nameless Variable can't have a circle reference
620 inuse = true;
621 tmp_isconstant = isconstant;
622 isconstant = true;
623
624 try{ code_line->calc( res ); }
625 catch(...)
626 {
627 inuse = false;
628 isconstant = tmp_isconstant;
629 throw;
630 }
631 inuse = false;
632 isconstant = tmp_isconstant;
633 }
634
set_string(const utf8_string & newstring)635 void Variable::set_string(const utf8_string &newstring) throw(error_obj)
636 {
637 if( isconstant == true )
638 THROW_ERROR( ErrorType_General, _("Tried to change a constant.") );
639 if( can_change_type == false && type != VariableType_String )
640 THROW_ERROR( ErrorType_General, _("Tried to change type of a type locked variable.") );
641
642 clear();
643
644 type = VariableType_String;
645 str = 0;
646 code_line = 0;
647
648 try{ str = new utf8_string(newstring); }
649 catch(...) { THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
650
651 if(change_func != 0)
652 (*change_func)(this);
653 }
654
set_code_line(const char * new_code_line)655 void Variable::set_code_line(const char *new_code_line) throw(error_obj)
656 {
657 void (*tmp_change_func)(Variable *ptr);
658
659 tmp_change_func = change_func;
660 change_func = 0;
661
662 set_string( new_code_line );
663
664 change_func = tmp_change_func;
665
666 code_line = 0;
667
668 if(new_code_line == 0)
669 return;
670 if(new_code_line[0] == 0)
671 return;
672
673 try{ code_line = new CodeLine; }
674 catch(...) { THROW_ERROR( ErrorType_Memory, _("Couldn't get memory.") ); }
675
676
677 code_line->set_code_line(new_code_line);
678
679
680 if(change_func != 0)
681 (*change_func)(this);
682 }
683
get_complex(void) const684 const Complex* Variable::get_complex(void) const throw(error_obj)
685 {
686 if(type != VariableType_Complex)
687 THROW_ERROR( ErrorType_General, _("Variable type isn't Complex") );
688
689 if( !boolean )
690 THROW_ERROR( ErrorType_Internal, "Variable has a NULL-object" );
691
692 return Complex_ptr(complex_buf);
693 }
694
get_complex_rw(void)695 Complex* Variable::get_complex_rw(void) throw(error_obj)
696 {
697 if(type != VariableType_Complex)
698 THROW_ERROR( ErrorType_General, _("Variable type isn't Complex") );
699
700 if( !boolean )
701 THROW_ERROR( ErrorType_Internal, "Variable has a NULL-object" );
702
703 return Complex_ptr(complex_buf);
704 }
705
get_boolean(void) const706 bool Variable::get_boolean(void) const throw(error_obj)
707 {
708 if(type == VariableType_Boolean)
709 return boolean;
710
711 THROW_ERROR( ErrorType_General, _("Variable type isn't Boolean") );
712 }
713
set_void(void)714 void Variable::set_void(void)
715 {
716 if(isconstant == true)
717 THROW_ERROR( ErrorType_General, _("Tried to change a constant.") );
718
719 if( can_change_type == false && type != VariableType_Void )
720 THROW_ERROR( ErrorType_General, _("Tried to change type of a type locked variable.") );
721
722 void (*tmp)(Variable *ptr);
723 tmp = change_func;
724 change_func = 0;
725
726 clear();
727
728 type = VariableType_Void;
729
730 change_func = tmp;
731
732 if(change_func != 0)
733 (*change_func)(this);
734 }
735
736 } // namespace math
737