Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

Value.cpp

Go to the documentation of this file.
00001 // Value.cpp: implementation of the CValue class.
00002 // developed at Eindhoven University of Technology, 1997
00003 // by the OOPS team
00005 /*
00006  * Copyright (c) 1996-2000 Erwin Coumans <coockie@acm.org>
00007  *
00008  * Permission to use, copy, modify, distribute and sell this software
00009  * and its documentation for any purpose is hereby granted without fee,
00010  * provided that the above copyright notice appear in all copies and
00011  * that both that copyright notice and this permission notice appear
00012  * in supporting documentation.  Erwin Coumans makes no
00013  * representations about the suitability of this software for any
00014  * purpose.  It is provided "as is" without express or implied warranty.
00015  *
00016  */
00017 
00018 
00019 #include "Value.h"
00020 #include "FloatValue.h"
00021 #include "IntValue.h"
00022 #include "VectorValue.h"
00023 #include "VoidValue.h"
00024 #include "StringValue.h"
00025 #include "ErrorValue.h"
00026 #include "ListValue.h"
00027 
00028 //#include "FactoryManager.h"
00029 
00031 // Construction/Destruction
00033 
00034 double CValue::m_sZeroVec[3] = {0.0,0.0,0.0};
00035 
00036 #ifndef NO_EXP_PYTHON_EMBEDDING
00037 
00038 PyObject* cvalue_add(PyObject*v, PyObject*w)

00039 {
00040         return  ((CValue*)v)->Calc(VALUE_ADD_OPERATOR,(CValue*)w);
00041 }
00042 PyObject* cvalue_sub(PyObject*v, PyObject*w)

00043 {
00044         return  ((CValue*)v)->Calc(VALUE_SUB_OPERATOR,(CValue*)w);
00045 }
00046 PyObject* cvalue_mul(PyObject*v, PyObject*w)

00047 {
00048         return  ((CValue*)v)->Calc(VALUE_MUL_OPERATOR,(CValue*)w);
00049 }
00050 PyObject* cvalue_div(PyObject*v, PyObject*w)

00051 {
00052         return  ((CValue*)v)->Calc(VALUE_DIV_OPERATOR,(CValue*)w);
00053 }
00054 PyObject* cvalue_neg(PyObject*v)

00055 {
00056         return  ((CValue*)v)->Calc(VALUE_NEG_OPERATOR,(CValue*)v);
00057 }
00058 
00059 int MyPyCompare (PyObject* v,PyObject* w)

00060 {
00061         CValue* eqval =  ((CValue*)v)->Calc(VALUE_EQL_OPERATOR,(CValue*)w);
00062         CCString txt = eqval->GetText();
00063         eqval->Release();
00064         if (txt=="TRUE")
00065                 return 0;
00066         CValue* lessval =  ((CValue*)v)->Calc(VALUE_LES_OPERATOR,(CValue*)w);
00067         txt = lessval->GetText();
00068         lessval->Release();
00069         if (txt=="TRUE")
00070                 return -1;
00071 
00072         return 1;
00073 }
00074 
00075 
00076 int cvalue_coerce(PyObject** pv,PyObject** pw)

