Embed:
(wiki syntax)
Show/hide line numbers
dict.c
Go to the documentation of this file.
00001 /* 00002 # This file is Copyright 2003, 2006, 2007, 2009 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 00020 /** 00021 * \file 00022 * \brief Dict Object Type 00023 * 00024 * Dict object type operations. 00025 */ 00026 00027 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, 1); 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, 1); 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 Tue Jul 12 2022 17:07:01 by
1.7.2