1 /****************************************************************************
2  *               povmscpp.cpp
3  *
4  * This module contains the C++ interface version of povms.cpp
5  *
6  * from Persistence of Vision(tm) Ray Tracer version 3.6.
7  * Copyright 1991-2003 Persistence of Vision Team
8  * Copyright 2003-2004 Persistence of Vision Raytracer Pty. Ltd.
9  *---------------------------------------------------------------------------
10  * NOTICE: This source code file is provided so that users may experiment
11  * with enhancements to POV-Ray and to port the software to platforms other
12  * than those supported by the POV-Ray developers. There are strict rules
13  * regarding how you are permitted to use this file. These rules are contained
14  * in the distribution and derivative versions licenses which should have been
15  * provided with this file.
16  *
17  * These licences may be found online, linked from the end-user license
18  * agreement that is located at http://www.povray.org/povlegal.html
19  *---------------------------------------------------------------------------
20  * This program is based on the popular DKB raytracer version 2.12.
21  * DKBTrace was originally written by David K. Buck.
22  * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
23  *---------------------------------------------------------------------------
24  *
25  *===========================================================================
26  * This file is part of MegaPOV, a modified and unofficial version of POV-Ray
27  * For more information on MegaPOV visit our website:
28  * http://megapov.inetart.net/
29  *===========================================================================
30  *
31  * $RCSfile: povmscpp.cpp,v $
32  * $Revision: 1.12 $
33  * $Author: chris $
34  *
35  *****************************************************************************/
36 
37 #include "configbase.h"
38 
39 #include "povmscpp.h"
40 
41 
42 USING_POV_BASE_NAMESPACE
43 
44 /*****************************************************************************
45 *
46 * CLASS
47 *   POVMS_Container
48 *
49 * DESCRIPTION
50 *   Base class for all other POVMS classes.
51 *
52 * CHANGES
53 *   -
54 *
55 ******************************************************************************/
56 
POVMS_Container()57 POVMS_Container::POVMS_Container()
58 {
59 	data.type = kPOVMSType_Null;
60 	data.size = 0;
61 	data.ptr = NULL;
62 }
63 
~POVMS_Container()64 POVMS_Container::~POVMS_Container()
65 {
66 	// do nothing for now
67 }
68 
Type()69 POVMSType POVMS_Container::Type()
70 {
71 	return data.type;
72 }
73 
Size()74 long POVMS_Container::Size()
75 {
76 	return data.size;
77 }
78 
IsNull()79 bool POVMS_Container::IsNull()
80 {
81 	return (data.type == kPOVMSType_Null);
82 }
83 
DetachData()84 void POVMS_Container::DetachData()
85 {
86 	data.type = kPOVMSType_Null;
87 	data.size = 0;
88 	data.ptr = NULL;
89 }
90 
91 
92 /*****************************************************************************
93 *
94 * CLASS
95 *   POVMS_Attribute
96 *
97 * DESCRIPTION
98 *   Class handling POVMSAttribute.
99 *
100 * CHANGES
101 *   -
102 *
103 ******************************************************************************/
104 
POVMS_Attribute()105 POVMS_Attribute::POVMS_Attribute()
106 {
107 	int err;
108 
109 	err = POVMSAttr_New(&data);
110 	if(err != kNoErr)
111 		throw err;
112 }
113 
POVMS_Attribute(const char * str)114 POVMS_Attribute::POVMS_Attribute(const char *str)
115 {
116 	int err;
117 
118 	err = POVMSAttr_New(&data);
119 	if(err != kNoErr)
120 		throw err;
121 	err = POVMSAttr_Set(&data, kPOVMSType_CString, (void *)str, strlen(str) + 1);
122 	if(err != kNoErr)
123 	{
124 		(void)POVMSAttr_Delete(&data);
125 		throw err;
126 	}
127 }
128 
POVMS_Attribute(POVMSInt value)129 POVMS_Attribute::POVMS_Attribute(POVMSInt value)
130 {
131 	int err;
132 
133 	err = POVMSAttr_New(&data);
134 	if(err != kNoErr)
135 		throw err;
136 	err = POVMSAttr_Set(&data, kPOVMSType_Int, (void *)(&value), sizeof(POVMSLong));
137 	if(err != kNoErr)
138 	{
139 		(void)POVMSAttr_Delete(&data);
140 		throw err;
141 	}
142 }
143 
POVMS_Attribute(POVMSLong value)144 POVMS_Attribute::POVMS_Attribute(POVMSLong value)
145 {
146 	int err;
147 
148 	err = POVMSAttr_New(&data);
149 	if(err != kNoErr)
150 		throw err;
151 	err = POVMSAttr_Set(&data, kPOVMSType_Long, (void *)(&value), sizeof(POVMSLong));
152 	if(err != kNoErr)
153 	{
154 		(void)POVMSAttr_Delete(&data);
155 		throw err;
156 	}
157 }
158 
POVMS_Attribute(POVMSFloat value)159 POVMS_Attribute::POVMS_Attribute(POVMSFloat value)
160 {
161 	int err;
162 
163 	err = POVMSAttr_New(&data);
164 	if(err != kNoErr)
165 		throw err;
166 	err = POVMSAttr_Set(&data, kPOVMSType_Float, (void *)(&value), sizeof(POVMSFloat));
167 	if(err != kNoErr)
168 	{
169 		(void)POVMSAttr_Delete(&data);
170 		throw err;
171 	}
172 }
173 
POVMS_Attribute(bool b)174 POVMS_Attribute::POVMS_Attribute(bool b)
175 {
176 	POVMSBool value = (POVMSBool)b;
177 	int err;
178 
179 	err = POVMSAttr_New(&data);
180 	if(err != kNoErr)
181 		throw err;
182 	err = POVMSAttr_Set(&data, kPOVMSType_Bool, (void *)(&value), sizeof(POVMSBool));
183 	if(err != kNoErr)
184 	{
185 		(void)POVMSAttr_Delete(&data);
186 		throw err;
187 	}
188 }
189 
POVMS_Attribute(POVMSType value)190 POVMS_Attribute::POVMS_Attribute(POVMSType value)
191 {
192 	int err;
193 
194 	err = POVMSAttr_New(&data);
195 	if(err != kNoErr)
196 		throw err;
197 	err = POVMSAttr_Set(&data, kPOVMSType_Type, (void *)(&value), sizeof(POVMSType));
198 	if(err != kNoErr)
199 	{
200 		(void)POVMSAttr_Delete(&data);
201 		throw err;
202 	}
203 }
204 
POVMS_Attribute(POVMSAttribute & convert)205 POVMS_Attribute::POVMS_Attribute(POVMSAttribute& convert)
206 {
207 	data = convert;
208 }
209 
POVMS_Attribute(POVMS_Attribute & source)210 POVMS_Attribute::POVMS_Attribute(POVMS_Attribute& source)
211 {
212 	int err;
213 
214 	err = POVMSAttr_Copy(&source.data, &data);
215 	if(err != kNoErr)
216 		throw err;
217 }
218 
~POVMS_Attribute()219 POVMS_Attribute::~POVMS_Attribute()
220 {
221 	int err;
222 
223 	err = POVMSAttr_Delete(&data);
224 	if(err != kNoErr)
225 		throw err;
226 }
227 
operator =(POVMS_Attribute & source)228 POVMS_Attribute& POVMS_Attribute::operator=(POVMS_Attribute& source)
229 {
230 	int err;
231 
232 	err = POVMSAttr_Delete(&data);
233 	if(err == kNoErr)
234 		err = POVMSAttr_Copy(&source.data, &data);
235 	if(err != kNoErr)
236 		throw err;
237 
238 	return *this;
239 }
240 
Get(POVMSType type,void * data,int * maxdatasize)241 void POVMS_Attribute::Get(POVMSType type, void *data, int *maxdatasize)
242 {
243 	int err;
244 
245 	err = POVMSAttr_Get(&this->data, type, data, maxdatasize);
246 	if(err != kNoErr)
247 		throw err;
248 }
249 
Set(POVMSType type,void * data,int datasize)250 void POVMS_Attribute::Set(POVMSType type, void *data, int datasize)
251 {
252 	int err;
253 
254 	err = POVMSAttr_Set(&this->data, type, data, datasize);
255 	if(err != kNoErr)
256 		throw err;
257 }
258 
259 
260 /*****************************************************************************
261 *
262 * CLASS
263 *   POVMS_List
264 *
265 * DESCRIPTION
266 *   Class handling POVMSAttributeList.
267 *
268 * CHANGES
269 *   -
270 *
271 ******************************************************************************/
272 
POVMS_List()273 POVMS_List::POVMS_List()
274 {
275 	int err;
276 
277 	err = POVMSAttrList_New(&data);
278 	if(err != kNoErr)
279 		throw err;
280 }
281 
POVMS_List(POVMSAttributeList & convert)282 POVMS_List::POVMS_List(POVMSAttributeList& convert)
283 {
284 	data = convert;
285 }
286 
POVMS_List(POVMS_List & source)287 POVMS_List::POVMS_List(POVMS_List& source)
288 {
289 	int err;
290 
291 	err = POVMSAttrList_Copy(&source.data, &data);
292 	if(err != kNoErr)
293 		throw err;
294 }
295 
~POVMS_List()296 POVMS_List::~POVMS_List()
297 {
298 	int err;
299 
300 	err = POVMSAttrList_Delete(&data);
301 	if(err != kNoErr)
302 		throw err;
303 }
304 
operator =(POVMS_List & source)305 POVMS_List& POVMS_List::operator=(POVMS_List& source)
306 {
307 	int err;
308 
309 	err = POVMSAttrList_Delete(&data);
310 	if(err == kNoErr)
311 		err = POVMSAttrList_Copy(&source.data, &data);
312 	if(err != kNoErr)
313 		throw err;
314 
315 	return *this;
316 }
317 
Append(POVMS_Attribute & item)318 void POVMS_List::Append(POVMS_Attribute& item)
319 {
320 	int err;
321 
322 	err = POVMSAttrList_Append(&data, &item.data);
323 	if(err != kNoErr)
324 		throw err;
325 
326 	item.DetachData();
327 }
328 
Append(POVMS_List & item)329 void POVMS_List::Append(POVMS_List& item)
330 {
331 	int err;
332 
333 	err = POVMSAttrList_Append(&data, &item.data);
334 	if(err != kNoErr)
335 		throw err;
336 
337 	item.DetachData();
338 }
339 
Append(POVMS_Object & item)340 void POVMS_List::Append(POVMS_Object& item)
341 {
342 	int err;
343 
344 	err = POVMSAttrList_Append(&data, &item.data);
345 	if(err != kNoErr)
346 		throw err;
347 
348 	item.DetachData();
349 }
350 
GetNth(int index,POVMS_Attribute & item)351 void POVMS_List::GetNth(int index, POVMS_Attribute& item)
352 {
353 	int err;
354 
355 	err = POVMSAttr_Delete(&item.data);
356 	if(err != kNoErr)
357 		throw err;
358 	err = POVMSAttrList_GetNth(&data, index, &item.data);
359 	if(err != kNoErr)
360 		throw err;
361 }
362 
GetNth(int index,POVMS_List & item)363 void POVMS_List::GetNth(int index, POVMS_List& item)
364 {
365 	int err;
366 
367 	err = POVMSAttrList_Delete(&item.data);
368 	if(err != kNoErr)
369 		throw err;
370 	err = POVMSAttrList_GetNth(&data, index, &item.data);
371 	if(err != kNoErr)
372 		throw err;
373 }
374 
GetNth(int index,POVMS_Object & item)375 void POVMS_List::GetNth(int index, POVMS_Object& item)
376 {
377 	int err;
378 
379 	err = POVMSObject_Delete(&item.data);
380 	if(err != kNoErr)
381 		throw err;
382 	err = POVMSAttrList_GetNth(&data, index, &item.data);
383 	if(err != kNoErr)
384 		throw err;
385 }
386 
SetNth(int index,POVMS_Attribute & item)387 void POVMS_List::SetNth(int index, POVMS_Attribute& item)
388 {
389 	int err;
390 
391 	err = POVMSAttrList_SetNth(&data, index, &item.data);
392 	if(err != kNoErr)
393 		throw err;
394 
395 	item.DetachData();
396 }
397 
SetNth(int index,POVMS_List & item)398 void POVMS_List::SetNth(int index, POVMS_List& item)
399 {
400 	int err;
401 
402 	err = POVMSAttrList_SetNth(&data, index, &item.data);
403 	if(err != kNoErr)
404 		throw err;
405 
406 	item.DetachData();
407 }
408 
SetNth(int index,POVMS_Object & item)409 void POVMS_List::SetNth(int index, POVMS_Object& item)
410 {
411 	int err;
412 
413 	err = POVMSAttrList_SetNth(&data, index, &item.data);
414 	if(err != kNoErr)
415 		throw err;
416 
417 	item.DetachData();
418 }
419 
RemoveNth(int index)420 void POVMS_List::RemoveNth(int index)
421 {
422 	int err;
423 
424 	err = POVMSAttrList_RemoveNth(&data, index);
425 	if(err != kNoErr)
426 		throw err;
427 }
428 
Clear()429 void POVMS_List::Clear()
430 {
431 	int err;
432 
433 	err = POVMSAttrList_Clear(&data);
434 	if(err != kNoErr)
435 		throw err;
436 }
437 
438 
439 /*****************************************************************************
440 *
441 * CLASS
442 *   POVMS_Object
443 *
444 * DESCRIPTION
445 *   Class handling POVMSObject.
446 *
447 * CHANGES
448 *   -
449 *
450 ******************************************************************************/
451 
POVMS_Object(POVMSType objclass)452 POVMS_Object::POVMS_Object(POVMSType objclass)
453 {
454 	int err;
455 
456 	err = POVMSObject_New(&data, objclass);
457 	if(err != kNoErr)
458 		throw err;
459 }
460 
POVMS_Object(POVMSObject & convert)461 POVMS_Object::POVMS_Object(POVMSObject& convert)
462 {
463 	data = convert;
464 }
465 
POVMS_Object(POVMSObjectPtr convert)466 POVMS_Object::POVMS_Object(POVMSObjectPtr convert)
467 {
468 	if(convert != NULL)
469 		data = *convert;
470 }
471 
POVMS_Object(POVMS_Object & source)472 POVMS_Object::POVMS_Object(POVMS_Object& source)
473 {
474 	int err;
475 
476 	err = POVMSObject_Copy(&source.data, &data);
477 	if(err != kNoErr)
478 		throw err;
479 }
480 
~POVMS_Object()481 POVMS_Object::~POVMS_Object()
482 {
483 	int err;
484 
485 	err = POVMSObject_Delete(&data);
486 	if(err != kNoErr)
487 		throw err;
488 }
489 
operator =(POVMS_Object & source)490 POVMS_Object& POVMS_Object::operator=(POVMS_Object& source)
491 {
492 	int err;
493 
494 	err = POVMSObject_Delete(&data);
495 	if(err == kNoErr)
496 		err = POVMSObject_Copy(&source.data, &data);
497 	if(err != kNoErr)
498 		throw err;
499 
500 	return *this;
501 }
502 
Get(POVMSType key,POVMS_Attribute & attr)503 void POVMS_Object::Get(POVMSType key, POVMS_Attribute& attr)
504 {
505 	int err;
506 
507 	err = POVMSAttr_Delete(&attr.data);
508 	if(err != kNoErr)
509 		throw err;
510 	err = POVMSObject_Get(&data, &attr.data, key);
511 	if(err != kNoErr)
512 		throw err;
513 }
514 
Get(POVMSType key,POVMS_List & attr)515 void POVMS_Object::Get(POVMSType key, POVMS_List& attr)
516 {
517 	int err;
518 
519 	err = POVMSAttrList_Delete(&attr.data);
520 	if(err != kNoErr)
521 		throw err;
522 	err = POVMSObject_Get(&data, &attr.data, key);
523 	if(err != kNoErr)
524 		throw err;
525 }
526 
Get(POVMSType key,POVMS_Object & attr)527 void POVMS_Object::Get(POVMSType key, POVMS_Object& attr)
528 {
529 	int err;
530 
531 	err = POVMSObject_Delete(&attr.data);
532 	if(err != kNoErr)
533 		throw err;
534 	err = POVMSObject_Get(&data, &attr.data, key);
535 	if(err != kNoErr)
536 		throw err;
537 }
538 
Set(POVMSType key,POVMS_Attribute & attr)539 void POVMS_Object::Set(POVMSType key, POVMS_Attribute& attr)
540 {
541 	int err;
542 
543 	err = POVMSObject_Set(&data, &attr.data, key);
544 	if(err != kNoErr)
545 		throw err;
546 
547 	attr.DetachData();
548 }
549 
Set(POVMSType key,POVMS_List & attr)550 void POVMS_Object::Set(POVMSType key, POVMS_List& attr)
551 {
552 	int err;
553 
554 	err = POVMSObject_Set(&data, &attr.data, key);
555 	if(err != kNoErr)
556 		throw err;
557 
558 	attr.DetachData();
559 }
560 
Set(POVMSType key,POVMS_Object & attr)561 void POVMS_Object::Set(POVMSType key, POVMS_Object& attr)
562 {
563 	int err;
564 
565 	err = POVMSObject_Set(&data, &attr.data, key);
566 	if(err != kNoErr)
567 		throw err;
568 
569 	attr.DetachData();
570 }
571 
Remove(POVMSType key)572 void POVMS_Object::Remove(POVMSType key)
573 {
574 	int err;
575 
576 	err = POVMSObject_Remove(&data, key);
577 	if(err != kNoErr)
578 		throw err;
579 }
580 
Exist(POVMSType key)581 bool POVMS_Object::Exist(POVMSType key)
582 {
583 	return (POVMSObject_Exist(&data, key) == kNoErr);
584 }
585 
Merge(POVMS_Object & source)586 void POVMS_Object::Merge(POVMS_Object& source)
587 {
588 	int err;
589 
590 	err = POVMSObject_Merge(&source.data, &data);
591 	if(err != kNoErr)
592 		throw err;
593 }
594 
operator *() const595 const POVMSObject& POVMS_Object::operator*() const
596 {
597 	return *((const POVMSObjectPtr)(&data));
598 }
599 
operator ->() const600 const POVMSObjectPtr POVMS_Object::operator->() const
601 {
602 	return (const POVMSObjectPtr)(&data);
603 }
604 
operator ()()605 POVMSObject POVMS_Object::operator()()
606 {
607 	POVMS_Object tc(*this);
608 	POVMSObject t = *((POVMSObjectPtr)(&tc.data));
609 	tc.DetachData();
610 	return t;
611 }
612 
SetString(POVMSType key,const char * str)613 void POVMS_Object::SetString(POVMSType key, const char *str)
614 {
615 	int err;
616 
617 	err = POVMSUtil_SetString(&data, key, str);
618 	if(err != kNoErr)
619 		throw err;
620 }
621 
SetInt(POVMSType key,POVMSInt value)622 void POVMS_Object::SetInt(POVMSType key, POVMSInt value)
623 {
624 	int err;
625 
626 	err = POVMSUtil_SetInt(&data, key, value);
627 	if(err != kNoErr)
628 		throw err;
629 }
630 
SetLong(POVMSType key,POVMSLong value)631 void POVMS_Object::SetLong(POVMSType key, POVMSLong value)
632 {
633 	int err;
634 
635 	err = POVMSUtil_SetLong(&data, key, value);
636 	if(err != kNoErr)
637 		throw err;
638 }
639 
SetFloat(POVMSType key,POVMSFloat value)640 void POVMS_Object::SetFloat(POVMSType key, POVMSFloat value)
641 {
642 	int err;
643 
644 	err = POVMSUtil_SetFloat(&data, key, value);
645 	if(err != kNoErr)
646 		throw err;
647 }
648 
SetBool(POVMSType key,POVMSBool value)649 void POVMS_Object::SetBool(POVMSType key, POVMSBool value)
650 {
651 	int err;
652 
653 	err = POVMSUtil_SetBool(&data, key, value);
654 	if(err != kNoErr)
655 		throw err;
656 }
657 
SetType(POVMSType key,POVMSType value)658 void POVMS_Object::SetType(POVMSType key, POVMSType value)
659 {
660 	int err;
661 
662 	err = POVMSUtil_SetType(&data, key, value);
663 	if(err != kNoErr)
664 		throw err;
665 }
666 
GetStringLength(POVMSType key)667 int POVMS_Object::GetStringLength(POVMSType key)
668 {
669 	int len = 0;
670 	int err;
671 
672 	err = POVMSUtil_GetStringLength(&data, key, &len);
673 	if(err != kNoErr)
674 		throw err;
675 
676 	return len;
677 }
678 
GetString(POVMSType key,char * str,int maxlen)679 int POVMS_Object::GetString(POVMSType key, char *str, int maxlen)
680 {
681 	int err;
682 
683 	err = POVMSUtil_GetString(&data, key, str, &maxlen);
684 	if(err != kNoErr)
685 		throw err;
686 
687 	return maxlen;
688 }
689 
GetInt(POVMSType key)690 POVMSInt POVMS_Object::GetInt(POVMSType key)
691 {
692 	POVMSInt value;
693 	int err;
694 
695 	err = POVMSUtil_GetInt(&data, key, &value);
696 	if(err != kNoErr)
697 		throw err;
698 
699 	return value;
700 }
701 
GetLong(POVMSType key)702 POVMSLong POVMS_Object::GetLong(POVMSType key)
703 {
704 	POVMSLong value;
705 	int err;
706 
707 	err = POVMSUtil_GetLong(&data, key, &value);
708 	if(err != kNoErr)
709 		throw err;
710 
711 	return value;
712 }
713 
GetFloat(POVMSType key)714 POVMSFloat POVMS_Object::GetFloat(POVMSType key)
715 {
716 	POVMSFloat value;
717 	int err;
718 
719 	err = POVMSUtil_GetFloat(&data, key, &value);
720 	if(err != kNoErr)
721 		throw err;
722 
723 	return value;
724 }
725 
GetBool(POVMSType key)726 POVMSBool POVMS_Object::GetBool(POVMSType key)
727 {
728 	POVMSBool value;
729 	int err;
730 
731 	err = POVMSUtil_GetBool(&data, key, &value);
732 	if(err != kNoErr)
733 		throw err;
734 
735 	return value;
736 }
737 
GetType(POVMSType key)738 POVMSType POVMS_Object::GetType(POVMSType key)
739 {
740 	POVMSType value;
741 	int err;
742 
743 	err = POVMSUtil_GetType(&data, key, &value);
744 	if(err != kNoErr)
745 		throw err;
746 
747 	return value;
748 }
749 
ReadHeader(POVMSStream * stream,int & objectsize)750 bool POVMS_Object::ReadHeader(POVMSStream *stream, int& objectsize)
751 {
752 	char header[8];
753 	POVMSInt datasize = 0;
754 	POVMSInt version = 0;
755 	POVMSInt objsize = 0;
756 	POVMSInt maxsize = 16;
757 
758 	objectsize = 0;
759 
760 	if(stream == NULL)
761 		return false;
762 
763 	datasize += POVMSStream_ReadString(header, stream, 8, &maxsize);               // header       8 byte
764 	if(!((header[0] == 'P') && (header[1] == 'O') && (header[2] == 'V') && (header[3] == 'R') &&
765 	     (header[4] == 'A') && (header[5] == 'Y') && (header[6] == 'M') && (header[7] == 'S')))
766 		return false;
767 
768 	datasize += POVMSStream_ReadInt(&version, stream + datasize, &maxsize);        // version      4 byte
769 	if(version != 0x0351)
770 		return false;
771 
772 	datasize += POVMSStream_ReadInt(&objsize, stream + datasize, &maxsize);        // object size   4 byte
773 	if(objsize == 0)
774 		return false;
775 
776 	if((datasize != 16) || (maxsize != 0))
777 		return false;
778 
779 	objectsize = objsize;
780 
781 	return true;
782 }
783 
ReadObject(POVMSStream * stream,int objectsize)784 bool POVMS_Object::ReadObject(POVMSStream *stream, int objectsize)
785 {
786 	int err;
787 
788 	if(stream == NULL)
789 		return false;
790 	if(objectsize == 0)
791 		return false;
792 
793 	err = POVMSObject_Delete(&data);
794 	if(err != kNoErr)
795 		return false;
796 
797 	err = POVMSStream_Read(&data, stream, &objectsize);
798 	if(err != kNoErr)
799 		return false;
800 	if(objectsize != 0)
801 		return false;
802 
803 	return true;
804 }
805 
WriteHeader(POVMSStream * stream,int & objectsize)806 bool POVMS_Object::WriteHeader(POVMSStream *stream, int& objectsize)
807 {
808 	POVMSInt datasize = 0;
809 	POVMSInt maxsize = 16;
810 
811 	objectsize = 0;
812 
813 	if(stream == NULL)
814 		return false;
815 
816 	objectsize = POVMSStream_Size(&data);
817 	if(objectsize == 0)
818 		return false;
819 
820 	datasize += POVMSStream_WriteString("POVRAYMS", stream, &maxsize);             // header       8 byte
821 	datasize += POVMSStream_WriteInt(0x0351, stream + datasize, &maxsize);         // version      4 byte
822 	datasize += POVMSStream_WriteInt(objectsize, stream + datasize, &maxsize);     // object size  4 byte
823 
824 	if((datasize != 16) || (maxsize != 0))
825 		return false;
826 
827 	return true;
828 }
829 
WriteObject(POVMSStream * stream,int objectsize)830 bool POVMS_Object::WriteObject(POVMSStream *stream, int objectsize)
831 {
832 	POVMSInt datasize = 0;
833 
834 	if(stream == NULL)
835 		return false;
836 	if(objectsize == 0)
837 		return false;
838 
839 	datasize += POVMSStream_Write(&data, stream, &objectsize);                       // object       x byte
840 
841 	if(objectsize != 0)
842 		return false;
843 
844 	return true;
845 }
846 
847 
848 /*****************************************************************************
849 *
850 * CLASS
851 *   POVMS_Message
852 *
853 * DESCRIPTION
854 *   Class handling messages contained in POVMSObjects.
855 *
856 * CHANGES
857 *   -
858 *
859 ******************************************************************************/
860 
POVMS_Message(POVMSType objclass,POVMSType msgclass,POVMSType msgid)861 POVMS_Message::POVMS_Message(POVMSType objclass, POVMSType msgclass, POVMSType msgid) : POVMS_Object(objclass)
862 {
863 	int err;
864 
865 	err = POVMSMsg_SetupMessage(&data, msgclass, msgid);
866 	if(err != kNoErr)
867 		throw err;
868 }
869 
POVMS_Message(POVMSObject & convert)870 POVMS_Message::POVMS_Message(POVMSObject& convert) : POVMS_Object(convert)
871 {
872 }
873 
POVMS_Message(POVMSObjectPtr convert)874 POVMS_Message::POVMS_Message(POVMSObjectPtr convert) : POVMS_Object(convert)
875 {
876 }
877 
POVMS_Message(POVMS_Object & source)878 POVMS_Message::POVMS_Message(POVMS_Object& source) : POVMS_Object(source.data)
879 {
880 }
881 
POVMS_Message(POVMS_Message & source)882 POVMS_Message::POVMS_Message(POVMS_Message& source) : POVMS_Object(source.data)
883 {
884 }
885 
operator =(POVMS_Message & source)886 POVMS_Message& POVMS_Message::operator=(POVMS_Message& source)
887 {
888 	int err;
889 
890 	err = POVMSObject_Delete(&data);
891 	if(err == kNoErr)
892 		err = POVMSObject_Copy(&source.data, &data);
893 	if(err != kNoErr)
894 		throw err;
895 
896 	return *this;
897 }
898 
GetClass()899 POVMSType POVMS_Message::GetClass()
900 {
901 	POVMSType type;
902 	int err;
903 
904 	err = POVMSMsg_GetMessageClass(&data, &type);
905 	if(err != kNoErr)
906 		throw err;
907 
908 	return type;
909 }
910 
GetIdentifier()911 POVMSType POVMS_Message::GetIdentifier()
912 {
913 	POVMSType type;
914 	int err;
915 
916 	err = POVMSMsg_GetMessageIdentifier(&data, &type);
917 	if(err != kNoErr)
918 		throw err;
919 
920 	return type;
921 }
922 
GetSourceAddress()923 POVMSAddress POVMS_Message::GetSourceAddress()
924 {
925 	POVMSAddress addr;
926 	int err;
927 
928 	err = POVMSMsg_GetSourceAddress(&data, &addr);
929 	if(err != kNoErr)
930 		throw err;
931 
932 	return addr;
933 }
934 
GetDestinationAddress()935 POVMSAddress POVMS_Message::GetDestinationAddress()
936 {
937 	POVMSAddress addr;
938 	int err;
939 
940 	err = POVMSMsg_GetDestinationAddress(&data, &addr);
941 	if(err != kNoErr)
942 		throw err;
943 
944 	return addr;
945 }
946 
SetDestinationAddress(POVMSAddress addr)947 void POVMS_Message::SetDestinationAddress(POVMSAddress addr)
948 {
949 	int err;
950 
951 	err = POVMSMsg_SetDestinationAddress(&data, addr);
952 	if(err != kNoErr)
953 		throw err;
954 }
955 
956 
957 /*****************************************************************************
958 *
959 * CLASS
960 *   POVMS_MessageReceiver
961 *
962 * DESCRIPTION
963 *   Class receiving messages.
964 *
965 * CHANGES
966 *   -
967 *
968 ******************************************************************************/
969 
POVMS_MessageReceiver(POVMSContext contextref)970 POVMS_MessageReceiver::POVMS_MessageReceiver(POVMSContext contextref)
971 {
972 	context = contextref;
973 	receivers = NULL;
974 }
975 
~POVMS_MessageReceiver()976 POVMS_MessageReceiver::~POVMS_MessageReceiver()
977 {
978 	while(receivers != NULL)
979 		RemoveNode(receivers);
980 
981 	receivers = NULL;
982 	context = NULL;
983 }
984 
Remove(POVMSType hclass,POVMSType hid)985 void POVMS_MessageReceiver::Remove(POVMSType hclass, POVMSType hid)
986 {
987 	HandlerNode *nodeptr = NULL;
988 
989 	for(nodeptr = receivers; nodeptr != NULL; nodeptr = nodeptr->next)
990 	{
991 		if((nodeptr->hclass == hclass) && ((nodeptr->hid == hid) || (hid == kPOVMSType_WildCard)))
992 		{
993 			RemoveNode(nodeptr);
994 			nodeptr = receivers;
995 		}
996 	}
997 }
998 
ReceiveHandler(POVMSObjectPtr msg,POVMSObjectPtr result,int mode,void * privatedataptr)999 int POVMS_MessageReceiver::ReceiveHandler(POVMSObjectPtr msg, POVMSObjectPtr result, int mode, void *privatedataptr)
1000 {
1001 	POVMS_MessageReceiver *self = (POVMS_MessageReceiver *)privatedataptr;
1002 	HandlerNode *nodeptr = NULL;
1003 	POVMSType hclass = kPOVMSType_Null;
1004 	POVMSType hid = kPOVMSType_Null;
1005 	int err = kNoErr;
1006 
1007 	if(self == NULL)
1008 		err = kParamErr;
1009 	if(err == kNoErr)
1010 		err = POVMSMsg_GetMessageClass(msg, &hclass);
1011 	if(err == kNoErr)
1012 		err = POVMSUtil_GetType(msg, kPOVMSMessageIdentID, &hid);
1013 	if(err == kNoErr)
1014 	{
1015 		for(nodeptr = self->receivers; nodeptr != NULL; nodeptr = nodeptr->next)
1016 		{
1017 			if((nodeptr->hclass == hclass) && ((nodeptr->hid == hid) || (nodeptr->hid == kPOVMSType_WildCard)))
1018 			{
1019 				try
1020 				{
1021 					if(nodeptr->handleroo != NULL)
1022 					{
1023 						POVMS_Message msg_obj(msg);
1024 						POVMS_Message result_obj(result);
1025 
1026 						nodeptr->handleroo->Call(msg_obj, result_obj, mode);
1027 
1028 						msg_obj.DetachData();
1029 						if(result != NULL)
1030 							*result = result_obj();
1031 						result_obj.DetachData();
1032 					}
1033 					else if(nodeptr->handler != NULL)
1034 						nodeptr->handler->Call(msg, result, mode);
1035 					else
1036 						err = kNullPointerErr;
1037 				}
1038 				catch(int e)
1039 				{
1040 					err = e;
1041 				}
1042 				catch(...)
1043 				{
1044 					err = kParamErr;
1045 				}
1046 			}
1047 		}
1048 	}
1049 
1050 	return err;
1051 }
1052 
AddNodeFront(POVMSType hclass,POVMSType hid,HandlerOO * hooptr,Handler * hptr)1053 void POVMS_MessageReceiver::AddNodeFront(POVMSType hclass, POVMSType hid, HandlerOO *hooptr, Handler *hptr)
1054 {
1055 	HandlerNode *nodeptr = new HandlerNode;
1056 	int err = kNoErr;
1057 
1058 	nodeptr->last = NULL;
1059 	nodeptr->next = NULL;
1060 	nodeptr->hclass = hclass;
1061 	nodeptr->hid = hid;
1062 	nodeptr->handleroo = hooptr;
1063 	nodeptr->handler = hptr;
1064 
1065 	err = POVMS_InstallReceiver(context, ReceiveHandler, hclass, hid, (void *)this);
1066 	if(err != kNoErr)
1067 		throw err;
1068 
1069 	nodeptr->last = NULL;
1070 	nodeptr->next = receivers;
1071 	if(nodeptr->next != NULL)
1072 		nodeptr->next->last = nodeptr;
1073 	receivers = nodeptr;
1074 }
1075 
AddNodeBack(POVMSType hclass,POVMSType hid,HandlerOO * hooptr,Handler * hptr)1076 void POVMS_MessageReceiver::AddNodeBack(POVMSType hclass, POVMSType hid, HandlerOO *hooptr, Handler *hptr)
1077 {
1078 	HandlerNode *nodeptr = new HandlerNode;
1079 	HandlerNode *iptr = NULL;
1080 	int err = kNoErr;
1081 
1082 	nodeptr->last = NULL;
1083 	nodeptr->next = NULL;
1084 	nodeptr->hclass = hclass;
1085 	nodeptr->hid = hid;
1086 	nodeptr->handleroo = hooptr;
1087 	nodeptr->handler = hptr;
1088 
1089 	err = POVMS_InstallReceiver(context, ReceiveHandler, hclass, hid, (void *)this);
1090 	if(err != kNoErr)
1091 		throw err;
1092 
1093 	if(receivers == NULL)
1094 	{
1095 		nodeptr->last = NULL;
1096 		nodeptr->next = NULL;
1097 		if(nodeptr->next != NULL)
1098 			nodeptr->next->last = nodeptr;
1099 		receivers = nodeptr;
1100 	}
1101 	else
1102 	{
1103 		iptr = receivers;
1104 		while(iptr->next != NULL)
1105 			iptr = iptr->next;
1106 		nodeptr->last = iptr;
1107 		nodeptr->next = NULL;
1108 		iptr->next = nodeptr;
1109 	}
1110 }
1111 
RemoveNode(HandlerNode * nodeptr)1112 void POVMS_MessageReceiver::RemoveNode(HandlerNode *nodeptr)
1113 {
1114 	if(nodeptr != NULL)
1115 	{
1116 		(void)POVMS_RemoveReceiver(context, nodeptr->hclass, nodeptr->hid);
1117 
1118 		if(nodeptr->last != NULL)
1119 			nodeptr->last->next = nodeptr->next;
1120 		if(nodeptr->next != NULL)
1121 			nodeptr->next->last = nodeptr->last;
1122 		if(receivers == nodeptr)
1123 			receivers = nodeptr->next;
1124 
1125 		if(nodeptr->handleroo != NULL)
1126 			delete nodeptr->handleroo;
1127 		if(nodeptr->handler != NULL)
1128 			delete nodeptr->handler;
1129 
1130 		delete nodeptr;
1131 	}
1132 }
1133 
1134 
1135 /*****************************************************************************
1136 *
1137 * FUNCTION
1138 *   POVMS_Send
1139 *
1140 * DESCRIPTION
1141 *   POVMS_SendMessage same as POVMS_Send in povms.cpp, but takes
1142 *   POVMS_Messages objects as arguments.
1143 *
1144 * CHANGES
1145 *   -
1146 *
1147 ******************************************************************************/
1148 
POVMS_SendMessage(POVMSContext contextref,POVMS_Message & msg,POVMS_Message * result,int mode)1149 void POVMS_SendMessage(POVMSContext contextref, POVMS_Message& msg, POVMS_Message *result, int mode)
1150 {
1151 	int err;
1152 
1153 	if(result != NULL)
1154 		err = POVMS_Send(contextref, &msg.data, &result->data, mode);
1155 	else
1156 		err = POVMS_Send(contextref, &msg.data, NULL, mode);
1157 
1158 	if(err != kNoErr)
1159 		throw err;
1160 
1161 	msg.DetachData();
1162 }
1163