LP-89 - Port OP_15.05.01 fixes. Release notes:
[librepilot.git] / flight / libraries / PyMite / vm / lst.c
blob53deaa113cc206de4d9fa27c9a1ffa1f7f8a3408
1 /*
2 # This file is Copyright 2003, 2006, 2007, 2009, 2010 Dean Hall.
4 # This file is part of the PyMite VM.
5 # The PyMite VM is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU GENERAL PUBLIC LICENSE Version 2.
8 # The PyMite VM is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 # A copy of the GNU GENERAL PUBLIC LICENSE Version 2
12 # is seen in the file COPYING in this directory.
16 #undef __FILE_ID__
17 #define __FILE_ID__ 0x0B
20 /**
21 * \file
22 * \brief List Object Type
24 * List object type operations.
28 #include "pm.h"
31 PmReturn_t
32 list_append(pPmObj_t plist, pPmObj_t pobj)
34 PmReturn_t retval;
35 uint8_t objid;
37 C_ASSERT(plist != C_NULL);
38 C_ASSERT(pobj != C_NULL);
40 /* If plist is not a list, raise a TypeError exception */
41 if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
43 PM_RAISE(retval, PM_RET_EX_TYPE);
44 return retval;
47 /* Create new seglist if needed */
48 if (((pPmList_t)plist)->length == 0)
50 retval = seglist_new(&((pPmList_t)plist)->val);
51 PM_RETURN_IF_ERROR(retval);
54 /* Append object to list */
55 heap_gcPushTempRoot((pPmObj_t)((pPmList_t)plist)->val, &objid);
56 retval = seglist_appendItem(((pPmList_t)plist)->val, pobj);
57 heap_gcPopTempRoot(objid);
58 PM_RETURN_IF_ERROR(retval);
60 /* Increment list length */
61 ((pPmList_t)plist)->length++;
63 return retval;
67 PmReturn_t
68 list_getItem(pPmObj_t plist, int16_t index, pPmObj_t *r_pobj)
70 PmReturn_t retval;
72 /* If it's not a list, raise TypeError */
73 if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
75 PM_RAISE(retval, PM_RET_EX_TYPE);
76 return retval;
79 /* Adjust the index */
80 if (index < 0)
82 index += ((pPmList_t)plist)->length;
85 /* Check the bounds of the index */
86 if ((index < 0) || (index >= ((pPmList_t)plist)->length))
88 PM_RAISE(retval, PM_RET_EX_INDX);
89 return retval;
92 /* Get item from seglist */
93 retval = seglist_getItem(((pPmList_t)plist)->val, index, r_pobj);
94 return retval;
98 PmReturn_t
99 list_insert(pPmObj_t plist, int16_t index, pPmObj_t pobj)
101 PmReturn_t retval;
102 int16_t len;
103 uint8_t objid;
105 C_ASSERT(plist != C_NULL);
106 C_ASSERT(pobj != C_NULL);
108 /* Raise a TypeError if plist is not a List */
109 if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
111 retval = PM_RET_EX_TYPE;
112 PM_RETURN_IF_ERROR(retval);
115 /* Adjust an out-of-bounds index value */
116 len = ((pPmList_t)plist)->length;
117 if (index < 0)
119 index += len;
121 if (index < 0)
123 index = 0;
125 if (index > len)
127 index = len;
130 /* Create new seglist if needed */
131 if (((pPmList_t)plist)->length == 0)
133 retval = seglist_new(&((pPmList_t)plist)->val);
134 PM_RETURN_IF_ERROR(retval);
137 /* Insert the item in the container */
138 heap_gcPushTempRoot((pPmObj_t)((pPmList_t)plist)->val, &objid);
139 retval = seglist_insertItem(((pPmList_t)plist)->val, pobj, index);
140 heap_gcPopTempRoot(objid);
141 PM_RETURN_IF_ERROR(retval);
143 /* Increment list length */
144 ((pPmList_t)plist)->length++;
145 return retval;
149 PmReturn_t
150 list_new(pPmObj_t *r_pobj)
152 PmReturn_t retval = PM_RET_OK;
153 pPmList_t plist = C_NULL;
155 /* Allocate a list */
156 retval = heap_getChunk(sizeof(PmList_t), (uint8_t **)r_pobj);
157 PM_RETURN_IF_ERROR(retval);
159 /* Set list type, empty the contents */
160 plist = (pPmList_t)*r_pobj;
161 OBJ_SET_TYPE(plist, OBJ_TYPE_LST);
162 plist->length = 0;
163 plist->val = C_NULL;
165 return retval;
169 PmReturn_t
170 list_copy(pPmObj_t pobj, pPmObj_t *r_pobj)
172 return list_replicate(pobj, 1, r_pobj);
176 PmReturn_t
177 list_replicate(pPmObj_t psrclist, int16_t n, pPmObj_t *r_pnewlist)
179 PmReturn_t retval = PM_RET_OK;
180 int16_t i = 0;
181 int16_t j = 0;
182 int16_t length = 0;
183 pPmObj_t pitem = C_NULL;
184 uint8_t objid;
186 C_ASSERT(psrclist != C_NULL);
187 C_ASSERT(r_pnewlist != C_NULL);
189 /* If first arg is not a list, raise TypeError */
190 if (OBJ_GET_TYPE(psrclist) != OBJ_TYPE_LST)
192 PM_RAISE(retval, PM_RET_EX_TYPE);
193 return retval;
195 length = ((pPmList_t)psrclist)->length;
197 /* Allocate new list */
198 retval = list_new(r_pnewlist);
199 PM_RETURN_IF_ERROR(retval);
201 /* Copy srclist the designated number of times */
202 for (i = n; i > 0; i--)
204 /* Iterate over the length of srclist */
205 for (j = 0; j < length; j++)
207 retval = list_getItem(psrclist, j, &pitem);
208 PM_RETURN_IF_ERROR(retval);
209 heap_gcPushTempRoot(*r_pnewlist, &objid);
210 retval = list_append(*r_pnewlist, pitem);
211 heap_gcPopTempRoot(objid);
212 PM_RETURN_IF_ERROR(retval);
215 return retval;
219 PmReturn_t
220 list_setItem(pPmObj_t plist, int16_t index, pPmObj_t pobj)
222 PmReturn_t retval;
224 /* If it's not a list, raise TypeError */
225 if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
227 PM_RAISE(retval, PM_RET_EX_TYPE);
228 return retval;
231 /* Adjust the index */
232 if (index < 0)
234 index += ((pPmList_t)plist)->length;
237 /* Check the bounds of the index */
238 if ((index < 0) || (index >= ((pPmList_t)plist)->length))
240 PM_RAISE(retval, PM_RET_EX_INDX);
241 return retval;
244 /* Set the item */
245 retval = seglist_setItem(((pPmList_t)plist)->val, pobj, index);
246 return retval;
250 PmReturn_t
251 list_remove(pPmObj_t plist, pPmObj_t item)
253 PmReturn_t retval = PM_RET_OK;
254 uint16_t index;
256 /* If it's not a list, raise TypeError */
257 if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
259 PM_RAISE(retval, PM_RET_EX_TYPE);
260 return retval;
263 /* Locate the item to remove */
264 retval = list_index(plist, item, &index);
265 PM_RETURN_IF_ERROR(retval);
267 /* Remove the item and decrement the list length */
268 retval = seglist_removeItem(((pPmList_t)plist)->val, index);
269 ((pPmList_t)plist)->length--;
271 /* Unlink seglist if there are no contents */
272 if (((pPmList_t)plist)->length == 0)
274 ((pPmList_t)plist)->val = C_NULL;
277 return retval;
281 PmReturn_t
282 list_index(pPmObj_t plist, pPmObj_t pitem, uint16_t *r_index)
284 PmReturn_t retval = PM_RET_OK;
285 pSeglist_t pseglist;
286 pPmObj_t pobj;
287 uint16_t index;
289 /* If it's not a list, raise TypeError */
290 if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
292 PM_RAISE(retval, PM_RET_EX_TYPE);
293 return retval;
296 /* Raise a ValueError if the list is empty */
297 if (((pPmList_t)plist)->length == 0)
299 PM_RAISE(retval, PM_RET_EX_VAL);
300 return retval;
303 pseglist = ((pPmList_t)plist)->val;
305 /* Iterate over the list's contents */
306 for (index = 0; index < pseglist->sl_length; index++)
308 retval = seglist_getItem(pseglist, index, &pobj);
309 PM_RETURN_IF_ERROR(retval);
311 /* If the list item matches the given item, return the index */
312 if (obj_compare(pobj, pitem) == C_SAME)
314 *r_index = index;
315 return PM_RET_OK;
319 return PM_RET_EX_VAL;
323 PmReturn_t
324 list_delItem(pPmObj_t plist, int16_t index)
326 PmReturn_t retval = PM_RET_OK;
328 /* If it's not a list, raise TypeError */
329 if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
331 PM_RAISE(retval, PM_RET_EX_TYPE);
332 return retval;
335 /* Adjust the index */
336 if (index < 0)
338 index += ((pPmList_t)plist)->length;
341 /* Check the bounds of the index */
342 if ((index < 0) || (index >= ((pPmList_t)plist)->length))
344 PM_RAISE(retval, PM_RET_EX_INDX);
345 return retval;
348 /* Remove the item and decrement the list length */
349 retval = seglist_removeItem(((pPmList_t)plist)->val, index);
350 ((pPmList_t)plist)->length--;
352 /* Unlink seglist if there are no contents */
353 if (((pPmList_t)plist)->length == 0)
355 ((pPmList_t)plist)->val = C_NULL;
358 return retval;
362 #ifdef HAVE_PRINT
363 PmReturn_t
364 list_print(pPmObj_t plist)
366 PmReturn_t retval = PM_RET_OK;
367 int16_t index;
368 pSeglist_t vals;
369 pPmObj_t pobj1;
371 C_ASSERT(plist != C_NULL);
373 /* If it's not a list, raise TypeError */
374 if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
376 PM_RAISE(retval, PM_RET_EX_TYPE);
377 return retval;
380 plat_putByte('[');
382 vals = ((pPmList_t)plist)->val;
384 /* Iterate over the list's contents */
385 for (index = 0; index < ((pPmList_t)plist)->length; index++)
387 if (index != 0)
389 plat_putByte(',');
390 plat_putByte(' ');
393 /* Print each item */
394 retval = seglist_getItem(vals, index, &pobj1);
395 PM_RETURN_IF_ERROR(retval);
396 retval = obj_print(pobj1, C_FALSE, C_TRUE);
397 PM_RETURN_IF_ERROR(retval);
400 return plat_putByte(']');
402 #endif /* HAVE_PRINT */
405 PmReturn_t
406 list_clear(pPmObj_t plist)
408 PmReturn_t retval = PM_RET_OK;
410 C_ASSERT(plist != C_NULL);
412 /* Raise TypeError if arg is not a dict */
413 if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
415 PM_RAISE(retval, PM_RET_EX_TYPE);
416 return retval;
419 /* Clear length and unlink seglist */
420 ((pPmList_t)plist)->length = 0;
421 ((pPmList_t)plist)->val = C_NULL;
423 return retval;