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