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