Norimasa Okamoto
/
pymite
python-on-a-chip online compiler
Embed:
(wiki syntax)
Show/hide line numbers
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 }
Generated on Tue Jul 12 2022 23:13:47 by 1.7.2