00077 {
00078         if (PyInt_Check(*pw)) {
00079                 double db  = (double)PyInt_AsLong(*pw);
00080                 *pw = new CIntValue(db);
00081                 Py_INCREF(*pv);
00082                 return 0;
00083         }
00084         else if (PyLong_Check(*pw)) {
00085                 double db = PyLong_AsDouble(*pw);
00086                 *pw = new CFloatValue(db);
00087                 Py_INCREF(*pv);
00088                 return 0;
00089         }
00090         else if (PyFloat_Check(*pw)) {
00091                 double db = PyFloat_AsDouble(*pw);
00092                 *pw = new CFloatValue(db);
00093                 Py_INCREF(*pv);
00094                 return 0;
00095         } else if (PyString_Check(*pw)) {
00096                 const CCString str = PyString_AsString(*pw);
00097                 *pw = new CStringValue(str,"");
00098                 Py_INCREF(*pv);
00099                 return 0;
00100         }
00101         return 1; /* Can't do it */
00102 
00103 }
00104 static PyNumberMethods cvalue_as_number = {
00105         (binaryfunc)cvalue_add, /*nb_add*/
00106         (binaryfunc)cvalue_sub, /*nb_subtract*/
00107         (binaryfunc)cvalue_mul, /*nb_multiply*/
00108         (binaryfunc)cvalue_div, /*nb_divide*/
00109         0,//(binaryfunc)cvalue_remainder,       /*nb_remainder*/
00110         0,//(binaryfunc)cvalue_divmod,  /*nb_divmod*/
00111         0,//0,//0,//0,//(ternaryfunc)cvalue_pow, /*nb_power*/
00112         (unaryfunc)cvalue_neg, /*nb_negative*/
00113         0,//(unaryfunc)cvalue_pos, /*nb_positive*/
00114         0,//(unaryfunc)cvalue_abs, /*nb_absolute*/
00115         0,//(inquiry)cvalue_nonzero, /*nb_nonzero*/
00116         0,              /*nb_invert*/
00117         0,              /*nb_lshift*/
00118         0,              /*nb_rshift*/
00119         0,              /*nb_and*/
00120         0,              /*nb_xor*/
00121         0,              /*nb_or*/
00122         (coercion)cvalue_coerce, /*nb_coerce*/
00123         0,//(unaryfunc)cvalue_int, /*nb_int*/
00124         0,//(unaryfunc)cvalue_long, /*nb_long*/
00125         0,//(unaryfunc)cvalue_float, /*nb_float*/
00126         0,              /*nb_oct*/
00127         0,              /*nb_hex*/
00128 };
00129 
00130 
00131 PyTypeObject CValue::Type = {
00132         PyObject_HEAD_INIT(&PyType_Type)
00133         0,
00134         "CValue",
00135         sizeof(CValue),
00136         0,
00137         PyDestructor,
00138         0,
00139         __getattr,
00140         __setattr,
00141         &MyPyCompare,
00142         __repr,
00143         &cvalue_as_number,
00144         0,
00145         0,
00146         0,
00147         0
00148 };
00149 
00150 PyParentObject CValue::Parents[] = {
00151         &CValue::Type,
00152                 NULL
00153 };
00154 
00155 PyMethodDef CValue::Methods[] = {
00156         { "printHello", (PyCFunction) CValue::sPyPrintHello, Py_NEWARGS},
00157         { "getName", (PyCFunction) CValue::sPyGetName, Py_NEWARGS},
00158         {NULL,NULL} //Sentinel
00159 };
00160 
00161 PyObject* CValue::PyGetName(PyObject* self,PyObject* args,PyObject* kwds)

00162 {
00163         PyObject* pyname = PyString_FromString(this->GetName());
00164         return pyname;
00165 }
00166 
00167 
00168 
00169 CValue::CValue(PyTypeObject *T)
00170                 : PyObjectPlus(T),
00171 #else
00172 CValue::CValue()
00173 : 
00174 #endif //NO_EXP_PYTHON_EMBEDDING
00175         
00176 m_refcount(1),
00177 m_pNamedPropertyArray(NULL)
00178 /*
00179 pre: false

00180 effect: constucts a CValue

00181 */
00182 {
00183         //debug(gRefCountValue++)       // debugging
00184 }
00185 
00186 
00187 
00188 CValue::~CValue()
00189 /*
00190 pre:

00191 effect: deletes the object

00192 */
00193 {
00194         ClearProperties();
00195 
00196         assertd (m_refcount==0);
00197 }
00198 
00199 
00200 
00201 
00202 #define VALUE_SUB(val1, val2) (val1)->Calc(VALUE_SUB_OPERATOR, val2)
00203 #define VALUE_MUL(val1, val2) (val1)->Calc(VALUE_MUL_OPERATOR, val2)
00204 #define VALUE_DIV(val1, val2) (val1)->Calc(VALUE_DIV_OPERATOR, val2)
00205 #define VALUE_NEG(val1)       (val1)->Calc(VALUE_NEG_OPERATOR, val1)
00206 
00207 
00208 CCString CValue::op2str (VALUE_OPERATOR op)

