list.c

Go to the documentation of this file.
00001 /*
00002 # This file is Copyright 2003, 2006, 2007, 2009, 2010 Dean Hall.
00003 #
00004 # This file is part of the PyMite VM.
00005 # The PyMite VM is free software: you can redistribute it and/or modify
00006 # it under the terms of the GNU GENERAL PUBLIC LICENSE Version 2.
00007 #
00008 # The PyMite VM is distributed in the hope that it will be useful,
00009 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00011 # A copy of the GNU GENERAL PUBLIC LICENSE Version 2
00012 # is seen in the file COPYING in this directory.
00013 */
00014 
00015 
00016 #undef __FILE_ID__
00017 #define __FILE_ID__ 0x0B
00018 
00019 
00028 #include "pm.h"
00029 
00030 
00031 PmReturn_t
00032 list_append(pPmObj_t plist, pPmObj_t pobj)
00033 {
00034     PmReturn_t retval;
00035     uint8_t objid;
00036 
00037     C_ASSERT(plist != C_NULL);
00038     C_ASSERT(pobj != C_NULL);
00039 
00040     /* If plist is not a list, raise a TypeError exception */
00041     if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
00042     {
00043         PM_RAISE(retval, PM_RET_EX_TYPE);
00044         return retval;
00045     }
00046 
00047     /* Create new seglist if needed */
00048     if (((pPmList_t)plist)->length == 0)
00049     {
00050         retval = seglist_new(&((pPmList_t)plist)->val);
00051         PM_RETURN_IF_ERROR(retval);
00052     }
00053 
00054     /* Append object to list */
00055     heap_gcPushTempRoot((pPmObj_t)((pPmList_t)plist)->val, &objid);
00056     retval = seglist_appendItem(((pPmList_t)plist)->val, pobj);
00057     heap_gcPopTempRoot(objid);
00058     PM_RETURN_IF_ERROR(retval);
00059 
00060     /* Increment list length */
00061     ((pPmList_t)plist)->length++;
00062 
00063     return retval;
00064 }
00065 
00066 
00067 PmReturn_t
00068 list_getItem(pPmObj_t plist, int16_t index, pPmObj_t *r_pobj)
00069 {
00070     PmReturn_t retval;
00071 
00072     /* If it's not a list, raise TypeError */
00073     if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
00074     {
00075         PM_RAISE(retval, PM_RET_EX_TYPE);
00076         return retval;
00077     }
00078 
00079     /* Adjust the index */
00080     if (index < 0)
00081     {
00082         index += ((pPmList_t)plist)->length;
00083     }
00084 
00085     /* Check the bounds of the index */
00086     if ((index < 0) || (index >= ((pPmList_t)plist)->length))
00087     {
00088         PM_RAISE(retval, PM_RET_EX_INDX);
00089         return retval;
00090     }
00091 
00092     /* Get item from seglist */
00093     retval = seglist_getItem(((pPmList_t)plist)->val, index, r_pobj);
00094     return retval;
00095 }
00096 
00097 
00098 PmReturn_t
00099 list_insert(pPmObj_t plist, int16_t index, pPmObj_t pobj)
00100 {
00101     PmReturn_t retval;
00102     int16_t len;
00103     uint8_t objid;
00104 
00105     C_ASSERT(plist != C_NULL);
00106     C_ASSERT(pobj != C_NULL);
00107 
00108     /* Raise a TypeError if plist is not a List */
00109     if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
00110     {
00111         retval = PM_RET_EX_TYPE;
00112         PM_RETURN_IF_ERROR(retval);
00113     }
00114 
00115     /* Adjust an out-of-bounds index value */
00116     len = ((pPmList_t)plist)->length;
00117     if (index < 0)
00118     {
00119         index += len;
00120     }
00121     if (index < 0)
00122     {
00123         index = 0;
00124     }
00125     if (index > len)
00126     {
00127         index = len;
00128     }
00129 
00130     /* Create new seglist if needed */
00131     if (((pPmList_t)plist)->length == 0)
00132     {
00133         retval = seglist_new(&((pPmList_t)plist)->val);
00134         PM_RETURN_IF_ERROR(retval);
00135     }
00136 
00137     /* Insert the item in the container */
00138     heap_gcPushTempRoot((pPmObj_t)((pPmList_t)plist)->val, &objid);
00139     retval = seglist_insertItem(((pPmList_t)plist)->val, pobj, index);
00140     heap_gcPopTempRoot(objid);
00141     PM_RETURN_IF_ERROR(retval);
00142 
00143     /* Increment list length */
00144     ((pPmList_t)plist)->length++;
00145     return retval;
00146 }
00147 
00148 
00149 PmReturn_t
00150 list_new(pPmObj_t *r_pobj)
00151 {
00152     PmReturn_t retval = PM_RET_OK;
00153     pPmList_t plist = C_NULL;
00154 
00155     /* Allocate a list */
00156     retval = heap_getChunk(sizeof(PmList_t), (uint8_t **)r_pobj);
00157     PM_RETURN_IF_ERROR(retval);
00158 
00159     /* Set list type, empty the contents */
00160     plist = (pPmList_t)*r_pobj;
00161     OBJ_SET_TYPE(plist, OBJ_TYPE_LST);
00162     plist->length = 0;
00163     plist->val = C_NULL;
00164 
00165     return retval;
00166 }
00167 
00168 
00169 PmReturn_t
00170 list_copy(pPmObj_t pobj, pPmObj_t *r_pobj)
00171 {
00172     return list_replicate(pobj, 1, r_pobj);
00173 }
00174 
00175 
00176 PmReturn_t
00177 list_replicate(pPmObj_t psrclist, int16_t n, pPmObj_t *r_pnewlist)
00178 {
00179     PmReturn_t retval = PM_RET_OK;
00180     int16_t i = 0;
00181     int16_t j = 0;
00182     int16_t length = 0;
00183     pPmObj_t pitem = C_NULL;
00184     uint8_t objid;
00185 
00186     C_ASSERT(psrclist != C_NULL);
00187     C_ASSERT(r_pnewlist != C_NULL);
00188 
00189     /* If first arg is not a list, raise TypeError */
00190     if (OBJ_GET_TYPE(psrclist) != OBJ_TYPE_LST)
00191     {
00192         PM_RAISE(retval, PM_RET_EX_TYPE);
00193         return retval;
00194     }
00195     length = ((pPmList_t)psrclist)->length;
00196 
00197     /* Allocate new list */
00198     retval = list_new(r_pnewlist);
00199     PM_RETURN_IF_ERROR(retval);
00200 
00201     /* Copy srclist the designated number of times */
00202     for (i = n; i > 0; i--)
00203     {
00204         /* Iterate over the length of srclist */
00205         for (j = 0; j < length; j++)
00206         {
00207             retval = list_getItem(psrclist, j, &pitem);
00208             PM_RETURN_IF_ERROR(retval);
00209             heap_gcPushTempRoot(*r_pnewlist, &objid);
00210             retval = list_append(*r_pnewlist, pitem);
00211             heap_gcPopTempRoot(objid);
00212             PM_RETURN_IF_ERROR(retval);
00213         }
00214     }
00215     return retval;
00216 }
00217 
00218 
00219 PmReturn_t
00220 list_setItem(pPmObj_t plist, int16_t index, pPmObj_t pobj)
00221 {
00222     PmReturn_t retval;
00223 
00224     /* If it's not a list, raise TypeError */
00225     if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
00226     {
00227         PM_RAISE(retval, PM_RET_EX_TYPE);
00228         return retval;
00229     }
00230 
00231     /* Adjust the index */
00232     if (index < 0)
00233     {
00234         index += ((pPmList_t)plist)->length;
00235     }
00236 
00237     /* Check the bounds of the index */
00238     if ((index < 0) || (index >= ((pPmList_t)plist)->length))
00239     {
00240         PM_RAISE(retval, PM_RET_EX_INDX);
00241         return retval;
00242     }
00243 
00244     /* Set the item */
00245     retval = seglist_setItem(((pPmList_t)plist)->val, pobj, index);
00246     return retval;
00247 }
00248 
00249 
00250 PmReturn_t
00251 list_remove(pPmObj_t plist, pPmObj_t item)
00252 {
00253     PmReturn_t retval = PM_RET_OK;
00254     uint16_t index;
00255 
00256     /* If it's not a list, raise TypeError */
00257     if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
00258     {
00259         PM_RAISE(retval, PM_RET_EX_TYPE);
00260         return retval;
00261     }
00262 
00263     /* Locate the item to remove */
00264     retval = list_index(plist, item, &index);
00265     PM_RETURN_IF_ERROR(retval);
00266 
00267     /* Remove the item and decrement the list length */
00268     retval = seglist_removeItem(((pPmList_t)plist)->val, index);
00269     ((pPmList_t)plist)->length--;
00270 
00271     /* Unlink seglist if there are no contents */
00272     if (((pPmList_t)plist)->length == 0)
00273     {
00274         ((pPmList_t)plist)->val = C_NULL;
00275     }
00276 
00277     return retval;
00278 }
00279 
00280 
00281 PmReturn_t
00282 list_index(pPmObj_t plist, pPmObj_t pitem, uint16_t *r_index)
00283 {
00284     PmReturn_t retval = PM_RET_OK;
00285     pSeglist_t pseglist;
00286     pPmObj_t pobj;
00287     uint16_t index;
00288 
00289     /* If it's not a list, raise TypeError */
00290     if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
00291     {
00292         PM_RAISE(retval, PM_RET_EX_TYPE);
00293         return retval;
00294     }
00295 
00296     /* Raise a ValueError if the list is empty */
00297     if (((pPmList_t)plist)->length == 0)
00298     {
00299         PM_RAISE(retval, PM_RET_EX_VAL);
00300         return retval;
00301     }
00302 
00303     pseglist = ((pPmList_t)plist)->val;
00304 
00305     /* Iterate over the list's contents */
00306     for (index = 0; index < pseglist->sl_length; index++)
00307     {
00308         retval = seglist_getItem(pseglist, index, &pobj);
00309         PM_RETURN_IF_ERROR(retval);
00310 
00311         /* If the list item matches the given item, return the index */
00312         if (obj_compare(pobj, pitem) == C_SAME)
00313         {
00314             *r_index = index;
00315             return PM_RET_OK;
00316         }
00317     }
00318 
00319     return PM_RET_EX_VAL;
00320 }
00321 
00322 
00323 PmReturn_t
00324 list_delItem(pPmObj_t plist, int16_t index)
00325 {
00326     PmReturn_t retval = PM_RET_OK;
00327 
00328     /* If it's not a list, raise TypeError */
00329     if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
00330     {
00331         PM_RAISE(retval, PM_RET_EX_TYPE);
00332         return retval;
00333     }
00334 
00335     /* Adjust the index */
00336     if (index < 0)
00337     {
00338         index += ((pPmList_t)plist)->length;
00339     }
00340 
00341     /* Check the bounds of the index */
00342     if ((index < 0) || (index >= ((pPmList_t)plist)->length))
00343     {
00344         PM_RAISE(retval, PM_RET_EX_INDX);
00345         return retval;
00346     }
00347 
00348     /* Remove the item and decrement the list length */
00349     retval = seglist_removeItem(((pPmList_t)plist)->val, index);
00350     ((pPmList_t)plist)->length--;
00351 
00352     /* Unlink seglist if there are no contents */
00353     if (((pPmList_t)plist)->length == 0)
00354     {
00355         ((pPmList_t)plist)->val = C_NULL;
00356     }
00357 
00358     return retval;
00359 }
00360 
00361 
00362 #ifdef HAVE_PRINT
00363 PmReturn_t
00364 list_print(pPmObj_t plist)
00365 {
00366     PmReturn_t retval = PM_RET_OK;
00367     int16_t index;
00368     pSeglist_t vals;
00369     pPmObj_t pobj1;
00370 
00371     C_ASSERT(plist != C_NULL);
00372 
00373     /* If it's not a list, raise TypeError */
00374     if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
00375     {
00376         PM_RAISE(retval, PM_RET_EX_TYPE);
00377         return retval;
00378     }
00379 
00380     plat_putByte('[');
00381 
00382     vals = ((pPmList_t)plist)->val;
00383 
00384     /* Iterate over the list's contents */
00385     for (index = 0; index < ((pPmList_t)plist)->length; index++)
00386     {
00387         if (index != 0)
00388         {
00389             plat_putByte(',');
00390             plat_putByte(' ');
00391         }
00392 
00393         /* Print each item */
00394         retval = seglist_getItem(vals, index, &pobj1);
00395         PM_RETURN_IF_ERROR(retval);
00396         retval = obj_print(pobj1, C_FALSE, C_TRUE);
00397         PM_RETURN_IF_ERROR(retval);
00398     }
00399 
00400     return plat_putByte(']');
00401 }
00402 #endif /* HAVE_PRINT */
00403 
00404 
00405 PmReturn_t
00406 list_clear(pPmObj_t plist)
00407 {
00408     PmReturn_t retval = PM_RET_OK;
00409 
00410     C_ASSERT(plist != C_NULL);
00411 
00412     /* Raise TypeError if arg is not a dict */
00413     if (OBJ_GET_TYPE(plist) != OBJ_TYPE_LST)
00414     {
00415         PM_RAISE(retval, PM_RET_EX_TYPE);
00416         return retval;
00417     }
00418 
00419     /* Clear length and unlink seglist */
00420     ((pPmList_t)plist)->length = 0;
00421     ((pPmList_t)plist)->val = C_NULL;
00422 
00423     return retval;
00424 }

Generated on Mon Oct 18 07:40:47 2010 for Python-on-a-chip by  doxygen 1.5.9