seq.c

Go to the documentation of this file.
00001 /*
00002 # This file is Copyright 2006, 2007, 2009, 2010 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 
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 Mon Oct 18 07:40:48 2010 for Python-on-a-chip by  doxygen 1.5.9