game engine python api
[blender.git] / source / gameengine / Expressions / ListValue.cpp
1 // ListValue.cpp: implementation of the CListValue class.
2 //
3 //////////////////////////////////////////////////////////////////////
4 /*
5  * Copyright (c) 1996-2000 Erwin Coumans <coockie@acm.org>
6  *
7  * Permission to use, copy, modify, distribute and sell this software
8  * and its documentation for any purpose is hereby granted without fee,
9  * provided that the above copyright notice appear in all copies and
10  * that both that copyright notice and this permission notice appear
11  * in supporting documentation.  Erwin Coumans makes no
12  * representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied warranty.
14  *
15  */
16
17 #include "ListValue.h"
18 #include "StringValue.h"
19 #include "VoidValue.h"
20 #include <algorithm>
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #if  ((PY_MAJOR_VERSION == 2) &&(PY_MINOR_VERSION < 5))
27 #define Py_ssize_t int
28 #endif
29
30 Py_ssize_t listvalue_bufferlen(PyObject* list)
31 {
32         return (Py_ssize_t)( ((CListValue*)list)->GetCount());
33 }
34
35 PyObject* listvalue_buffer_item(PyObject* list,Py_ssize_t index)
36 {
37         if (index >= 0 && index < ((CListValue*) list)->GetCount())
38         {
39                 PyObject* pyobj = ((CListValue*) list)->GetValue(index)->ConvertValueToPython();
40                 if (pyobj)
41                         return pyobj;
42                 else
43                         return ((CListValue*) list)->GetValue(index)->AddRef();
44
45         }
46         PyErr_SetString(PyExc_IndexError, "Python ListIndex out of range");
47         return NULL;
48 }
49
50 PyObject* listvalue_mapping_subscript(PyObject* list,PyObject* pyindex)
51 {
52         if (PyString_Check(pyindex))
53         {
54                 STR_String  index(PyString_AsString(pyindex));
55                 CValue *item = ((CListValue*) list)->FindValue(index);
56                 if (item)
57                         return (PyObject*) item;
58                         
59         }
60         if (PyInt_Check(pyindex))
61         {
62                 int index = PyInt_AsLong(pyindex);
63                 return listvalue_buffer_item(list, index);
64         }
65         
66         PyObject *pyindex_str = PyObject_Repr(pyindex); /* new ref */
67         STR_String index_str(PyString_AsString(pyindex_str));
68         PyErr_Format(PyExc_KeyError, "'%s' not in list", index_str.Ptr());
69         Py_DECREF(pyindex_str);
70         return NULL;
71 }
72
73
74 /* just slice it into a python list... */
75 PyObject* listvalue_buffer_slice(PyObject* list,Py_ssize_t ilow, Py_ssize_t ihigh)
76 {
77         int i, j;
78         PyListObject *newlist;
79
80         if (ilow < 0) ilow = 0;
81
82         int n = ((CListValue*) list)->GetCount();
83
84         if (ihigh >= n)
85                 ihigh = n;
86     if (ihigh < ilow)
87         ihigh = ilow;
88
89         newlist = (PyListObject *) PyList_New(ihigh - ilow);
90         if (!newlist)
91                 return NULL;
92
93         for (i = ilow, j = 0; i < ihigh; i++, j++)
94         {
95                 PyObject* pyobj = ((CListValue*) list)->GetValue(i)->ConvertValueToPython();
96                 if (!pyobj)
97                         pyobj = ((CListValue*) list)->GetValue(i)->AddRef();
98                 newlist->ob_item[j] = pyobj;
99         }       
100         return (PyObject *) newlist;
101 }
102
103
104
105 static PyObject *
106 listvalue_buffer_concat(PyObject * self, PyObject * other)
107 {
108         // for now, we support CListValue concatenated with items
109         // and CListValue concatenated to Python Lists
110         // and CListValue concatenated with another CListValue
111
112         CListValue* listval = (CListValue*) self;
113         listval->AddRef();
114         if (other->ob_type == &PyList_Type)
115         {
116                 bool error = false;
117
118                 int i;
119                 int numitems = PyList_Size(other);
120                 for (i=0;i<numitems;i++)
121                 {
122                         PyObject* listitem = PyList_GetItem(other,i);
123                         CValue* listitemval = listval->ConvertPythonToValue(listitem);
124                         if (listitemval)
125                         {
126                                 listval->Add(listitemval);
127                         } else
128                         {
129                                 error = true;
130                         }
131                 }
132
133                 if (error) {
134                         PyErr_SetString(PyExc_SystemError, "Python Error: couldn't add one or more items to a list");
135                         return NULL;
136                 }
137
138         } else
139         {
140                 if (other->ob_type == &CListValue::Type)
141                 {
142                         // add items from otherlist to this list
143                         CListValue* otherval = (CListValue*) other;
144                         
145
146                         for (int i=0;i<otherval->GetCount();i++)
147                         {
148                                 otherval->Add(listval->GetValue(i)->AddRef());
149                         }
150                 }
151                 else
152                 {
153                         CValue* objval = listval->ConvertPythonToValue(other);
154                         if (objval)
155                         {
156                                 listval->Add(objval);
157                         } else
158                         {
159                                 PyErr_SetString(PyExc_SystemError, "Python Error: couldn't add item to a list");  
160                                 return NULL;
161                         }
162                 }
163         }
164
165         return self;
166 }
167
168
169
170 static  PySequenceMethods listvalue_as_sequence = {
171         listvalue_bufferlen,//(inquiry)buffer_length, /*sq_length*/
172         listvalue_buffer_concat, /*sq_concat*/
173         NULL, /*sq_repeat*/
174         listvalue_buffer_item, /*sq_item*/
175         listvalue_buffer_slice, /*sq_slice*/
176         NULL, /*sq_ass_item*/
177         NULL /*sq_ass_slice*/
178 };
179
180
181
182 /* Is this one used ? */
183 static  PyMappingMethods instance_as_mapping = {
184         listvalue_bufferlen, /*mp_length*/
185         listvalue_mapping_subscript, /*mp_subscript*/
186         NULL /*mp_ass_subscript*/
187 };
188
189
190
191 PyTypeObject CListValue::Type = {
192         PyObject_HEAD_INIT(&PyType_Type)
193         0,                              /*ob_size*/
194         "CListValue",                   /*tp_name*/
195         sizeof(CListValue),             /*tp_basicsize*/
196         0,                              /*tp_itemsize*/
197         /* methods */
198         PyDestructor,                   /*tp_dealloc*/
199         0,                              /*tp_print*/
200         __getattr,                      /*tp_getattr*/
201         __setattr,                      /*tp_setattr*/
202         0,                              /*tp_compare*/
203         __repr,                         /*tp_repr*/
204         0,                              /*tp_as_number*/
205         &listvalue_as_sequence, /*tp_as_sequence*/
206         &instance_as_mapping,           /*tp_as_mapping*/
207         0,                              /*tp_hash*/
208         0,                              /*tp_call */
209 };
210
211
212
213 PyParentObject CListValue::Parents[] = {
214         &CListValue::Type,
215         &CValue::Type,
216                 NULL
217 };
218
219
220
221
222 PyMethodDef CListValue::Methods[] = {
223         {"append", (PyCFunction)CListValue::sPyappend,METH_VARARGS},
224         {"reverse", (PyCFunction)CListValue::sPyreverse,METH_VARARGS},
225         {"index", (PyCFunction)CListValue::sPyindex,METH_VARARGS},
226         {"count", (PyCFunction)CListValue::sPycount,METH_VARARGS},
227         
228         {NULL,NULL} //Sentinel
229 };
230
231
232
233 PyObject* CListValue::_getattr(const STR_String& attr) {
234         _getattr_up(CValue);
235 }
236
237
238 //////////////////////////////////////////////////////////////////////
239 // Construction/Destruction
240 //////////////////////////////////////////////////////////////////////
241
242 CListValue::CListValue(PyTypeObject *T ) 
243 : CPropValue(T)
244 {
245         m_bReleaseContents=true;        
246 }
247
248
249
250 CListValue::~CListValue()
251 {
252
253         if (m_bReleaseContents) {
254                 for (unsigned int i=0;i<m_pValueArray.size();i++) {
255                         m_pValueArray[i]->Release();
256                 }
257         }
258 }
259
260
261 static STR_String gstrListRep=STR_String("List");
262
263 const STR_String & CListValue::GetText()
264 {
265         gstrListRep = "[";
266         STR_String commastr = "";
267
268         for (int i=0;i<GetCount();i++)
269         {
270                 gstrListRep += commastr;
271                 gstrListRep += GetValue(i)->GetText();
272                 commastr = ",";
273         }
274         gstrListRep += "]";
275
276         return gstrListRep;
277 }
278
279
280
281 CValue* CListValue::GetReplica() { 
282         CListValue* replica = new CListValue(*this);
283
284         CValue::AddDataToReplica(replica);
285
286         replica->m_bReleaseContents=true; // for copy, complete array is copied for now...
287         // copy all values
288         int numelements = m_pValueArray.size();
289         unsigned int i=0;
290         replica->m_pValueArray.resize(numelements);
291         for (i=0;i<m_pValueArray.size();i++)
292                 replica->m_pValueArray[i] = m_pValueArray[i]->GetReplica();
293
294
295         return replica;
296 };
297
298
299
300 void CListValue::SetValue(int i, CValue *val)
301 {
302         assertd(i < m_pValueArray.size());
303         m_pValueArray[i]=val;
304 }
305
306
307
308 void CListValue::Resize(int num)
309 {
310         m_pValueArray.resize(num);
311 }
312
313
314
315 void CListValue::Remove(int i)
316 {
317         assertd(i<m_pValueArray.size());
318         m_pValueArray.erase(m_pValueArray.begin()+i);
319 }
320
321
322
323 void CListValue::ReleaseAndRemoveAll()
324 {
325         for (unsigned int i=0;i<m_pValueArray.size();i++)
326                 m_pValueArray[i]->Release();
327         m_pValueArray.clear();//.Clear();
328 }
329
330
331
332 CValue* CListValue::FindValue(const STR_String & name)
333 {
334         CValue* resultval = NULL;
335         int i=0;
336         
337         while (!resultval && i < GetCount())
338         {
339                 CValue* myval = GetValue(i);
340                                 
341                 if (myval->GetName() == name)
342                         resultval = GetValue(i)->AddRef(); // add referencecount
343                 else
344                         i++;
345                 
346         }
347         return resultval;
348 }
349
350
351
352 bool CListValue::SearchValue(CValue *val)
353 {
354         for (int i=0;i<GetCount();i++)
355                 if (val == GetValue(i))
356                         return true;
357         return false;
358 }
359
360
361
362 void CListValue::SetReleaseOnDestruct(bool bReleaseContents)
363 {
364         m_bReleaseContents = bReleaseContents;
365 }
366
367
368
369 bool CListValue::RemoveValue(CValue *val)
370 {
371         bool result=false;
372
373         for (int i=GetCount()-1;i>=0;i--)
374                 if (val == GetValue(i))
375                 {
376                         Remove(i);
377                         result=true;
378                 }
379         return result;
380 }
381
382
383
384 void CListValue::MergeList(CListValue *otherlist)
385 {
386
387         int numelements = this->GetCount();
388         int numotherelements = otherlist->GetCount();
389
390
391         Resize(numelements+numotherelements);
392
393         for (int i=0;i<numotherelements;i++)
394         {
395                 SetValue(i+numelements,otherlist->GetValue(i)->AddRef());
396         }
397
398 }
399
400
401
402 PyObject* CListValue::Pyappend(PyObject* self, 
403                                PyObject* args, 
404                                PyObject* kwds)
405 {
406
407         PyObject* pyobj = NULL;
408         if (PyArg_ParseTuple(args,"O",&pyobj))
409         {
410                 return listvalue_buffer_concat(self,pyobj);
411         }
412         else
413         {
414            return NULL;      
415         }
416
417         
418 }
419
420
421
422 PyObject* CListValue::Pyreverse(PyObject* self, 
423                                PyObject* args, 
424                                PyObject* kwds)
425 {
426         std::reverse(m_pValueArray.begin(),m_pValueArray.end());
427
428         Py_Return;
429         
430 }
431
432
433
434 bool CListValue::CheckEqual(CValue* first,CValue* second)
435 {
436         bool result = false;
437
438         CValue* eqval =  ((CValue*)first)->Calc(VALUE_EQL_OPERATOR,(CValue*)second);
439         STR_String txt = eqval->GetText();
440         eqval->Release();
441         if (txt=="TRUE")
442         {
443                 result = true;
444         }
445         return result;
446
447 }
448
449
450
451 PyObject* CListValue::Pyindex(PyObject* self, 
452                                PyObject* args, 
453                                PyObject* kwds)
454 {
455         PyObject* result = NULL;
456
457         PyObject* pyobj = NULL;
458         if (PyArg_ParseTuple(args,"O",&pyobj))
459         {
460         
461                 CValue* checkobj = ConvertPythonToValue(pyobj);
462                 int numelem = GetCount();
463                 for (int i=0;i<numelem;i++)
464                 {
465                         CValue* elem =                  GetValue(i);
466                         if (CheckEqual(checkobj,elem))
467                         {
468                                 result = PyInt_FromLong(i);
469                                 break;
470                         }
471                 }
472                 checkobj->Release();
473         }
474
475         return result;
476         
477 }
478
479
480
481 PyObject* CListValue::Pycount(PyObject* self, 
482                                PyObject* args, 
483                                PyObject* kwds)
484 {
485         
486         int numfound = 0;
487
488         PyObject* pyobj = NULL;
489         if (PyArg_ParseTuple(args,"O",&pyobj))
490         {
491                 CValue* checkobj = ConvertPythonToValue(pyobj);
492                 int numelem = GetCount();
493                 for (int i=0;i<numelem;i++)
494                 {
495                         CValue* elem =                  GetValue(i);
496                         if (CheckEqual(checkobj,elem))
497                         {
498                                 numfound ++;
499                         }
500                 }
501                 checkobj->Release();
502         }
503
504         return PyInt_FromLong(numfound);
505 }
506
507
508
509 /* --------------------------------------------------------------------- 
510  * Some stuff taken from the header
511  * --------------------------------------------------------------------- */
512 CValue* CListValue::Calc(VALUE_OPERATOR op,CValue *val) 
513 {
514         assert(false); // todo: implement me!
515         return NULL;
516 }
517
518
519
520 CValue* CListValue::CalcFinal(VALUE_DATA_TYPE dtype,
521                                                           VALUE_OPERATOR op, 
522                                                           CValue* val) 
523 {
524         assert(false); // todo: implement me!
525         return NULL;
526 }
527
528
529
530 void CListValue::Add(CValue* value)
531 {
532         m_pValueArray.push_back(value);
533 }
534
535
536
537 float CListValue::GetNumber()
538 {
539         return -1;
540 }
541
542
543
544 void CListValue::SetModified(bool bModified)
545 {       
546         CValue::SetModified(bModified);
547         int numels = GetCount();
548
549         for (int i=0;i<numels;i++)
550                 GetValue(i)->SetModified(bModified);
551 }
552
553
554
555 bool CListValue::IsModified()
556 {
557         bool bmod = CValue::IsModified(); //normal own flag
558         int numels = GetCount();
559
560         for (int i=0;i<numels;i++)
561                 bmod = bmod || GetValue(i)->IsModified();
562
563         return bmod;
564 }