povray/source/base/povmscpp.cpp
2013-11-06 13:07:19 -05:00

1882 lines
40 KiB
C++

/*******************************************************************************
* povmscpp.cpp
*
* This module contains the C++ interface version of povms.cpp
*
* ---------------------------------------------------------------------------
* Persistence of Vision Ray Tracer ('POV-Ray') version 3.7.
* Copyright 1991-2013 Persistence of Vision Raytracer Pty. Ltd.
*
* POV-Ray is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* POV-Ray is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ---------------------------------------------------------------------------
* POV-Ray is based on the popular DKB raytracer version 2.12.
* DKBTrace was originally written by David K. Buck.
* DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
* ---------------------------------------------------------------------------
* $File: //depot/public/povray/3.x/source/base/povmscpp.cpp $
* $Revision: #1 $
* $Change: 6069 $
* $DateTime: 2013/11/06 11:59:40 $
* $Author: chrisc $
*******************************************************************************/
// configbase.h must always be the first POV file included within base *.cpp files
#include "configbase.h"
#include "povmscpp.h"
#include "zlib.h"
// this must be the last file included
#include "base/povdebug.h"
#include <stdlib.h>
#include <string.h>
const POVMSType kPOVMSRawStreamEncoding = 'RAWS';
const POVMSType kPOVMSGZipStreamEncoding = 'GZIP';
POVMSUCS2String POVMS_ASCIItoUCS2String(const char *s)
{
POVMSUCS2String r;
unsigned char ch;
if(s != NULL)
{
while(*s != 0)
{
ch = *s++;
r += (POVMSUCS2)(ch);
}
}
return r;
}
std::string POVMS_UCS2toASCIIString(const POVMSUCS2String& s)
{
std::string r;
for(std::size_t i = 0; i < s.length(); i++)
{
if(s[i] >= 256)
r += ' ';
else
r += (char)(s[i]);
}
return r;
}
/*****************************************************************************
*
* CLASS
* POVMS_Container
*
* DESCRIPTION
* Base class for all other POVMS classes.
*
* CHANGES
* -
*
******************************************************************************/
POVMS_Container::POVMS_Container()
{
data.type = kPOVMSType_Null;
data.size = 0;
data.ptr = NULL;
}
POVMS_Container::~POVMS_Container()
{
// do nothing for now
}
POVMSType POVMS_Container::Type() const
{
return data.type;
}
size_t POVMS_Container::Size() const
{
return data.size;
}
bool POVMS_Container::IsNull() const
{
return (data.type == kPOVMSType_Null);
}
void POVMS_Container::DetachData()
{
data.type = kPOVMSType_Null;
data.size = 0;
data.ptr = NULL;
}
/*****************************************************************************
*
* CLASS
* POVMS_Attribute
*
* DESCRIPTION
* Class handling POVMSAttribute.
*
* CHANGES
* -
*
******************************************************************************/
POVMS_Attribute::POVMS_Attribute()
{
int err;
err = POVMSAttr_New(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
POVMS_Attribute::POVMS_Attribute(const char *str)
{
int err;
err = POVMSAttr_New(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
err = POVMSAttr_Set(&data, kPOVMSType_CString, reinterpret_cast<const void *>(str), strlen(str) + 1);
if(err != pov_base::kNoErr)
{
(void)POVMSAttr_Delete(&data);
throw POV_EXCEPTION_CODE(err);
}
}
POVMS_Attribute::POVMS_Attribute(const POVMSUCS2 *str)
{
int len;
int err;
for(len = 0; str[len] != 0; len++) { }
err = POVMSAttr_New(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
err = POVMSAttr_Set(&data, kPOVMSType_UCS2String, reinterpret_cast<const void *>(str), (len + 1) * 2);
if(err != pov_base::kNoErr)
{
(void)POVMSAttr_Delete(&data);
throw POV_EXCEPTION_CODE(err);
}
}
POVMS_Attribute::POVMS_Attribute(POVMSInt value)
{
int err;
err = POVMSAttr_New(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
err = POVMSAttr_Set(&data, kPOVMSType_Int, (void *)(&value), sizeof(POVMSLong));
if(err != pov_base::kNoErr)
{
(void)POVMSAttr_Delete(&data);
throw POV_EXCEPTION_CODE(err);
}
}
POVMS_Attribute::POVMS_Attribute(POVMSLong value)
{
int err;
err = POVMSAttr_New(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
err = POVMSAttr_Set(&data, kPOVMSType_Long, (void *)(&value), sizeof(POVMSLong));
if(err != pov_base::kNoErr)
{
(void)POVMSAttr_Delete(&data);
throw POV_EXCEPTION_CODE(err);
}
}
POVMS_Attribute::POVMS_Attribute(POVMSFloat value)
{
int err;
err = POVMSAttr_New(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
err = POVMSAttr_Set(&data, kPOVMSType_Float, (void *)(&value), sizeof(POVMSFloat));
if(err != pov_base::kNoErr)
{
(void)POVMSAttr_Delete(&data);
throw POV_EXCEPTION_CODE(err);
}
}
POVMS_Attribute::POVMS_Attribute(bool b)
{
POVMSBool value = (POVMSBool)b;
int err;
err = POVMSAttr_New(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
err = POVMSAttr_Set(&data, kPOVMSType_Bool, (void *)(&value), sizeof(POVMSBool));
if(err != pov_base::kNoErr)
{
(void)POVMSAttr_Delete(&data);
throw POV_EXCEPTION_CODE(err);
}
}
POVMS_Attribute::POVMS_Attribute(POVMSType value)
{
int err;
err = POVMSAttr_New(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
err = POVMSAttr_Set(&data, kPOVMSType_Type, (void *)(&value), sizeof(POVMSType));
if(err != pov_base::kNoErr)
{
(void)POVMSAttr_Delete(&data);
throw POV_EXCEPTION_CODE(err);
}
}
POVMS_Attribute::POVMS_Attribute(std::vector<POVMSInt>& value)
{
int err;
err = POVMSAttr_New(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
err = POVMSAttr_Set(&data, kPOVMSType_VectorInt, (void *)(&value[0]), sizeof(POVMSInt) * value.size());
if(err != pov_base::kNoErr)
{
(void)POVMSAttr_Delete(&data);
throw POV_EXCEPTION_CODE(err);
}
}
POVMS_Attribute::POVMS_Attribute(std::vector<POVMSLong>& value)
{
int err;
err = POVMSAttr_New(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
err = POVMSAttr_Set(&data, kPOVMSType_VectorLong, (void *)(&value[0]), sizeof(POVMSLong) * value.size());
if(err != pov_base::kNoErr)
{
(void)POVMSAttr_Delete(&data);
throw POV_EXCEPTION_CODE(err);
}
}
POVMS_Attribute::POVMS_Attribute(std::vector<POVMSFloat>& value)
{
int err;
err = POVMSAttr_New(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
err = POVMSAttr_Set(&data, kPOVMSType_VectorFloat, (void *)(&value[0]), sizeof(POVMSFloat) * value.size());
if(err != pov_base::kNoErr)
{
(void)POVMSAttr_Delete(&data);
throw POV_EXCEPTION_CODE(err);
}
}
POVMS_Attribute::POVMS_Attribute(std::vector<POVMSType>& value)
{
int err;
err = POVMSAttr_New(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
err = POVMSAttr_Set(&data, kPOVMSType_VectorType, (void *)(&value[0]), sizeof(POVMSType) * value.size());
if(err != pov_base::kNoErr)
{
(void)POVMSAttr_Delete(&data);
throw POV_EXCEPTION_CODE(err);
}
}
POVMS_Attribute::POVMS_Attribute(POVMSAttribute& convert)
{
data = convert;
}
POVMS_Attribute::POVMS_Attribute(const POVMS_Attribute& source)
{
int err;
err = POVMSAttr_Copy(&source.data, &data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
POVMS_Attribute::~POVMS_Attribute()
{
int err;
err = POVMSAttr_Delete(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
POVMS_Attribute& POVMS_Attribute::operator=(const POVMS_Attribute& source)
{
int err;
err = POVMSAttr_Delete(&data);
if(err == pov_base::kNoErr)
err = POVMSAttr_Copy(&source.data, &data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return *this;
}
void POVMS_Attribute::Get(POVMSType type, void *data, int *maxdatasize)
{
int err;
err = POVMSAttr_Get(&this->data, type, data, maxdatasize);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
void POVMS_Attribute::Set(POVMSType type, const void *data, int datasize)
{
int err;
err = POVMSAttr_Set(&this->data, type, data, datasize);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
int POVMS_Attribute::GetStringLength() const // Note: Includes trailing \0 character code!
{
return Size();
}
int POVMS_Attribute::GetString(char *str, int maxlen)
{
Get(kPOVMSType_CString, (void *)str, &maxlen);
return maxlen;
}
std::string POVMS_Attribute::GetString()
{
int len = Size();
char *strptr = new char[len];
try
{
Get(kPOVMSType_CString, (void *)strptr, &len);
std::string str(strptr);
delete[] strptr;
return str;
}
catch(pov_base::Exception&)
{
delete[] strptr;
throw;
}
return std::string();
}
int POVMS_Attribute::GetUCS2StringLength() const // Note: Includes trailing \0 character code!
{
return Size() / 2;
}
int POVMS_Attribute::GetUCS2String(POVMSUCS2 *str, int maxlen)
{
maxlen /= 2;
Get(kPOVMSType_UCS2String, (void *)str, &maxlen);
return maxlen / 2;
}
POVMSUCS2String POVMS_Attribute::GetUCS2String()
{
int len = Size();
POVMSUCS2 *strptr = new POVMSUCS2[len / 2];
try
{
Get(kPOVMSType_UCS2String, (void *)strptr, &len);
POVMSUCS2String str(strptr);
delete[] strptr;
return str;
}
catch(pov_base::Exception&)
{
delete[] strptr;
throw;
}
return POVMSUCS2String();
}
POVMSInt POVMS_Attribute::GetInt()
{
POVMSInt result;
int len = sizeof(result);
Get(kPOVMSType_Int, (void *)&result, &len);
return result;
}
POVMSLong POVMS_Attribute::GetLong()
{
POVMSLong result;
int len = sizeof(result);
Get(kPOVMSType_Long, (void *)&result, &len);
return result;
}
POVMSFloat POVMS_Attribute::GetFloat()
{
POVMSFloat result;
int len = sizeof(result);
Get(kPOVMSType_Float, (void *)&result, &len);
return result;
}
POVMSBool POVMS_Attribute::GetBool()
{
POVMSBool result;
int len = sizeof(result);
Get(kPOVMSType_Bool, (void *)&result, &len);
return result;
}
POVMSType POVMS_Attribute::GetType()
{
POVMSType result;
int len = sizeof(result);
Get(kPOVMSType_Type, (void *)&result, &len);
return result;
}
std::vector<POVMSInt> POVMS_Attribute::GetIntVector()
{
std::vector<POVMSInt> result;
result.resize(GetVectorSize());
int len = result.size() * sizeof(POVMSInt);
Get(kPOVMSType_VectorInt, (void *)&result[0], &len);
return result;
}
std::vector<POVMSLong> POVMS_Attribute::GetLongVector()
{
std::vector<POVMSLong> result;
result.resize(GetVectorSize());
int len = result.size() * sizeof(POVMSLong);
Get(kPOVMSType_VectorLong, (void *)&result[0], &len);
return result;
}
std::vector<POVMSFloat> POVMS_Attribute::GetFloatVector()
{
std::vector<POVMSFloat> result;
result.resize(GetVectorSize());
int len = result.size() * sizeof(POVMSFloat);
Get(kPOVMSType_VectorFloat, (void *)&result[0], &len);
return result;
}
std::vector<POVMSType> POVMS_Attribute::GetTypeVector()
{
std::vector<POVMSType> result;
result.resize(GetVectorSize());
int len = result.size() * sizeof(POVMSType);
Get(kPOVMSType_VectorType, (void *)&result[0], &len);
return result;
}
int POVMS_Attribute::GetVectorSize() const
{
switch(Type())
{
case kPOVMSType_VectorInt:
return Size() / sizeof(POVMSInt);
case kPOVMSType_VectorLong:
return Size() / sizeof(POVMSLong);
case kPOVMSType_VectorFloat:
return Size() / sizeof(POVMSFloat);
case kPOVMSType_VectorType:
return Size() / sizeof(POVMSType);
default:
throw POV_EXCEPTION_CODE(pov_base::kCannotHandleDataErr);
}
return 0;
}
/*****************************************************************************
*
* CLASS
* POVMS_List
*
* DESCRIPTION
* Class handling POVMSAttributeList.
*
* CHANGES
* -
*
******************************************************************************/
POVMS_List::POVMS_List()
{
int err;
err = POVMSAttrList_New(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
POVMS_List::POVMS_List(POVMSAttributeList& convert)
{
data = convert;
}
POVMS_List::POVMS_List(const POVMS_List& source)
{
int err;
err = POVMSAttrList_Copy(&source.data, &data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
POVMS_List::~POVMS_List()
{
int err;
err = POVMSAttrList_Delete(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
POVMS_List& POVMS_List::operator=(const POVMS_List& source)
{
int err;
err = POVMSAttrList_Delete(&data);
if(err == pov_base::kNoErr)
err = POVMSAttrList_Copy(&source.data, &data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return *this;
}
void POVMS_List::Append(POVMS_Attribute& item)
{
int err;
err = POVMSAttrList_Append(&data, &item.data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
item.DetachData();
}
void POVMS_List::Append(POVMS_List& item)
{
int err;
err = POVMSAttrList_Append(&data, &item.data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
item.DetachData();
}
void POVMS_List::Append(POVMS_Object& item)
{
int err;
err = POVMSAttrList_Append(&data, &item.data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
item.DetachData();
}
void POVMS_List::AppendN(int cnt, POVMS_Attribute& item)
{
for(; cnt > 0; cnt--) // TODO - make more efficient
Append(item);
}
void POVMS_List::AppendN(int cnt, POVMS_List& item)
{
for(; cnt > 0; cnt--) // TODO - make more efficient
Append(item);
}
void POVMS_List::AppendN(int cnt, POVMS_Object& item)
{
for(; cnt > 0; cnt--) // TODO - make more efficient
Append(item);
}
void POVMS_List::GetNth(int index, POVMS_Attribute& item)
{
int err;
err = POVMSAttr_Delete(&item.data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
err = POVMSAttrList_GetNth(&data, index, &item.data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
void POVMS_List::GetNth(int index, POVMS_List& item)
{
int err;
err = POVMSAttrList_Delete(&item.data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
err = POVMSAttrList_GetNth(&data, index, &item.data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
void POVMS_List::GetNth(int index, POVMS_Object& item)
{
int err;
err = POVMSObject_Delete(&item.data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
err = POVMSAttrList_GetNth(&data, index, &item.data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
void POVMS_List::SetNth(int index, POVMS_Attribute& item)
{
int err;
err = POVMSAttrList_SetNth(&data, index, &item.data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
item.DetachData();
}
void POVMS_List::SetNth(int index, POVMS_List& item)
{
int err;
err = POVMSAttrList_SetNth(&data, index, &item.data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
item.DetachData();
}
void POVMS_List::SetNth(int index, POVMS_Object& item)
{
int err;
err = POVMSAttrList_SetNth(&data, index, &item.data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
item.DetachData();
}
void POVMS_List::RemoveNth(int index)
{
int err;
err = POVMSAttrList_RemoveNth(&data, index);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
void POVMS_List::Clear()
{
int err;
err = POVMSAttrList_Clear(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
int POVMS_List::GetListSize()
{
int len = 0;
int err;
err = POVMSAttrList_Count(&data, &len);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return len;
}
/*****************************************************************************
*
* CLASS
* POVMS_Object
*
* DESCRIPTION
* Class handling POVMSObject.
*
* CHANGES
* -
*
******************************************************************************/
POVMS_Object::POVMS_Object()
{
// Null object!
}
POVMS_Object::POVMS_Object(POVMSType objclass)
{
int err;
err = POVMSObject_New(&data, objclass);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
POVMS_Object::POVMS_Object(POVMSObject& convert)
{
data = convert;
}
POVMS_Object::POVMS_Object(POVMSObjectPtr convert)
{
if(convert != NULL)
data = *convert;
}
POVMS_Object::POVMS_Object(const POVMS_Object& source)
{
if(source.IsNull() == false)
{
int err;
err = POVMSObject_Copy(&source.data, &data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
}
POVMS_Object::~POVMS_Object()
{
int err;
err = POVMSObject_Delete(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
POVMS_Object& POVMS_Object::operator=(const POVMS_Object& source)
{
int err;
err = POVMSObject_Delete(&data);
if((err == pov_base::kNoErr) && (IsNull() == false))
err = POVMSObject_Copy(&source.data, &data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return *this;
}
void POVMS_Object::Get(POVMSType key, POVMS_Attribute& attr)
{
int err;
err = POVMSAttr_Delete(&attr.data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
err = POVMSObject_Get(&data, &attr.data, key);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
void POVMS_Object::Get(POVMSType key, POVMS_List& attr)
{
int err;
err = POVMSAttrList_Delete(&attr.data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
err = POVMSObject_Get(&data, &attr.data, key);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
void POVMS_Object::Get(POVMSType key, POVMS_Object& attr)
{
int err;
err = POVMSObject_Delete(&attr.data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
err = POVMSObject_Get(&data, &attr.data, key);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
void POVMS_Object::Set(POVMSType key, POVMS_Attribute& attr)
{
int err;
err = POVMSObject_Set(&data, &attr.data, key);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
attr.DetachData();
}
void POVMS_Object::Set(POVMSType key, POVMS_List& attr)
{
int err;
err = POVMSObject_Set(&data, &attr.data, key);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
attr.DetachData();
}
void POVMS_Object::Set(POVMSType key, POVMS_Object& attr)
{
int err;
err = POVMSObject_Set(&data, &attr.data, key);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
attr.DetachData();
}
void POVMS_Object::Remove(POVMSType key)
{
int err;
err = POVMSObject_Remove(&data, key);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
bool POVMS_Object::Exist(POVMSType key)
{
return (POVMSObject_Exist(&data, key) == pov_base::kNoErr);
}
void POVMS_Object::Merge(POVMS_Object& source)
{
int err;
err = POVMSObject_Merge(&source.data, &data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
const POVMSObject& POVMS_Object::operator*() const
{
return *((const POVMSObject*)(&data));
}
const POVMSObject* POVMS_Object::operator->() const
{
return (const POVMSObject*)(&data);
}
POVMSObject POVMS_Object::operator()()
{
POVMS_Object tc(*this);
POVMSObject t = *((POVMSObjectPtr)(&tc.data));
tc.DetachData();
return t;
}
void POVMS_Object::SetString(POVMSType key, const char *str)
{
int err;
err = POVMSUtil_SetString(&data, key, str);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
void POVMS_Object::SetUCS2String(POVMSType key, const POVMSUCS2 *str)
{
int err;
err = POVMSUtil_SetUCS2String(&data, key, str);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
void POVMS_Object::SetInt(POVMSType key, POVMSInt value)
{
int err;
err = POVMSUtil_SetInt(&data, key, value);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
void POVMS_Object::SetLong(POVMSType key, POVMSLong value)
{
int err;
err = POVMSUtil_SetLong(&data, key, value);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
void POVMS_Object::SetFloat(POVMSType key, POVMSFloat value)
{
int err;
err = POVMSUtil_SetFloat(&data, key, value);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
void POVMS_Object::SetBool(POVMSType key, POVMSBool value)
{
int err;
err = POVMSUtil_SetBool(&data, key, value);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
void POVMS_Object::SetType(POVMSType key, POVMSType value)
{
int err;
err = POVMSUtil_SetType(&data, key, value);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
void POVMS_Object::SetIntVector(POVMSType key, std::vector<POVMSInt>& value)
{
POVMS_Attribute attr(value);
Set(key, attr);
}
void POVMS_Object::SetLongVector(POVMSType key, std::vector<POVMSLong>& value)
{
POVMS_Attribute attr(value);
Set(key, attr);
}
void POVMS_Object::SetFloatVector(POVMSType key, std::vector<POVMSFloat>& value)
{
POVMS_Attribute attr(value);
Set(key, attr);
}
void POVMS_Object::SetTypeVector(POVMSType key, std::vector<POVMSType>& value)
{
POVMS_Attribute attr(value);
Set(key, attr);
}
int POVMS_Object::GetStringLength(POVMSType key)
{
int len = 0;
int err;
err = POVMSUtil_GetStringLength(&data, key, &len);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return len;
}
int POVMS_Object::GetString(POVMSType key, char *str, int maxlen)
{
int err;
err = POVMSUtil_GetString(&data, key, str, &maxlen);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return maxlen;
}
std::string POVMS_Object::GetString(POVMSType key)
{
int len = 0;
int err;
err = POVMSUtil_GetStringLength(&data, key, &len);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
char *strptr = new char[len];
err = POVMSUtil_GetString(&data, key, strptr, &len);
if(err != pov_base::kNoErr)
{
delete[] strptr;
throw POV_EXCEPTION_CODE(err);
}
std::string str(strptr);
delete[] strptr;
return str;
}
int POVMS_Object::GetUCS2StringLength(POVMSType key)
{
int len = 0;
int err;
err = POVMSUtil_GetUCS2StringLength(&data, key, &len);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return len;
}
int POVMS_Object::GetUCS2String(POVMSType key, POVMSUCS2 *str, int maxlen)
{
int err;
err = POVMSUtil_GetUCS2String(&data, key, str, &maxlen);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return maxlen;
}
POVMSUCS2String POVMS_Object::GetUCS2String(POVMSType key)
{
int len = 0;
int err;
err = POVMSUtil_GetUCS2StringLength(&data, key, &len);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
POVMSUCS2 *strptr = new POVMSUCS2[len];
err = POVMSUtil_GetUCS2String(&data, key, strptr, &len);
if(err != pov_base::kNoErr)
{
delete[] strptr;
throw POV_EXCEPTION_CODE(err);
}
POVMSUCS2String str(strptr);
delete[] strptr;
return str;
}
POVMSInt POVMS_Object::GetInt(POVMSType key)
{
POVMSInt value;
int err;
err = POVMSUtil_GetInt(&data, key, &value);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return value;
}
POVMSLong POVMS_Object::GetLong(POVMSType key)
{
POVMSLong value;
int err;
err = POVMSUtil_GetLong(&data, key, &value);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return value;
}
POVMSFloat POVMS_Object::GetFloat(POVMSType key)
{
POVMSFloat value;
int err;
err = POVMSUtil_GetFloat(&data, key, &value);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return value;
}
POVMSBool POVMS_Object::GetBool(POVMSType key)
{
POVMSBool value;
int err;
err = POVMSUtil_GetBool(&data, key, &value);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return value;
}
POVMSType POVMS_Object::GetType(POVMSType key)
{
POVMSType value;
int err;
err = POVMSUtil_GetType(&data, key, &value);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return value;
}
std::vector<POVMSInt> POVMS_Object::GetIntVector(POVMSType key)
{
POVMS_Attribute attr;
Get(key, attr);
return attr.GetIntVector();
}
std::vector<POVMSLong> POVMS_Object::GetLongVector(POVMSType key)
{
POVMS_Attribute attr;
Get(key, attr);
return attr.GetLongVector();
}
std::vector<POVMSFloat> POVMS_Object::GetFloatVector(POVMSType key)
{
POVMS_Attribute attr;
Get(key, attr);
return attr.GetFloatVector();
}
std::vector<POVMSType> POVMS_Object::GetTypeVector(POVMSType key)
{
POVMS_Attribute attr;
Get(key, attr);
return attr.GetTypeVector();
}
std::string POVMS_Object::TryGetString(POVMSType key, const char *alt)
{
if(Exist(key) == true)
return GetString(key);
return std::string(alt);
}
std::string POVMS_Object::TryGetString(POVMSType key, const std::string& alt)
{
if(Exist(key) == true)
return GetString(key);
return alt;
}
POVMSUCS2String POVMS_Object::TryGetUCS2String(POVMSType key, const char *alt)
{
if(Exist(key) == true)
return GetUCS2String(key);
return POVMS_ASCIItoUCS2String(alt);
}
POVMSUCS2String POVMS_Object::TryGetUCS2String(POVMSType key, const POVMSUCS2String& alt)
{
if(Exist(key) == true)
return GetUCS2String(key);
return alt;
}
POVMSInt POVMS_Object::TryGetInt(POVMSType key, POVMSInt alt)
{
if(Exist(key) == true)
return GetInt(key);
return alt;
}
POVMSLong POVMS_Object::TryGetLong(POVMSType key, POVMSLong alt)
{
if(Exist(key) == true)
return GetLong(key);
return alt;
}
POVMSFloat POVMS_Object::TryGetFloat(POVMSType key, POVMSFloat alt)
{
if(Exist(key) == true)
return GetFloat(key);
return alt;
}
POVMSBool POVMS_Object::TryGetBool(POVMSType key, POVMSBool alt)
{
if(Exist(key) == true)
return GetBool(key);
return alt;
}
POVMSType POVMS_Object::TryGetType(POVMSType key, POVMSType alt)
{
if(Exist(key) == true)
return GetType(key);
return alt;
}
void POVMS_Object::Read(InputStream& stream, bool continued, bool headeronly)
{
POVMSStream headerstream[16];
POVMSStream *objectstream = NULL;
POVMSStream *compressedstream = NULL;
int err = pov_base::kNoErr;
int maxheadersize = 0;
int datasize = 0;
try
{
err = POVMSObject_Delete(&data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
if(continued == false)
{
char header[8];
POVMSInt version = 0;
if(!stream.read((void *)headerstream, 12))
throw POV_EXCEPTION_CODE(pov_base::kFileDataErr);
datasize = 0;
maxheadersize = 12; // header
datasize += POVMSStream_ReadString(header, headerstream + datasize, 8, &maxheadersize); // header 8 byte
if(!((header[0] == 'P') && (header[1] == 'O') && (header[2] == 'V') && (header[3] == 'R') &&
(header[4] == 'A') && (header[5] == 'Y') && (header[6] == 'M') && (header[7] == 'S')))
throw POV_EXCEPTION_CODE(pov_base::kVersionErr);
datasize += POVMSStream_ReadInt(&version, headerstream + datasize, &maxheadersize); // version 4 byte
if(version != 0x0370)
throw POV_EXCEPTION_CODE(pov_base::kVersionErr);
}
if(headeronly == false)
{
POVMSInt objectsize = 0;
POVMSType encoding = kPOVMSRawStreamEncoding;
if(!stream.read((void *)headerstream, 8))
throw POV_EXCEPTION_CODE(pov_base::kFileDataErr);
datasize = 0;
maxheadersize = 8; // header
datasize += POVMSStream_ReadInt(&objectsize, headerstream + datasize, &maxheadersize); // data size 4 byte
if(objectsize == 0)
throw POV_EXCEPTION_CODE(pov_base::kFileDataErr);
datasize += POVMSStream_ReadType(&encoding, headerstream + datasize, &maxheadersize); // encoding 4 byte
if(encoding == kPOVMSRawStreamEncoding)
{
objectstream = new POVMSStream[objectsize];
if(!stream.read((void *)objectstream, objectsize)) // object x byte
throw POV_EXCEPTION_CODE(pov_base::kFileDataErr);
if(POVMSStream_Read(&data, objectstream, &objectsize) == 0)
throw POV_EXCEPTION_CODE(pov_base::kFileDataErr);
}
else if(encoding == kPOVMSGZipStreamEncoding)
{
int compressedsize = objectsize;
datasize = 0;
maxheadersize = 4; // header
if(!stream.read((void *)headerstream, 4))
throw POV_EXCEPTION_CODE(pov_base::kFileDataErr);
datasize += POVMSStream_ReadInt(&objectsize, headerstream + datasize, &maxheadersize); // object size 4 byte
if(objectsize == 0)
throw POV_EXCEPTION_CODE(pov_base::kFileDataErr);
compressedstream = new POVMSStream[compressedsize];
objectstream = new POVMSStream[objectsize];
if(!stream.read((void *)compressedstream, compressedsize)) // data x byte
throw POV_EXCEPTION_CODE(pov_base::kFileDataErr);
// uncompress stream data
uLongf destlen = (uLongf)objectsize;
if(uncompress((Bytef *)(objectstream), &destlen, (Bytef *)(compressedstream), (uLongf)(compressedsize)) != Z_OK)
throw POV_EXCEPTION_CODE(pov_base::kCannotHandleDataErr);
if(POVMSStream_Read(&data, objectstream, &objectsize) == 0)
throw POV_EXCEPTION_CODE(pov_base::kFileDataErr);
}
else
throw POV_EXCEPTION_CODE(pov_base::kCannotHandleDataErr);
}
if(objectstream != NULL)
delete[] objectstream;
objectstream = NULL;
if(compressedstream != NULL)
delete[] compressedstream;
compressedstream = NULL;
}
catch(...)
{
if(objectstream != NULL)
delete[] objectstream;
if(compressedstream != NULL)
delete[] compressedstream;
throw;
}
}
void POVMS_Object::Write(OutputStream& stream, bool append, bool compress)
{
POVMSType encoding = kPOVMSRawStreamEncoding;
POVMSStream headerstream[16];
POVMSStream *objectstream = NULL;
POVMSStream *compressedstream = NULL;
int maxheadersize = 0;
int maxobjectsize = 0;
int objectsize = 0;
int datasize = 0;
try
{
objectsize = POVMSStream_Size(&data);
if(objectsize == 0)
throw POV_EXCEPTION_CODE(pov_base::kNullPointerErr);
if(append == false)
{
datasize = 0;
maxheadersize = 12; // header
datasize += POVMSStream_WriteString("POVRAYMS", headerstream + datasize, &maxheadersize); // header 8 byte
datasize += POVMSStream_WriteInt(0x0370, headerstream + datasize, &maxheadersize); // version 4 byte
if(!stream.write((void *)headerstream, datasize))
throw POV_EXCEPTION_CODE(pov_base::kFileDataErr);
}
objectstream = new POVMSStream[objectsize];
maxobjectsize = objectsize;
(void)POVMSStream_Write(&data, objectstream, &maxobjectsize);
#ifdef POVMS_COMPRESSION_ENABLED
if(compress == true)
{
compressedstream = new POVMSStream[objectsize * 2];
// compress stream data
uLongf destlen = (uLongf)(objectsize * 2);
if(compress2((Bytef *)(compressedstream), &destlen, (Bytef *)(objectstream), (uLongf)(objectsize), Z_BEST_COMPRESSION) != Z_OK)
throw POV_EXCEPTION_CODE(pov_base::kCannotHandleDataErr);
datasize = 0;
maxheadersize = 12; // header
datasize += POVMSStream_WriteInt((POVMSInt)(destlen), headerstream + datasize, &maxheadersize); // data size 4 byte
datasize += POVMSStream_WriteType(kPOVMSGZipStreamEncoding, headerstream + datasize, &maxheadersize); // encoding 4 byte
datasize += POVMSStream_WriteInt(objectsize, headerstream + datasize, &maxheadersize); // object size 4 byte
if(!stream.write((void *)headerstream, datasize))
throw POV_EXCEPTION_CODE(pov_base::kFileDataErr);
if(!stream.write((void *)compressedstream, (int)(destlen))) // data x byte
throw POV_EXCEPTION_CODE(pov_base::kFileDataErr);
}
else
#endif
{
datasize = 0;
maxheadersize = 8; // header
datasize += POVMSStream_WriteInt(objectsize, headerstream + datasize, &maxheadersize); // object size 4 byte
datasize += POVMSStream_WriteType(kPOVMSRawStreamEncoding, headerstream + datasize, &maxheadersize); // encoding 4 byte
if(!stream.write((void *)headerstream, datasize))
throw POV_EXCEPTION_CODE(pov_base::kFileDataErr);
if(!stream.write((void *)objectstream, objectsize)) // object x byte
throw POV_EXCEPTION_CODE(pov_base::kFileDataErr);
}
if(objectstream != NULL)
delete[] objectstream;
objectstream = NULL;
if(compressedstream != NULL)
delete[] compressedstream;
compressedstream = NULL;
}
catch(...)
{
if(objectstream != NULL)
delete[] objectstream;
if(compressedstream != NULL)
delete[] compressedstream;
throw;
}
}
/*****************************************************************************
*
* CLASS
* POVMS_Message
*
* DESCRIPTION
* Class handling messages contained in POVMSObjects.
*
* CHANGES
* -
*
******************************************************************************/
POVMS_Message::POVMS_Message()
{
// Null object!
}
POVMS_Message::POVMS_Message(POVMSType objclass, POVMSType msgclass, POVMSType msgid) : POVMS_Object(objclass)
{
int err;
err = POVMSMsg_SetupMessage(&data, msgclass, msgid);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
POVMS_Message::POVMS_Message(POVMS_Object& convert, POVMSType msgclass, POVMSType msgid) : POVMS_Object(convert)
{
int err;
err = POVMSMsg_SetupMessage(&data, msgclass, msgid);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
POVMS_Message::POVMS_Message(POVMSObject& convert) : POVMS_Object(convert)
{
}
POVMS_Message::POVMS_Message(POVMSObjectPtr convert) : POVMS_Object(convert)
{
}
POVMS_Message::POVMS_Message(const POVMS_Message& source) : POVMS_Object(source)
{
}
POVMS_Message& POVMS_Message::operator=(const POVMS_Message& source)
{
int err;
err = POVMSObject_Delete(&data);
if((err == pov_base::kNoErr) && (source.IsNull() == false))
err = POVMSObject_Copy(&source.data, &data);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return *this;
}
POVMSType POVMS_Message::GetClass()
{
POVMSType type;
int err;
err = POVMSMsg_GetMessageClass(&data, &type);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return type;
}
POVMSType POVMS_Message::GetIdentifier()
{
POVMSType type;
int err;
err = POVMSMsg_GetMessageIdentifier(&data, &type);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return type;
}
POVMSAddress POVMS_Message::GetSourceAddress()
{
POVMSAddress addr;
int err;
err = POVMSMsg_GetSourceAddress(&data, &addr);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return addr;
}
POVMSAddress POVMS_Message::GetDestinationAddress()
{
POVMSAddress addr;
int err;
err = POVMSMsg_GetDestinationAddress(&data, &addr);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
return addr;
}
void POVMS_Message::SetSourceAddress(POVMSAddress addr)
{
int err;
err = POVMSMsg_SetSourceAddress(&data, addr);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
void POVMS_Message::SetDestinationAddress(POVMSAddress addr)
{
int err;
err = POVMSMsg_SetDestinationAddress(&data, addr);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
}
/*****************************************************************************
*
* CLASS
* POVMS_MessageReceiver
*
* DESCRIPTION
* Class receiving messages.
*
* CHANGES
* -
*
******************************************************************************/
POVMS_MessageReceiver::POVMS_MessageReceiver(POVMSContext contextref)
{
context = contextref;
receivers = NULL;
}
POVMS_MessageReceiver::~POVMS_MessageReceiver()
{
while(receivers != NULL)
RemoveNode(receivers);
receivers = NULL;
context = NULL;
}
void POVMS_MessageReceiver::Remove(POVMSType hclass, POVMSType hid)
{
HandlerNode *nodeptr = NULL;
for(nodeptr = receivers; nodeptr != NULL; nodeptr = nodeptr->next)
{
if((nodeptr->hclass == hclass) && ((nodeptr->hid == hid) || (hid == kPOVMSType_WildCard)))
{
RemoveNode(nodeptr);
nodeptr = receivers;
}
}
}
int POVMS_MessageReceiver::ReceiveHandler(POVMSObjectPtr msg, POVMSObjectPtr result, int mode, void *privatedataptr)
{
POVMS_MessageReceiver *self = (POVMS_MessageReceiver *)privatedataptr;
HandlerNode *nodeptr = NULL;
POVMSType hclass = kPOVMSType_Null;
POVMSType hid = kPOVMSType_Null;
int err = pov_base::kNoErr;
if(self == NULL)
err = pov_base::kParamErr;
if(err == pov_base::kNoErr)
err = POVMSMsg_GetMessageClass(msg, &hclass);
if(err == pov_base::kNoErr)
err = POVMSUtil_GetType(msg, kPOVMSMessageIdentID, &hid);
for(nodeptr = self->receivers; nodeptr != NULL && err == pov_base::kNoErr; nodeptr = nodeptr->next)
{
if((nodeptr->hclass == hclass) && ((nodeptr->hid == hid) || (nodeptr->hid == kPOVMSType_WildCard)))
{
if(nodeptr->handleroo != NULL)
{
POVMS_Message result_obj(result);
POVMS_Message msg_obj(msg);
// Note: This try-catch block is only required because msg_obj.DetachData always has to be executed! [trf]
try
{
nodeptr->handleroo->Call(msg_obj, result_obj, mode);
}
catch(...)
{
// result and msg no longer own their resources; if we don't clear them here,
// we can get a double-free in a parent method when this method throws an exception.
// an example of this is when create scene fails with an out-of-memory exception.
memset(result, 0, sizeof(*result));
memset(msg, 0, sizeof(*msg));
msg_obj.DetachData();
throw;
}
msg_obj.DetachData();
if((result != NULL) && (result_obj.IsNull() == false))
*result = result_obj();
}
else if(nodeptr->handler != NULL)
nodeptr->handler->Call(msg, result, mode);
else
err = pov_base::kNullPointerErr;
}
}
return err;
}
void POVMS_MessageReceiver::AddNodeFront(POVMSType hclass, POVMSType hid, HandlerOO *hooptr, Handler *hptr)
{
HandlerNode *nodeptr = new HandlerNode;
int err = pov_base::kNoErr;
nodeptr->last = NULL;
nodeptr->next = NULL;
nodeptr->hclass = hclass;
nodeptr->hid = hid;
nodeptr->handleroo = hooptr;
nodeptr->handler = hptr;
err = POVMS_InstallReceiver(context, ReceiveHandler, hclass, hid, (void *)this);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
nodeptr->last = NULL;
nodeptr->next = receivers;
if(nodeptr->next != NULL)
nodeptr->next->last = nodeptr;
receivers = nodeptr;
}
void POVMS_MessageReceiver::AddNodeBack(POVMSType hclass, POVMSType hid, HandlerOO *hooptr, Handler *hptr)
{
HandlerNode *nodeptr = new HandlerNode;
HandlerNode *iptr = NULL;
int err = pov_base::kNoErr;
nodeptr->last = NULL;
nodeptr->next = NULL;
nodeptr->hclass = hclass;
nodeptr->hid = hid;
nodeptr->handleroo = hooptr;
nodeptr->handler = hptr;
err = POVMS_InstallReceiver(context, ReceiveHandler, hclass, hid, (void *)this);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
if(receivers == NULL)
{
nodeptr->last = NULL;
nodeptr->next = NULL;
if(nodeptr->next != NULL)
nodeptr->next->last = nodeptr;
receivers = nodeptr;
}
else
{
iptr = receivers;
while(iptr->next != NULL)
iptr = iptr->next;
nodeptr->last = iptr;
nodeptr->next = NULL;
iptr->next = nodeptr;
}
}
void POVMS_MessageReceiver::RemoveNode(HandlerNode *nodeptr)
{
if(nodeptr != NULL)
{
(void)POVMS_RemoveReceiver(context, nodeptr->hclass, nodeptr->hid);
if(nodeptr->last != NULL)
nodeptr->last->next = nodeptr->next;
if(nodeptr->next != NULL)
nodeptr->next->last = nodeptr->last;
if(receivers == nodeptr)
receivers = nodeptr->next;
if(nodeptr->handleroo != NULL)
delete nodeptr->handleroo;
if(nodeptr->handler != NULL)
delete nodeptr->handler;
delete nodeptr;
}
}
/*****************************************************************************
*
* FUNCTION
* POVMS_Send
*
* DESCRIPTION
* POVMS_SendMessage same as POVMS_Send in povms.cpp, but takes
* only a POVMS_Message object as arguments and sends it using
* kPOVMSSendMode_NoReply mode. Note that sending using this mode
* does not require a POVMS context, which makes sending messages
* from any thread really easy as long as no reply is needed.
*
* CHANGES
* -
*
******************************************************************************/
void POVMS_SendMessage(POVMS_Message& msg)
{
int err;
err = POVMS_Send(NULL, &msg.data, NULL, kPOVMSSendMode_NoReply);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
msg.DetachData();
}
/*****************************************************************************
*
* FUNCTION
* POVMS_Send
*
* DESCRIPTION
* POVMS_SendMessage same as POVMS_Send in povms.cpp, but takes
* POVMS_Messages objects as arguments.
*
* CHANGES
* -
*
******************************************************************************/
void POVMS_SendMessage(POVMSContext contextref, POVMS_Message& msg, POVMS_Message *result, int mode)
{
int err;
if(result != NULL)
err = POVMS_Send(contextref, &msg.data, &result->data, mode);
else
err = POVMS_Send(contextref, &msg.data, NULL, mode);
if(err != pov_base::kNoErr)
throw POV_EXCEPTION_CODE(err);
msg.DetachData();
}