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