00209 {
00210         //pre:
00211         //ret: the stringrepresentation of operator op
00212         
00213         CCString opmsg;
00214         switch (op) {
00215         case VALUE_ADD_OPERATOR:
00216                 opmsg = " + ";
00217                 break;
00218         case VALUE_SUB_OPERATOR:
00219                 opmsg = " - ";
00220                 break;
00221         case VALUE_MUL_OPERATOR:
00222                 opmsg = " * ";
00223                 break;
00224         case VALUE_DIV_OPERATOR:
00225                 opmsg = " / ";
00226                 break;
00227         case VALUE_NEG_OPERATOR:
00228                 opmsg = " -";
00229                 break;
00230         case VALUE_AND_OPERATOR:
00231                 opmsg = " & ";
00232                 break;
00233         case VALUE_OR_OPERATOR:
00234                 opmsg = " | ";
00235                 break;
00236         case VALUE_EQL_OPERATOR:
00237                 opmsg = " = ";
00238                 break;
00239         case VALUE_NEQ_OPERATOR:
00240                 opmsg = " != ";
00241                 break;
00242         case VALUE_NOT_OPERATOR:
00243                 opmsg = " !";
00244                 break;
00245         default:
00246                 opmsg="Error in Errorhandling routine.";
00247                 //              AfxMessageBox("Invalid operator");
00248                 break;
00249         }
00250         return opmsg;
00251 }
00252 
00253 
00254 
00255 
00256 
00257 //---------------------------------------------------------------------------------------------------------------------
00258 //      Property Management
00259 //---------------------------------------------------------------------------------------------------------------------
00260 
00261 
00262 
00263 //
00264 // Set property <ioProperty>, overwrites and releases a previous property with the same name if needed
00265 //
00266 void CValue::SetProperty(const CCString & name,CValue* ioProperty)

00267 {
00268         // Check if somebody is setting an empty property
00269         if (ioProperty==NULL)
00270         {
00271                 trace("Warning:trying to set empty property!");
00272                 return;
00273         }
00274 
00275         // Make sure we have a property array
00276         if (m_pNamedPropertyArray == NULL)
00277                 m_pNamedPropertyArray = new std::map<const CCString,CValue *>;
00278 
00279         // Try to replace property (if so -> exit as soon as we replaced it)
00280         CValue* oldval = (*m_pNamedPropertyArray)[name];
00281         if (oldval)
00282         {
00283                 oldval->Release();
00284         }
00285         
00286         // Add property at end of array
00287         (*m_pNamedPropertyArray)[name] = ioProperty;//->Add(ioProperty);
00288 }
00289 
00290 
00291 
00292 //
00293 // Get pointer to a property with name <inName>, returns NULL if there is no property named <inName>
00294 //
00295 CValue* CValue::GetProperty(const CCString & inName)

00296 {
00297         // Check properties, as soon as we found it -> Return a pointer to the property
00298         CValue* result = NULL;
00299         if (m_pNamedPropertyArray)
00300         {
00301                 std::map<const CCString,CValue*>::iterator it = (*m_pNamedPropertyArray).find(inName);
00302                 if (!( it==m_pNamedPropertyArray->end()))
00303                 {
00304                         result = (*it).second;
00305                 }
00306 
00307         }
00308                 //for (int i=0; i<m_pValuePropertyArray->size(); i++)
00309                 //      if ((*m_pValuePropertyArray)[i]->GetName() == inName)
00310                 //              return (*m_pValuePropertyArray)[i];
00311         
00312         // Did not find property with name <inName>, return NULL property pointer
00313         return result;
00314 }
00315 
00316 
00317 
00318 //
00319 // Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
00320 //
00321 CCString CValue::GetPropertyText(const CCString & inName,const CCString& deftext)

