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