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