00322 {
00323         CValue *property = GetProperty(inName);
00324         if (property)
00325                 return property->GetText();
00326         else
00327                 return deftext;//String::sEmpty;
00328 }
00329 
00330 float CValue::GetPropertyNumber(const CCString& inName,float defnumber)

00331 {
00332         CValue *property = GetProperty(inName);
00333         if (property)
00334                 return property->GetNumber();
00335         else
00336                 return defnumber;
00337 }
00338 
00339 
00340 
00341 //
00342 // Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed
00343 //
00344 bool CValue::RemoveProperty(const CCString & inName)

00345 {
00346         // Check if there are properties at all which can be removed
00347         if (m_pNamedPropertyArray == NULL)
00348                 return false;
00349 
00350         // Scan all properties, as soon as we find one with <inName> -> Remove it
00351         CValue* val = (*m_pNamedPropertyArray)[inName];
00352         
00353         return false;
00354 }
00355 
00356 
00357 
00358 //
00359 // Clear all properties
00360 //
00361 void CValue::ClearProperties()

00362 {               
00363         // Check if we have any properties
00364         if (m_pNamedPropertyArray == NULL)
00365                 return;
00366 
00367         // Remove all properties
00368         for ( std::map<const CCString,CValue*>::iterator it = m_pNamedPropertyArray->begin();
00369         !(it == m_pNamedPropertyArray->end());it++)
00370         {
00371                 CValue* tmpval = (*it).second;
00372                 CCString name = (*it).first;
00373                 tmpval->Release();
00374         }
00375 
00376         // Delete property array
00377         delete m_pNamedPropertyArray;
00378         m_pNamedPropertyArray=NULL;
00379 }
00380 
00381 
00382 
00383 //
00384 // Set all properties' modified flag to <inModified>
00385 //
00386 void CValue::SetPropertiesModified(bool inModified)

00387 {
00388         int numprops = GetPropertyCount();
00389         for (int i=0; i<numprops; i++)
00390                 GetProperty(i)->SetModified(inModified);
00391 }
00392 
00393 
00394 
00395 //
00396 // Check if any of the properties in this value have been modified
00397 //
00398 bool CValue::IsAnyPropertyModified()

00399 {
00400         int numprops = GetPropertyCount();
00401         for (int i=0;i<numprops;i++)
00402                 if (GetProperty(i)->IsModified())
00403                         return true;
00404 
00405         return false;
00406 }
00407 
00408 
00409 
00410 //
00411 // Get property number <inIndex>
00412 //
00413 
00414 CValue* CValue::GetProperty(int inIndex)

00415 {
00416 
00417         int count=0;
00418         CValue* result = NULL;
00419 
00420         if (m_pNamedPropertyArray)
00421         {
00422                 for ( std::map<const CCString,CValue*>::iterator it = m_pNamedPropertyArray->begin();
00423                 !(it == m_pNamedPropertyArray->end());it++)
00424                 {
00425                         if (count++==inIndex)
00426                         {
00427                                 result = (*it).second;
00428                                 break;
00429                         }
00430                 }
00431 
00432         }
00433         return result;
00434 }
00435 
00436 
00437 
00438 //
00439 // Get the amount of properties assiocated with this value
00440 //
00441 int CValue::GetPropertyCount()

00442 {
00443         if (m_pNamedPropertyArray)
00444                 return m_pNamedPropertyArray->size();
00445         else
00446                 return 0;
00447 }
00448 
00449 
00450 
00451 
00452 
00453 void CValue::CloneProperties(CValue *replica)

