Norimasa Okamoto
/
pymite
python-on-a-chip online compiler
Embed:
(wiki syntax)
Show/hide line numbers
seq.c
Go to the documentation of this file.
00001 /* 00002 # This file is Copyright 2006 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__ 0x14 00011 00012 00013 /** 00014 * \file 00015 * \brief Sequence 00016 * 00017 * Functions that operate on sequences 00018 */ 00019 00020 00021 #include "pm.h" 00022 00023 00024 /* 00025 * Compares two sequence objects 00026 * Assumes both objects are of same type (guaranteed by obj_compare) 00027 */ 00028 int8_t 00029 seq_compare(pPmObj_t pobj1, pPmObj_t pobj2) 00030 { 00031 int16_t l1; 00032 int16_t l2; 00033 pPmObj_t pa; 00034 pPmObj_t pb; 00035 PmReturn_t retval; 00036 int8_t retcompare; 00037 00038 /* Get the lengths of supported types or return differ */ 00039 if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_TUP) 00040 { 00041 l1 = ((pPmTuple_t)pobj1)->length; 00042 l2 = ((pPmTuple_t)pobj2)->length; 00043 } 00044 else if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_LST) 00045 { 00046 l1 = ((pPmList_t)pobj1)->length; 00047 l2 = ((pPmList_t)pobj2)->length; 00048 } 00049 00050 #ifdef HAVE_BYTEARRAY 00051 else if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_BYA) 00052 { 00053 /* Return if the lengths differ */ 00054 l1 = ((pPmBytearray_t)pobj1)->length; 00055 l2 = ((pPmBytearray_t)pobj2)->length; 00056 if (l1 != l2) 00057 { 00058 return C_DIFFER; 00059 } 00060 00061 return sli_strncmp((char const *)&(((pPmBytes_t)((pPmBytearray_t)pobj1)->val)->val), 00062 (char const *)&(((pPmBytes_t)((pPmBytearray_t)pobj2)->val)->val), 00063 l1) 00064 ? C_DIFFER : C_SAME; 00065 } 00066 #endif /* HAVE_BYTEARRAY */ 00067 00068 else 00069 { 00070 return C_DIFFER; 00071 } 00072 00073 /* Return if the lengths differ */ 00074 if (l1 != l2) 00075 { 00076 return C_DIFFER; 00077 } 00078 00079 /* Compare all items in the sequences */ 00080 while (--l1 >= 0) 00081 { 00082 retval = seq_getSubscript(pobj1, l1, &pa); 00083 if (retval != PM_RET_OK) 00084 { 00085 return C_DIFFER; 00086 } 00087 retval = seq_getSubscript(pobj2, l1, &pb); 00088 if (retval != PM_RET_OK) 00089 { 00090 return C_DIFFER; 00091 } 00092 retcompare = obj_compare(pa, pb); 00093 if (retcompare != C_SAME) 00094 { 00095 return retcompare; 00096 } 00097 } 00098 00099 return C_SAME; 00100 } 00101 00102 00103 /* Returns the length of the sequence */ 00104 PmReturn_t 00105 seq_getLength(pPmObj_t pobj, uint16_t *r_index) 00106 { 00107 PmReturn_t retval = PM_RET_OK; 00108 00109 switch (OBJ_GET_TYPE(pobj)) 00110 { 00111 case OBJ_TYPE_STR: 00112 *r_index = ((pPmString_t)pobj)->length; 00113 break; 00114 00115 case OBJ_TYPE_TUP: 00116 *r_index = ((pPmTuple_t)pobj)->length; 00117 break; 00118 00119 case OBJ_TYPE_LST: 00120 *r_index = ((pPmList_t)pobj)->length; 00121 break; 00122 00123 #ifdef HAVE_BYTEARRAY 00124 case OBJ_TYPE_BYA: 00125 *r_index = ((pPmBytearray_t)pobj)->length; 00126 break; 00127 #endif /* HAVE_BYTEARRAY */ 00128 00129 case OBJ_TYPE_DIC: 00130 *r_index = ((pPmDict_t)pobj)->length; 00131 break; 00132 00133 default: 00134 /* Raise TypeError, non-sequence object */ 00135 PM_RAISE(retval, PM_RET_EX_TYPE); 00136 break; 00137 } 00138 00139 return retval; 00140 } 00141 00142 00143 /* Returns the object sequence[index] */ 00144 PmReturn_t 00145 seq_getSubscript(pPmObj_t pobj, int16_t index, pPmObj_t *r_pobj) 00146 { 00147 PmReturn_t retval; 00148 pSeglist_t pkeys; 00149 uint8_t c; 00150 00151 switch (OBJ_GET_TYPE(pobj)) 00152 { 00153 case OBJ_TYPE_STR: 00154 /* Adjust for negative index */ 00155 if (index < 0) 00156 { 00157 index += ((pPmString_t)pobj)->length; 00158 } 00159 00160 /* Raise IndexError if index is out of bounds */ 00161 if ((index < 0) || (index > ((pPmString_t)pobj)->length)) 00162 { 00163 PM_RAISE(retval, PM_RET_EX_INDX); 00164 break; 00165 } 00166 00167 /* Get the character from the string */ 00168 c = ((pPmString_t)pobj)->val[index]; 00169 00170 /* Create a new string from the character */ 00171 retval = string_newFromChar(c, r_pobj); 00172 break; 00173 00174 case OBJ_TYPE_TUP: 00175 /* Get the tuple item */ 00176 retval = tuple_getItem(pobj, index, r_pobj); 00177 break; 00178 00179 case OBJ_TYPE_LST: 00180 /* Get the list item */ 00181 retval = list_getItem(pobj, index, r_pobj); 00182 break; 00183 00184 #ifdef HAVE_BYTEARRAY 00185 case OBJ_TYPE_BYA: 00186 retval = bytearray_getItem(pobj, index, r_pobj); 00187 break; 00188 #endif /* HAVE_BYTEARRAY */ 00189 00190 /* Issue #176 Add support to iterate over keys in a dict */ 00191 case OBJ_TYPE_DIC: 00192 pkeys = ((pPmDict_t)pobj)->d_keys; 00193 retval = seglist_getItem(pkeys, index, r_pobj); 00194 break; 00195 00196 default: 00197 /* Raise TypeError, unsubscriptable object */ 00198 PM_RAISE(retval, PM_RET_EX_TYPE); 00199 break; 00200 } 00201 00202 return retval; 00203 } 00204 00205 00206 PmReturn_t 00207 seqiter_getNext(pPmObj_t pobj, pPmObj_t *r_pitem) 00208 { 00209 PmReturn_t retval; 00210 uint16_t length; 00211 00212 C_ASSERT(pobj != C_NULL); 00213 C_ASSERT(*r_pitem != C_NULL); 00214 C_ASSERT(OBJ_GET_TYPE(pobj) == OBJ_TYPE_SQI); 00215 00216 /* 00217 * Raise TypeError if sequence iterator's object is not a sequence 00218 * otherwise, the get sequence's length 00219 */ 00220 retval = seq_getLength(((pPmSeqIter_t)pobj)->si_sequence, &length); 00221 PM_RETURN_IF_ERROR(retval); 00222 00223 /* Raise StopIteration if at the end of the sequence */ 00224 if (((pPmSeqIter_t)pobj)->si_index == length) 00225 { 00226 /* Make null the pointer to the sequence */ 00227 ((pPmSeqIter_t)pobj)->si_sequence = C_NULL; 00228 PM_RAISE(retval, PM_RET_EX_STOP); 00229 return retval; 00230 } 00231 00232 /* Get the item at the current index */ 00233 retval = seq_getSubscript(((pPmSeqIter_t)pobj)->si_sequence, 00234 ((pPmSeqIter_t)pobj)->si_index, r_pitem); 00235 00236 /* Increment the index */ 00237 ((pPmSeqIter_t)pobj)->si_index++; 00238 00239 return retval; 00240 } 00241 00242 00243 PmReturn_t 00244 seqiter_new(pPmObj_t pobj, pPmObj_t *r_pobj) 00245 { 00246 PmReturn_t retval; 00247 uint8_t *pchunk; 00248 pPmSeqIter_t psi; 00249 00250 C_ASSERT(pobj != C_NULL); 00251 C_ASSERT(*r_pobj != C_NULL); 00252 00253 /* Raise a TypeError if pobj is not a sequence */ 00254 if ((OBJ_GET_TYPE(pobj) != OBJ_TYPE_STR) 00255 && (OBJ_GET_TYPE(pobj) != OBJ_TYPE_TUP) 00256 && (OBJ_GET_TYPE(pobj) != OBJ_TYPE_LST) 00257 && (OBJ_GET_TYPE(pobj) != OBJ_TYPE_DIC)) 00258 { 00259 PM_RAISE(retval, PM_RET_EX_TYPE); 00260 return retval; 00261 } 00262 00263 /* Alloc a chunk for the sequence iterator obj */ 00264 retval = heap_getChunk(sizeof(PmSeqIter_t), &pchunk); 00265 PM_RETURN_IF_ERROR(retval); 00266 00267 /* Set the sequence iterator's fields */ 00268 psi = (pPmSeqIter_t)pchunk; 00269 OBJ_SET_TYPE(psi, OBJ_TYPE_SQI); 00270 psi->si_sequence = pobj; 00271 psi->si_index = 0; 00272 00273 *r_pobj = (pPmObj_t)psi; 00274 return retval; 00275 }
Generated on Tue Jul 12 2022 23:13:47 by 1.7.2