Norimasa Okamoto
/
pymite
python-on-a-chip online compiler
- http://pymbed.appspot.com/
- https://code.google.com/p/python-on-a-chip/
- http://www.youtube.com/watch?v=Oyqc2bFRW9I
- https://bitbucket.org/va009039/pymbed/
more info: python-on-a-chip
Diff: vm/dict.c
- Revision:
- 0:65f1469d6bfb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/dict.c Sat Mar 02 11:54:20 2013 +0000 @@ -0,0 +1,375 @@ +/* +# This file is Copyright 2002 Dean Hall. +# This file is part of the PyMite VM. +# This file is licensed under the MIT License. +# See the LICENSE file for details. +*/ + + +#undef __FILE_ID__ +#define __FILE_ID__ 0x02 + + +/** + * \file + * \brief Dict Object Type + * + * Dict object type operations. + */ + + +#include "pm.h" + + +PmReturn_t +dict_new(pPmObj_t *r_pdict) +{ + PmReturn_t retval = PM_RET_OK; + pPmDict_t pdict = C_NULL; + uint8_t *pchunk; + + /* Allocate a dict */ + retval = heap_getChunk(sizeof(PmDict_t), &pchunk); + PM_RETURN_IF_ERROR(retval); + + /* Init dict fields */ + pdict = (pPmDict_t)pchunk; + OBJ_SET_TYPE(pdict, OBJ_TYPE_DIC); + pdict->length = 0; + pdict->d_keys = C_NULL; + pdict->d_vals = C_NULL; + + *r_pdict = (pPmObj_t)pchunk; + return retval; +} + + +PmReturn_t +dict_clear(pPmObj_t pdict) +{ + PmReturn_t retval = PM_RET_OK; + + C_ASSERT(pdict != C_NULL); + + /* Raise TypeError if arg is not a dict */ + if (OBJ_GET_TYPE(pdict) != OBJ_TYPE_DIC) + { + PM_RAISE(retval, PM_RET_EX_TYPE); + return retval; + } + + /* clear length */ + ((pPmDict_t)pdict)->length = 0; + + /* Free the keys and values seglists if needed */ + if (((pPmDict_t)pdict)->d_keys != C_NULL) + { + PM_RETURN_IF_ERROR(seglist_clear(((pPmDict_t)pdict)->d_keys)); + PM_RETURN_IF_ERROR(heap_freeChunk((pPmObj_t) + ((pPmDict_t)pdict)->d_keys)); + ((pPmDict_t)pdict)->d_keys = C_NULL; + } + if (((pPmDict_t)pdict)->d_vals != C_NULL) + { + PM_RETURN_IF_ERROR(seglist_clear(((pPmDict_t)pdict)->d_vals)); + retval = heap_freeChunk((pPmObj_t)((pPmDict_t)pdict)->d_vals); + ((pPmDict_t)pdict)->d_vals = C_NULL; + } + return retval; +} + + +/* + * Sets a value in the dict using the given key. + * + * Scans dict for the key. If key val found, replace old + * with new val. If no key found, add key/val pair to dict. + */ +PmReturn_t +dict_setItem(pPmObj_t pdict, pPmObj_t pkey, pPmObj_t pval) +{ + PmReturn_t retval = PM_RET_OK; + int16_t indx; + + C_ASSERT(pdict != C_NULL); + C_ASSERT(pkey != C_NULL); + C_ASSERT(pval != C_NULL); + + /* If it's not a dict, raise TypeError */ + if (OBJ_GET_TYPE(pdict) != OBJ_TYPE_DIC) + { + PM_RAISE(retval, PM_RET_EX_TYPE); + return retval; + } + + /* #112: Force Dict keys to be of hashable type */ + /* If key is not hashable, raise TypeError */ + if (OBJ_GET_TYPE(pkey) > OBJ_TYPE_HASHABLE_MAX) + { + PM_RAISE(retval, PM_RET_EX_TYPE); + return retval; + } + + /* #147: Change boolean keys to integers */ + if (pkey == PM_TRUE) + { + pkey = PM_ONE; + } + else if (pkey == PM_FALSE) + { + pkey = PM_ZERO; + } + + /* + * #115: If this is the first key/value pair to be added to the Dict, + * allocate the key and value seglists that hold those items + */ + if (((pPmDict_t)pdict)->length == 0) + { + retval = seglist_new(&((pPmDict_t)pdict)->d_keys); + PM_RETURN_IF_ERROR(retval); + retval = seglist_new(&((pPmDict_t)pdict)->d_vals); + PM_RETURN_IF_ERROR(retval); + } + else + { + /* Check for matching key */ + indx = 0; + retval = seglist_findEqual(((pPmDict_t)pdict)->d_keys, pkey, &indx); + + /* If found a matching key, replace val obj */ + if (retval == PM_RET_OK) + { + retval = seglist_setItem(((pPmDict_t)pdict)->d_vals, pval, indx); + return retval; + } + } + + /* Otherwise, insert the key,val pair */ + retval = seglist_insertItem(((pPmDict_t)pdict)->d_keys, pkey, 0); + PM_RETURN_IF_ERROR(retval); + retval = seglist_insertItem(((pPmDict_t)pdict)->d_vals, pval, 0); + ((pPmDict_t)pdict)->length++; + + return retval; +} + + +PmReturn_t +dict_getItem(pPmObj_t pdict, pPmObj_t pkey, pPmObj_t *r_pobj) +{ + PmReturn_t retval = PM_RET_OK; + int16_t indx = 0; + +/* C_ASSERT(pdict != C_NULL);*/ + + /* if it's not a dict, raise TypeError */ + if (OBJ_GET_TYPE(pdict) != OBJ_TYPE_DIC) + { + PM_RAISE(retval, PM_RET_EX_TYPE); + return retval; + } + + /* if dict is empty, raise KeyError */ + if (((pPmDict_t)pdict)->length <= 0) + { + PM_RAISE(retval, PM_RET_EX_KEY); + return retval; + } + + /* #147: Change boolean keys to integers */ + if (pkey == PM_TRUE) + { + pkey = PM_ONE; + } + else if (pkey == PM_FALSE) + { + pkey = PM_ZERO; + } + + /* check for matching key */ + retval = seglist_findEqual(((pPmDict_t)pdict)->d_keys, pkey, &indx); + /* if key not found, raise KeyError */ + if (retval == PM_RET_NO) + { + PM_RAISE(retval, PM_RET_EX_KEY); + } + /* return any other error */ + PM_RETURN_IF_ERROR(retval); + + /* key was found, get obj from vals */ + retval = seglist_getItem(((pPmDict_t)pdict)->d_vals, indx, r_pobj); + return retval; +} + + +#ifdef HAVE_DEL +PmReturn_t +dict_delItem(pPmObj_t pdict, pPmObj_t pkey) +{ + PmReturn_t retval = PM_RET_OK; + int16_t indx = 0; + + C_ASSERT(pdict != C_NULL); + + /* Check for matching key */ + retval = seglist_findEqual(((pPmDict_t)pdict)->d_keys, pkey, &indx); + + /* Raise KeyError if key is not found */ + if (retval == PM_RET_NO) + { + PM_RAISE(retval, PM_RET_EX_KEY); + } + + /* Return any other error */ + PM_RETURN_IF_ERROR(retval); + + /* Remove the key and value */ + retval = seglist_removeItem(((pPmDict_t)pdict)->d_keys, indx); + PM_RETURN_IF_ERROR(retval); + retval = seglist_removeItem(((pPmDict_t)pdict)->d_vals, indx); + + /* Reduce the item count */ + ((pPmDict_t)pdict)->length--; + + return retval; +} +#endif /* HAVE_DEL */ + + +#ifdef HAVE_PRINT +PmReturn_t +dict_print(pPmObj_t pdict) +{ + PmReturn_t retval = PM_RET_OK; + int16_t index; + pSeglist_t keys, + vals; + pPmObj_t pobj1; + + C_ASSERT(pdict != C_NULL); + + /* if it's not a dict, raise TypeError */ + if (OBJ_GET_TYPE(pdict) != OBJ_TYPE_DIC) + { + PM_RAISE(retval, PM_RET_EX_TYPE); + return retval; + } + + plat_putByte('{'); + + keys = ((pPmDict_t)pdict)->d_keys; + vals = ((pPmDict_t)pdict)->d_vals; + + /* if dict is empty, raise KeyError */ + for (index = 0; index < ((pPmDict_t)pdict)->length; index++) + { + if (index != 0) + { + plat_putByte(','); + plat_putByte(' '); + } + retval = seglist_getItem(keys, index, &pobj1); + PM_RETURN_IF_ERROR(retval); + retval = obj_print(pobj1, C_FALSE, C_TRUE); + PM_RETURN_IF_ERROR(retval); + + plat_putByte(':'); + retval = seglist_getItem(vals, index, &pobj1); + PM_RETURN_IF_ERROR(retval); + retval = obj_print(pobj1, C_FALSE, C_TRUE); + PM_RETURN_IF_ERROR(retval); + } + + return plat_putByte('}'); +} +#endif /* HAVE_PRINT */ + + +PmReturn_t +dict_update(pPmObj_t pdestdict, pPmObj_t psourcedict, uint8_t omit_underscored) +{ + PmReturn_t retval = PM_RET_OK; + int16_t i; + pPmObj_t pkey; + pPmObj_t pval; + + C_ASSERT(pdestdict != C_NULL); + C_ASSERT(psourcedict != C_NULL); + + /* If it's not a dict, raise TypeError */ + if (OBJ_GET_TYPE(pdestdict) != OBJ_TYPE_DIC) + { + PM_RAISE(retval, PM_RET_EX_TYPE); + return retval; + } + + /* If it's not a dict, raise TypeError */ + if (OBJ_GET_TYPE(psourcedict) != OBJ_TYPE_DIC) + { + PM_RAISE(retval, PM_RET_EX_TYPE); + return retval; + } + + /* Iterate over the add-on dict */ + for (i = 0; i < ((pPmDict_t)psourcedict)->length; i++) + { + /* Get the key,val from the add-on dict */ + retval = seglist_getItem(((pPmDict_t)psourcedict)->d_keys, i, &pkey); + PM_RETURN_IF_ERROR(retval); + retval = seglist_getItem(((pPmDict_t)psourcedict)->d_vals, i, &pval); + PM_RETURN_IF_ERROR(retval); + + if (!(omit_underscored && (OBJ_GET_TYPE(pkey) == OBJ_TYPE_STR) + && ((pPmString_t)pkey)->val[0] == '_')) + { + /* Set the key,val to the destination dict */ + retval = dict_setItem(pdestdict, pkey, pval); + PM_RETURN_IF_ERROR(retval); + } + } + + return retval; +} + + +int8_t +dict_compare(pPmObj_t d1, pPmObj_t d2) +{ + pPmDict_t pd1 = (pPmDict_t)d1; + pPmDict_t pd2 = (pPmDict_t)d2; + pPmObj_t pkey1; + pPmObj_t pval1; + pPmObj_t pval2; + uint16_t i; + PmReturn_t retval; + + /* Return if lengths are not equal */ + if (pd1->length != pd2->length) + { + return C_DIFFER; + } + + for (i = 0; i < pd1->length; i++) + { + /* Get the key,val from one dict */ + retval = seglist_getItem(pd1->d_keys, i, &pkey1); + PM_RETURN_IF_ERROR(retval); + retval = seglist_getItem(pd1->d_vals, i, &pval1); + PM_RETURN_IF_ERROR(retval); + + /* Return if the key,val pair is not in the other dict */ + retval = dict_getItem(d2, pkey1, &pval2); + if (retval != PM_RET_OK) + { + return C_DIFFER; + } + if (obj_compare(pval1, pval2) != C_SAME) + { + return C_DIFFER; + } + } + + /* All key,values match */ + return C_SAME; +}