00454 {
00455         
00456         if (m_pNamedPropertyArray)
00457         {
00458                 replica->m_pNamedPropertyArray=NULL;
00459                 for ( std::map<const CCString,CValue*>::iterator it = m_pNamedPropertyArray->begin();
00460                 !(it == m_pNamedPropertyArray->end());it++)
00461                 {
00462                         
00463                         replica->SetProperty((*it).first,(*it).second->GetReplica());
00464                 }
00465         }
00466 
00467         
00468 }
00469 
00470 
00471 
00472 
00473 
00474 
00475 double*         CValue::GetVector3(bool bGetTransformedVec)

00476 {
00477         assertd(false); // don;t get vector from me
00478         return m_sZeroVec;//::sZero;
00479 }
00480 
00481 
00482 
00483 
00484 
00485 
00486 /*---------------------------------------------------------------------------------------------------------------------

00487         Reference Counting

00488 ---------------------------------------------------------------------------------------------------------------------*/
00489 
00490 
00491 
00492 //
00493 // Add a reference to this value
00494 //
00495 CValue *CValue::AddRef()

00496 {
00497         // Increase global reference count, used to see at the end of the program
00498         // if all CValue-derived classes have been dereferenced to 0
00499         //debug(gRefCountValue++);
00500         m_refcount++; 
00501         
00502         return this;
00503 }
00504 
00505 
00506 
00507 //
00508 // Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
00509 //
00510 int     CValue::Release()

00511 {
00512         // Decrease global reference count, used to see at the end of the program
00513         // if all CValue-derived classes have been dereferenced to 0
00514         //debug(gRefCountValue--);
00515         
00516         // Decrease local reference count, if it reaches 0 the object should be freed
00517         if (--m_refcount > 0)
00518         {
00519                 // Reference count normal, return new reference count
00520                 return m_refcount;
00521         }
00522         else
00523         {
00524                 // Reference count reached 0, delete ourselves and return 0
00525 //              assert(m_refcount==0, "Reference count reached sub-zero, object released too much");
00526                 delete this;
00527                 return 0;
00528         }
00529 
00530 }
00531 
00532 
00533 
00534 //
00535 // Disable reference counting for this value
00536 //
00537 void CValue::DisableRefCount()

00538 {
00539         assertd(m_refcount == 1);
00540         m_refcount--;
00541 
00542         //debug(gRefCountValue--);
00543         m_ValFlags.RefCountDisabled=true;
00544 }
00545 
00546 
00547 
00548 void CValue::AddDataToReplica(CValue *replica)

00549 {
00550         replica->m_refcount = 1;
00551 #ifdef _DEBUG
00552         //gRefCountValue++;
00553 #endif
00554         replica->m_ValFlags.RefCountDisabled = false;
00555 
00556         replica->ReplicaSetName(GetName());
00557 
00558         //copy all props
00559         CloneProperties(replica);
00560 }
00561 
00562 
00563 
00564 CValue* CValue::FindIdentifier(const CCString& identifiername)

00565 {
00566 
00567         CValue* result = NULL;
00568 
00569         int pos = 0;
00570         // if a dot exists, explode the name into pieces to get the subcontext
00571         if ((pos=identifiername.Find('.'))>=0)
00572         {
00573                 const CCString rightstring = identifiername.Right(identifiername.Length() -1 - pos);
00574                 const CCString leftstring = identifiername.Left(pos);
00575                 CValue* tempresult = GetProperty(leftstring);
00576                 if (tempresult)
00577                 {
00578                         result=tempresult->FindIdentifier(rightstring);
00579                 } 
00580         } else
00581         {
00582                 result = GetProperty(identifiername);
00583                 int i=0;
00584         }
00585         if (result)
00586                 return result->AddRef();
00587         // warning here !!!
00588         result = new CErrorValue(identifiername+" not found");
00589         return result;
00590 }
00591 
00592 
00593 #ifndef NO_EXP_PYTHON_EMBEDDING
00594 
00595 
00596 static PyMethodDef      CValueMethods[] = 
00597 {
00598         { "new", CValue::PyMake , Py_NEWARGS},
00599         { NULL,NULL}    // Sentinel
00600 };
00601 
00602 
00603 PyObject*       CValue::_getattr(char* attr)

