python-on-a-chip online compiler

Dependencies:   mbed TSI

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dict.c Source File

dict.c

Go to the documentation of this file.
00001 /*
00002 # This file is Copyright 2002 Dean Hall.
00003 # This file is part of the PyMite VM.
00004 # This file is licensed under the MIT License.
00005 # See the LICENSE file for details.
00006 */
00007 
00008 
00009 #undef __FILE_ID__
00010 #define __FILE_ID__ 0x02
00011 
00012 
00013 /**
00014  * \file
00015  * \brief Dict Object Type
00016  *
00017  * Dict object type operations.
00018  */
00019 
00020 
00021 #include "pm.h"
00022 
00023 
00024 PmReturn_t
00025 dict_new(pPmObj_t *r_pdict)
00026 {
00027     PmReturn_t retval = PM_RET_OK;
00028     pPmDict_t pdict = C_NULL;
00029     uint8_t *pchunk;
00030 
00031     /* Allocate a dict */
00032     retval = heap_getChunk(sizeof(PmDict_t), &pchunk);
00033     PM_RETURN_IF_ERROR(retval);
00034 
00035     /* Init dict fields */
00036     pdict = (pPmDict_t)pchunk;
00037     OBJ_SET_TYPE(pdict, OBJ_TYPE_DIC);
00038     pdict->length = 0;
00039     pdict->d_keys = C_NULL;
00040     pdict->d_vals = C_NULL;
00041 
00042     *r_pdict = (pPmObj_t)pchunk;
00043     return retval;
00044 }
00045 
00046 
00047 PmReturn_t
00048 dict_clear(pPmObj_t pdict)
00049 {
00050     PmReturn_t retval = PM_RET_OK;
00051 
00052     C_ASSERT(pdict != C_NULL);
00053 
00054     /* Raise TypeError if arg is not a dict */
00055     if (OBJ_GET_TYPE(pdict) != OBJ_TYPE_DIC)
00056     {
00057         PM_RAISE(retval, PM_RET_EX_TYPE);
00058         return retval;
00059     }
00060 
00061     /* clear length */
00062     ((pPmDict_t)pdict)->length = 0;
00063 
00064     /* Free the keys and values seglists if needed */
00065     if (((pPmDict_t)pdict)->d_keys != C_NULL)
00066     {
00067         PM_RETURN_IF_ERROR(seglist_clear(((pPmDict_t)pdict)->d_keys));
00068         PM_RETURN_IF_ERROR(heap_freeChunk((pPmObj_t)
00069                                           ((pPmDict_t)pdict)->d_keys));
00070         ((pPmDict_t)pdict)->d_keys = C_NULL;
00071     }
00072     if (((pPmDict_t)pdict)->d_vals != C_NULL)
00073     {
00074         PM_RETURN_IF_ERROR(seglist_clear(((pPmDict_t)pdict)->d_vals));
00075         retval = heap_freeChunk((pPmObj_t)((pPmDict_t)pdict)->d_vals);
00076         ((pPmDict_t)pdict)->d_vals = C_NULL;
00077     }
00078     return retval;
00079 }
00080 
00081 
00082 /*
00083  * Sets a value in the dict using the given key.
00084  *
00085  * Scans dict for the key.  If key val found, replace old
00086  * with new val.  If no key found, add key/val pair to dict.
00087  */
00088 PmReturn_t
00089 dict_setItem(pPmObj_t pdict, pPmObj_t pkey, pPmObj_t pval)
00090 {
00091     PmReturn_t retval = PM_RET_OK;
00092     int16_t indx;
00093 
00094     C_ASSERT(pdict != C_NULL);
00095     C_ASSERT(pkey != C_NULL);
00096     C_ASSERT(pval != C_NULL);
00097 
00098     /* If it's not a dict, raise TypeError */
00099     if (OBJ_GET_TYPE(pdict) != OBJ_TYPE_DIC)
00100     {
00101         PM_RAISE(retval, PM_RET_EX_TYPE);
00102         return retval;
00103     }
00104 
00105     /* #112: Force Dict keys to be of hashable type */
00106     /* If key is not hashable, raise TypeError */
00107     if (OBJ_GET_TYPE(pkey) > OBJ_TYPE_HASHABLE_MAX)
00108     {
00109         PM_RAISE(retval, PM_RET_EX_TYPE);
00110         return retval;
00111     }
00112 
00113     /* #147: Change boolean keys to integers */
00114     if (pkey == PM_TRUE)
00115     {
00116         pkey = PM_ONE;
00117     }
00118     else if (pkey == PM_FALSE)
00119     {
00120         pkey = PM_ZERO;
00121     }
00122 
00123     /*
00124      * #115: If this is the first key/value pair to be added to the Dict,
00125      * allocate the key and value seglists that hold those items
00126      */
00127     if (((pPmDict_t)pdict)->length == 0)
00128     {
00129         retval = seglist_new(&((pPmDict_t)pdict)->d_keys);
00130         PM_RETURN_IF_ERROR(retval);
00131         retval = seglist_new(&((pPmDict_t)pdict)->d_vals);
00132         PM_RETURN_IF_ERROR(retval);
00133     }
00134     else
00135     {
00136         /* Check for matching key */
00137         indx = 0;
00138         retval = seglist_findEqual(((pPmDict_t)pdict)->d_keys, pkey, &indx);
00139 
00140         /* If found a matching key, replace val obj */
00141         if (retval == PM_RET_OK)
00142         {
00143             retval = seglist_setItem(((pPmDict_t)pdict)->d_vals, pval, indx);
00144             return retval;
00145         }
00146     }
00147 
00148     /* Otherwise, insert the key,val pair */
00149     retval = seglist_insertItem(((pPmDict_t)pdict)->d_keys, pkey, 0);
00150     PM_RETURN_IF_ERROR(retval);
00151     retval = seglist_insertItem(((pPmDict_t)pdict)->d_vals, pval, 0);
00152     ((pPmDict_t)pdict)->length++;
00153 
00154     return retval;
00155 }
00156 
00157 
00158 PmReturn_t
00159 dict_getItem(pPmObj_t pdict, pPmObj_t pkey, pPmObj_t *r_pobj)
00160 {
00161     PmReturn_t retval = PM_RET_OK;
00162     int16_t indx = 0;
00163 
00164 /*    C_ASSERT(pdict != C_NULL);*/
00165 
00166     /* if it's not a dict, raise TypeError */
00167     if (OBJ_GET_TYPE(pdict) != OBJ_TYPE_DIC)
00168     {
00169         PM_RAISE(retval, PM_RET_EX_TYPE);
00170         return retval;
00171     }
00172 
00173     /* if dict is empty, raise KeyError */
00174     if (((pPmDict_t)pdict)->length <= 0)
00175     {
00176         PM_RAISE(retval, PM_RET_EX_KEY);
00177         return retval;
00178     }
00179 
00180     /* #147: Change boolean keys to integers */
00181     if (pkey == PM_TRUE)
00182     {
00183         pkey = PM_ONE;
00184     }
00185     else if (pkey == PM_FALSE)
00186     {
00187         pkey = PM_ZERO;
00188     }
00189 
00190     /* check for matching key */
00191     retval = seglist_findEqual(((pPmDict_t)pdict)->d_keys, pkey, &indx);
00192     /* if key not found, raise KeyError */
00193     if (retval == PM_RET_NO)
00194     {
00195         PM_RAISE(retval, PM_RET_EX_KEY);
00196     }
00197     /* return any other error */
00198     PM_RETURN_IF_ERROR(retval);
00199 
00200     /* key was found, get obj from vals */
00201     retval = seglist_getItem(((pPmDict_t)pdict)->d_vals, indx, r_pobj);
00202     return retval;
00203 }
00204 
00205 
00206 #ifdef HAVE_DEL
00207 PmReturn_t
00208 dict_delItem(pPmObj_t pdict, pPmObj_t pkey)
00209 {
00210     PmReturn_t retval = PM_RET_OK;
00211     int16_t indx = 0;
00212 
00213     C_ASSERT(pdict != C_NULL);
00214 
00215     /* Check for matching key */
00216     retval = seglist_findEqual(((pPmDict_t)pdict)->d_keys, pkey, &indx);
00217 
00218     /* Raise KeyError if key is not found */
00219     if (retval == PM_RET_NO)
00220     {
00221         PM_RAISE(retval, PM_RET_EX_KEY);
00222     }
00223 
00224     /* Return any other error */
00225     PM_RETURN_IF_ERROR(retval);
00226 
00227     /* Remove the key and value */
00228     retval = seglist_removeItem(((pPmDict_t)pdict)->d_keys, indx);
00229     PM_RETURN_IF_ERROR(retval);
00230     retval = seglist_removeItem(((pPmDict_t)pdict)->d_vals, indx);
00231 
00232     /* Reduce the item count */
00233     ((pPmDict_t)pdict)->length--;
00234 
00235     return retval;
00236 }
00237 #endif /* HAVE_DEL */
00238 
00239 
00240 #ifdef HAVE_PRINT
00241 PmReturn_t
00242 dict_print(pPmObj_t pdict)
00243 {
00244     PmReturn_t retval = PM_RET_OK;
00245     int16_t index;
00246     pSeglist_t keys,
00247       vals;
00248     pPmObj_t pobj1;
00249 
00250     C_ASSERT(pdict != C_NULL);
00251 
00252     /* if it's not a dict, raise TypeError */
00253     if (OBJ_GET_TYPE(pdict) != OBJ_TYPE_DIC)
00254     {
00255         PM_RAISE(retval, PM_RET_EX_TYPE);
00256         return retval;
00257     }
00258 
00259     plat_putByte('{');
00260 
00261     keys = ((pPmDict_t)pdict)->d_keys;
00262     vals = ((pPmDict_t)pdict)->d_vals;
00263 
00264     /* if dict is empty, raise KeyError */
00265     for (index = 0; index < ((pPmDict_t)pdict)->length; index++)
00266     {
00267         if (index != 0)
00268         {
00269             plat_putByte(',');
00270             plat_putByte(' ');
00271         }
00272         retval = seglist_getItem(keys, index, &pobj1);
00273         PM_RETURN_IF_ERROR(retval);
00274         retval = obj_print(pobj1, C_FALSE, C_TRUE);
00275         PM_RETURN_IF_ERROR(retval);
00276 
00277         plat_putByte(':');
00278         retval = seglist_getItem(vals, index, &pobj1);
00279         PM_RETURN_IF_ERROR(retval);
00280         retval = obj_print(pobj1, C_FALSE, C_TRUE);
00281         PM_RETURN_IF_ERROR(retval);
00282     }
00283 
00284     return plat_putByte('}');
00285 }
00286 #endif /* HAVE_PRINT */
00287 
00288 
00289 PmReturn_t
00290 dict_update(pPmObj_t pdestdict, pPmObj_t psourcedict, uint8_t omit_underscored)
00291 {
00292     PmReturn_t retval = PM_RET_OK;
00293     int16_t i;
00294     pPmObj_t pkey;
00295     pPmObj_t pval;
00296 
00297     C_ASSERT(pdestdict != C_NULL);
00298     C_ASSERT(psourcedict != C_NULL);
00299 
00300     /* If it's not a dict, raise TypeError */
00301     if (OBJ_GET_TYPE(pdestdict) != OBJ_TYPE_DIC)
00302     {
00303         PM_RAISE(retval, PM_RET_EX_TYPE);
00304         return retval;
00305     }
00306 
00307     /* If it's not a dict, raise TypeError */
00308     if (OBJ_GET_TYPE(psourcedict) != OBJ_TYPE_DIC)
00309     {
00310         PM_RAISE(retval, PM_RET_EX_TYPE);
00311         return retval;
00312     }
00313 
00314     /* Iterate over the add-on dict */
00315     for (i = 0; i < ((pPmDict_t)psourcedict)->length; i++)
00316     {
00317         /* Get the key,val from the add-on dict */
00318         retval = seglist_getItem(((pPmDict_t)psourcedict)->d_keys, i, &pkey);
00319         PM_RETURN_IF_ERROR(retval);
00320         retval = seglist_getItem(((pPmDict_t)psourcedict)->d_vals, i, &pval);
00321         PM_RETURN_IF_ERROR(retval);
00322 
00323         if (!(omit_underscored && (OBJ_GET_TYPE(pkey) == OBJ_TYPE_STR)
00324               && ((pPmString_t)pkey)->val[0] == '_'))
00325         {
00326             /* Set the key,val to the destination dict */
00327             retval = dict_setItem(pdestdict, pkey, pval);
00328             PM_RETURN_IF_ERROR(retval);
00329         }
00330     }
00331 
00332     return retval;
00333 }
00334 
00335 
00336 int8_t
00337 dict_compare(pPmObj_t d1, pPmObj_t d2)
00338 {
00339     pPmDict_t pd1 = (pPmDict_t)d1;
00340     pPmDict_t pd2 = (pPmDict_t)d2;
00341     pPmObj_t pkey1;
00342     pPmObj_t pval1;
00343     pPmObj_t pval2;
00344     uint16_t i;
00345     PmReturn_t retval;
00346 
00347     /* Return if lengths are not equal */
00348     if (pd1->length != pd2->length)
00349     {
00350         return C_DIFFER;
00351     }
00352 
00353     for (i = 0; i < pd1->length; i++)
00354     {
00355         /* Get the key,val from one dict */
00356         retval = seglist_getItem(pd1->d_keys, i, &pkey1);
00357         PM_RETURN_IF_ERROR(retval);
00358         retval = seglist_getItem(pd1->d_vals, i, &pval1);
00359         PM_RETURN_IF_ERROR(retval);
00360 
00361         /* Return if the key,val pair is not in the other dict */
00362         retval = dict_getItem(d2, pkey1, &pval2);
00363         if (retval != PM_RET_OK)
00364         {
00365             return C_DIFFER;
00366         }
00367         if (obj_compare(pval1, pval2) != C_SAME)
00368         {
00369             return C_DIFFER;
00370         }
00371     }
00372 
00373     /* All key,values match */
00374     return C_SAME;
00375 }