dict.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__ 0x02
00018 
00019 
00028 #include "pm.h"
00029 
00030 
00031 PmReturn_t
00032 dict_new(pPmObj_t *r_pdict)
00033 {
00034     PmReturn_t retval = PM_RET_OK;
00035     pPmDict_t pdict = C_NULL;
00036     uint8_t *pchunk;
00037     
00038     /* Allocate a dict */
00039     retval = heap_getChunk(sizeof(PmDict_t), &pchunk);
00040     PM_RETURN_IF_ERROR(retval);
00041 
00042     /* Init dict fields */
00043     pdict = (pPmDict_t)pchunk;
00044     OBJ_SET_TYPE(pdict, OBJ_TYPE_DIC);
00045     pdict->length = 0;
00046     pdict->d_keys = C_NULL;
00047     pdict->d_vals = C_NULL;
00048 
00049     *r_pdict = (pPmObj_t)pchunk;
00050     return retval;
00051 }
00052 
00053 
00054 PmReturn_t
00055 dict_clear(pPmObj_t pdict)
00056 {
00057     PmReturn_t retval = PM_RET_OK;
00058 
00059     C_ASSERT(pdict != C_NULL);
00060 
00061     /* Raise TypeError if arg is not a dict */
00062     if (OBJ_GET_TYPE(pdict) != OBJ_TYPE_DIC)
00063     {
00064         PM_RAISE(retval, PM_RET_EX_TYPE);
00065         return retval;
00066     }
00067 
00068     /* clear length */
00069     ((pPmDict_t)pdict)->length = 0;
00070 
00071     /* Free the keys and values seglists if needed */
00072     if (((pPmDict_t)pdict)->d_keys != C_NULL)
00073     {
00074         PM_RETURN_IF_ERROR(seglist_clear(((pPmDict_t)pdict)->d_keys));
00075         PM_RETURN_IF_ERROR(heap_freeChunk((pPmObj_t)
00076                                           ((pPmDict_t)pdict)->d_keys));
00077         ((pPmDict_t)pdict)->d_keys = C_NULL;
00078     }
00079     if (((pPmDict_t)pdict)->d_vals != C_NULL)
00080     {
00081         PM_RETURN_IF_ERROR(seglist_clear(((pPmDict_t)pdict)->d_vals));
00082         retval = heap_freeChunk((pPmObj_t)((pPmDict_t)pdict)->d_vals);
00083         ((pPmDict_t)pdict)->d_vals = C_NULL;
00084     }
00085     return retval;
00086 }
00087 
00088 
00089 /*
00090  * Sets a value in the dict using the given key.
00091  *
00092  * Scans dict for the key.  If key val found, replace old
00093  * with new val.  If no key found, add key/val pair to dict.
00094  */
00095 PmReturn_t
00096 dict_setItem(pPmObj_t pdict, pPmObj_t pkey, pPmObj_t pval)
00097 {
00098     PmReturn_t retval = PM_RET_OK;
00099     int16_t indx;
00100 
00101     C_ASSERT(pdict != C_NULL);
00102     C_ASSERT(pkey != C_NULL);
00103     C_ASSERT(pval != C_NULL);
00104 
00105     /* If it's not a dict, raise TypeError */
00106     if (OBJ_GET_TYPE(pdict) != OBJ_TYPE_DIC)
00107     {
00108         PM_RAISE(retval, PM_RET_EX_TYPE);
00109         return retval;
00110     }
00111 
00112     /* #112: Force Dict keys to be of hashable type */
00113     /* If key is not hashable, raise TypeError */
00114     if (OBJ_GET_TYPE(pkey) > OBJ_TYPE_HASHABLE_MAX)
00115     {
00116         PM_RAISE(retval, PM_RET_EX_TYPE);
00117         return retval;
00118     }
00119 
00120     /* #147: Change boolean keys to integers */
00121     if (pkey == PM_TRUE)
00122     {
00123         pkey = PM_ONE;
00124     }
00125     else if (pkey == PM_FALSE)
00126     {
00127         pkey = PM_ZERO;
00128     }
00129 
00130     /*
00131      * #115: If this is the first key/value pair to be added to the Dict,
00132      * allocate the key and value seglists that hold those items
00133      */
00134     if (((pPmDict_t)pdict)->length == 0)
00135     {
00136         retval = seglist_new(&((pPmDict_t)pdict)->d_keys);
00137         PM_RETURN_IF_ERROR(retval);
00138         retval = seglist_new(&((pPmDict_t)pdict)->d_vals);
00139         PM_RETURN_IF_ERROR(retval);
00140     }
00141     else
00142     {
00143         /* Check for matching key */
00144         indx = 0;
00145         retval = seglist_findEqual(((pPmDict_t)pdict)->d_keys, pkey, &indx);
00146 
00147         /* If found a matching key, replace val obj */
00148         if (retval == PM_RET_OK)
00149         {
00150             retval = seglist_setItem(((pPmDict_t)pdict)->d_vals, pval, indx);
00151             return retval;
00152         }
00153     }
00154 
00155     /* Otherwise, insert the key,val pair */
00156     retval = seglist_insertItem(((pPmDict_t)pdict)->d_keys, pkey, 0);
00157     PM_RETURN_IF_ERROR(retval);
00158     retval = seglist_insertItem(((pPmDict_t)pdict)->d_vals, pval, 0);
00159     ((pPmDict_t)pdict)->length++;
00160 
00161     return retval;
00162 }
00163 
00164 
00165 PmReturn_t
00166 dict_getItem(pPmObj_t pdict, pPmObj_t pkey, pPmObj_t *r_pobj)
00167 {
00168     PmReturn_t retval = PM_RET_OK;
00169     int16_t indx = 0;
00170 
00171 /*    C_ASSERT(pdict != C_NULL);*/
00172 
00173     /* if it's not a dict, raise TypeError */
00174     if (OBJ_GET_TYPE(pdict) != OBJ_TYPE_DIC)
00175     {
00176         PM_RAISE(retval, PM_RET_EX_TYPE);
00177         return retval;
00178     }
00179 
00180     /* if dict is empty, raise KeyError */
00181     if (((pPmDict_t)pdict)->length <= 0)
00182     {
00183         PM_RAISE(retval, PM_RET_EX_KEY);
00184         return retval;
00185     }
00186 
00187     /* #147: Change boolean keys to integers */
00188     if (pkey == PM_TRUE)
00189     {
00190         pkey = PM_ONE;
00191     }
00192     else if (pkey == PM_FALSE)
00193     {
00194         pkey = PM_ZERO;
00195     }
00196 
00197     /* check for matching key */
00198     retval = seglist_findEqual(((pPmDict_t)pdict)->d_keys, pkey, &indx);
00199     /* if key not found, raise KeyError */
00200     if (retval == PM_RET_NO)
00201     {
00202         PM_RAISE(retval, PM_RET_EX_KEY);
00203     }
00204     /* return any other error */
00205     PM_RETURN_IF_ERROR(retval);
00206 
00207     /* key was found, get obj from vals */
00208     retval = seglist_getItem(((pPmDict_t)pdict)->d_vals, indx, r_pobj);
00209     return retval;
00210 }
00211 
00212 
00213 #ifdef HAVE_DEL
00214 PmReturn_t
00215 dict_delItem(pPmObj_t pdict, pPmObj_t pkey)
00216 {
00217     PmReturn_t retval = PM_RET_OK;
00218     int16_t indx = 0;
00219 
00220     C_ASSERT(pdict != C_NULL);
00221 
00222     /* Check for matching key */
00223     retval = seglist_findEqual(((pPmDict_t)pdict)->d_keys, pkey, &indx);
00224 
00225     /* Raise KeyError if key is not found */
00226     if (retval == PM_RET_NO)
00227     {
00228         PM_RAISE(retval, PM_RET_EX_KEY);
00229     }
00230 
00231     /* Return any other error */
00232     PM_RETURN_IF_ERROR(retval);
00233 
00234     /* Remove the key and value */
00235     retval = seglist_removeItem(((pPmDict_t)pdict)->d_keys, indx);
00236     PM_RETURN_IF_ERROR(retval);
00237     retval = seglist_removeItem(((pPmDict_t)pdict)->d_vals, indx);
00238 
00239     /* Reduce the item count */
00240     ((pPmDict_t)pdict)->length--;
00241 
00242     return retval;
00243 }
00244 #endif /* HAVE_DEL */
00245 
00246 
00247 #ifdef HAVE_PRINT
00248 PmReturn_t
00249 dict_print(pPmObj_t pdict)
00250 {
00251     PmReturn_t retval = PM_RET_OK;
00252     int16_t index;
00253     pSeglist_t keys,
00254       vals;
00255     pPmObj_t pobj1;
00256 
00257     C_ASSERT(pdict != C_NULL);
00258 
00259     /* if it's not a dict, raise TypeError */
00260     if (OBJ_GET_TYPE(pdict) != OBJ_TYPE_DIC)
00261     {
00262         PM_RAISE(retval, PM_RET_EX_TYPE);
00263         return retval;
00264     }
00265 
00266     plat_putByte('{');
00267 
00268     keys = ((pPmDict_t)pdict)->d_keys;
00269     vals = ((pPmDict_t)pdict)->d_vals;
00270 
00271     /* if dict is empty, raise KeyError */
00272     for (index = 0; index < ((pPmDict_t)pdict)->length; index++)
00273     {
00274         if (index != 0)
00275         {
00276             plat_putByte(',');
00277             plat_putByte(' ');
00278         }
00279         retval = seglist_getItem(keys, index, &pobj1);
00280         PM_RETURN_IF_ERROR(retval);
00281         retval = obj_print(pobj1, C_FALSE, C_TRUE);
00282         PM_RETURN_IF_ERROR(retval);
00283 
00284         plat_putByte(':');
00285         retval = seglist_getItem(vals, index, &pobj1);
00286         PM_RETURN_IF_ERROR(retval);
00287         retval = obj_print(pobj1, C_FALSE, C_TRUE);
00288         PM_RETURN_IF_ERROR(retval);
00289     }
00290 
00291     return plat_putByte('}');
00292 }
00293 #endif /* HAVE_PRINT */
00294 
00295 PmReturn_t
00296 dict_update(pPmObj_t pdestdict, pPmObj_t psourcedict)
00297 {
00298     PmReturn_t retval = PM_RET_OK;
00299     int16_t i;
00300     pPmObj_t pkey;
00301     pPmObj_t pval;
00302 
00303     C_ASSERT(pdestdict != C_NULL);
00304     C_ASSERT(psourcedict != C_NULL);
00305 
00306     /* If it's not a dict, raise TypeError */
00307     if (OBJ_GET_TYPE(pdestdict) != OBJ_TYPE_DIC)
00308     {
00309         PM_RAISE(retval, PM_RET_EX_TYPE);
00310         return retval;
00311     }
00312 
00313     /* If it's not a dict, raise TypeError */
00314     if (OBJ_GET_TYPE(psourcedict) != OBJ_TYPE_DIC)
00315     {
00316         PM_RAISE(retval, PM_RET_EX_TYPE);
00317         return retval;
00318     }
00319 
00320     /* Iterate over the add-on dict */
00321     for (i = 0; i < ((pPmDict_t)psourcedict)->length; i++)
00322     {
00323         /* Get the key,val from the add-on dict */
00324         retval = seglist_getItem(((pPmDict_t)psourcedict)->d_keys, i, &pkey);
00325         PM_RETURN_IF_ERROR(retval);
00326         retval = seglist_getItem(((pPmDict_t)psourcedict)->d_vals, i, &pval);
00327         PM_RETURN_IF_ERROR(retval);
00328 
00329         /* Set the key,val to the destination dict */
00330         retval = dict_setItem(pdestdict, pkey, pval);
00331         PM_RETURN_IF_ERROR(retval);
00332     }
00333 
00334     return retval;
00335 }

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