00604 {
00605         PyTypeObject* type = ob_type;
00606         CValue* resultattr = FindIdentifier(attr);
00607         CCString text;
00608         if (resultattr)
00609         {
00610                 if (resultattr->IsError())
00611                 {
00612                         resultattr->Release();
00613                 } else
00614                 {
00615                         // to avoid some compare problems, return a real pythonthing
00616                         PyObject* pyconvert = resultattr->ConvertValueToPython();
00617                         if (pyconvert)
00618                         {
00619                                 resultattr->Release();
00620                                 return pyconvert;
00621                         } else
00622                         {
00623                                 // also check if it's already in pythoninterpreter!
00624                                 return resultattr;
00625                         }
00626                         
00627                 }
00628         }
00629         _getattr_up(PyObjectPlus);
00630 }
00631 
00632 CValue* CValue::ConvertPythonToValue(PyObject* pyobj)

00633 {
00634 
00635         CValue* vallie = NULL;
00636 
00637         PyTypeObject* type = pyobj->ob_type;
00638 
00639         if (type == &PyList_Type)
00640         {
00641                 CListValue* listval = new CListValue();
00642                 bool error = false;
00643 
00644                 int i;
00645                 int numitems = PyList_Size(pyobj);
00646                 for (i=0;i<numitems;i++)
00647                 {
00648                         PyObject* listitem = PyList_GetItem(pyobj,i);
00649                         CValue* listitemval = ConvertPythonToValue(listitem);
00650                         if (listitemval)
00651                         {
00652                                 listval->Add(listitemval);
00653                         } else
00654                         {
00655                                 error = true;
00656                         }
00657                 }
00658                 if (!error)
00659                 {
00660                         // jippie! could be converted
00661                         vallie = listval;
00662                 } else
00663                 {
00664                         // list could not be converted... bad luck
00665                         listval->Release();
00666                 }
00667 
00668         } else
00669         if (type == &PyFloat_Type)
00670         {
00671                 float fl;
00672                 PyArg_Parse(pyobj,"f",&fl);
00673                 vallie = new CFloatValue(fl);
00674         } else
00675         if (type==&PyInt_Type)
00676         {
00677                 int innie;
00678                 PyArg_Parse(pyobj,"i",&innie);
00679                 vallie = new CIntValue(innie);
00680         } else
00681         
00682         if (type==&PyString_Type)
00683         {
00684                 vallie = new CStringValue(PyString_AsString(pyobj),"");
00685         } else
00686         if (type==&CValue::Type || type==&CListValue::Type)
00687         {
00688                 vallie = ((CValue*) pyobj)->AddRef();
00689         }
00690         return vallie;
00691 
00692 }
00693 int     CValue::_setattr(char* attr,PyObject* pyobj)

00694 {
00695         
00696         CValue* vallie = ConvertPythonToValue(pyobj);
00697         if (vallie)
00698         {
00699                 SetProperty(attr,vallie);
00700         }
00701         
00702         //PyObjectPlus::_setattr(attr,value);
00703         return 0;
00704 };
00705 PyObject*       CValue::PyMake(PyObject* ignored,PyObject* args)

00706 {
00707         char* name;
00708         //Py_Try(PyArg_ParseTuple(args,"s",&name));
00709         Py_INCREF(Py_None);
00710         return Py_None;//new CValue();
00711 }
00712 
00713 extern "C" {
00714         void initCValue(void)

00715         {
00716                 Py_InitModule("CValue",CValueMethods);
00717         }
00718 }
00719 
00720 
00721 
00722 #endif //NO_EXP_PYTHON_EMBEDDING
00723 
00728 

Generated at Thu Feb 1 13:03:13 2001 for Ketsji Game Engine by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000