python-on-a-chip online compiler

Dependencies:   mbed TSI

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers bytearray.c Source File

bytearray.c

Go to the documentation of this file.
00001 /*
00002 # This file is Copyright 2010 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__ 0x19
00011 
00012 
00013 /**
00014  * \file
00015  * \brief VM Bytearray Type
00016  *
00017  * VM Bytearray object type operations.
00018  */
00019 
00020 #include "pm.h"
00021 #ifdef HAVE_BYTEARRAY
00022 
00023 
00024 #define ROUND_UP_TO_MUL_OF_FOUR(n) n = (((n) + 3) & ~3)
00025 
00026 
00027 /* Returns a container that can hold at least n bytes */
00028 static
00029 PmReturn_t
00030 bytes_new(int16_t n, pPmObj_t *r_pobj)
00031 {
00032     PmReturn_t retval = PM_RET_OK;
00033     pPmBytes_t pb = C_NULL;
00034 
00035     ROUND_UP_TO_MUL_OF_FOUR(n);
00036 
00037     /* Allocate a container */
00038     retval = heap_getChunk(sizeof(PmBytes_t) + n, (uint8_t **)&pb);
00039     PM_RETURN_IF_ERROR(retval);
00040     OBJ_SET_TYPE(pb, OBJ_TYPE_BYS);
00041     pb->length = n;
00042 
00043     *r_pobj = (pPmObj_t)pb;
00044     return retval;
00045 }
00046 
00047 
00048 /* Returns the int or one-char string as a byte */
00049 static
00050 PmReturn_t
00051 bytes_getByteFromObj(pPmObj_t pobj, uint8_t *b)
00052 {
00053     PmReturn_t retval = PM_RET_OK;
00054 
00055     if (OBJ_GET_TYPE(pobj) == OBJ_TYPE_INT)
00056     {
00057         if ((((pPmInt_t)pobj)->val > 255) || (((pPmInt_t)pobj)->val < 0))
00058         {
00059             PM_RAISE(retval, PM_RET_EX_VAL);
00060             return retval;
00061         }
00062 
00063         *b = (uint8_t)((pPmInt_t)pobj)->val;
00064     }
00065 
00066     else if (OBJ_GET_TYPE(pobj) == OBJ_TYPE_STR)
00067     {
00068         if (((pPmString_t)pobj)->length != 1)
00069         {
00070             PM_RAISE(retval, PM_RET_EX_VAL);
00071             return retval;
00072         }
00073         *b = ((pPmString_t)pobj)->val[0];
00074     }
00075 
00076     else
00077     {
00078         PM_RAISE(retval, PM_RET_EX_TYPE);
00079     }
00080     return retval;
00081 }
00082 
00083 
00084 PmReturn_t
00085 bytearray_new(pPmObj_t pobj, pPmObj_t *r_pobj)
00086 {
00087     PmReturn_t retval = PM_RET_OK;
00088     pPmBytearray_t pba = C_NULL;
00089     pPmBytes_t pb = C_NULL;
00090     pPmObj_t pitem;
00091     int32_t i;
00092     int16_t n;
00093     uint8_t b;
00094     uint8_t objid;
00095 
00096     /* If object is an instance, get the thing it is containing */
00097     if (OBJ_GET_TYPE(pobj) == OBJ_TYPE_CLI)
00098     {
00099         retval = dict_getItem((pPmObj_t)((pPmInstance_t)pobj)->cli_attrs,
00100                               PM_NONE,
00101                               (pPmObj_t *)&pba);
00102         PM_RETURN_IF_ERROR(retval);
00103         pobj = (pPmObj_t)pba;
00104     }
00105 
00106     /* Get the requested length of the new bytearray */
00107     switch (OBJ_GET_TYPE(pobj))
00108     {
00109         case OBJ_TYPE_INT:
00110             i = ((pPmInt_t)pobj)->val;
00111             if ((i < 0) || (i > 65535))
00112             {
00113                 PM_RAISE(retval, PM_RET_EX_VAL);
00114                 return retval;
00115             }
00116             n = i;
00117             break;
00118 
00119         case OBJ_TYPE_STR:
00120             n = ((pPmString_t)pobj)->length;
00121             break;
00122 
00123         case OBJ_TYPE_LST:
00124             n = ((pPmList_t)pobj)->length;
00125             break;
00126 
00127         case OBJ_TYPE_TUP:
00128             n = ((pPmTuple_t)pobj)->length;
00129             break;
00130 
00131         case OBJ_TYPE_BYA:
00132             n = ((pPmBytearray_t)pobj)->length;
00133             break;
00134 
00135         default:
00136             PM_RAISE(retval, PM_RET_EX_TYPE);
00137             return retval;
00138     }
00139 
00140     /* Allocate a bytearray */
00141     retval = heap_getChunk(sizeof(PmBytearray_t), (uint8_t **)&pba);
00142     PM_RETURN_IF_ERROR(retval);
00143     OBJ_SET_TYPE(pba, OBJ_TYPE_BYA);
00144     pba->length = n;
00145     pba->val = C_NULL;
00146 
00147     /* Allocate the bytes container */
00148     heap_gcPushTempRoot((pPmObj_t)pba, &objid);
00149     retval = bytes_new(n, (pPmObj_t *)&pb);
00150     heap_gcPopTempRoot(objid);
00151     PM_RETURN_IF_ERROR(retval);
00152     pba->val = pb;
00153 
00154     /* Fill the bytes */
00155     switch (OBJ_GET_TYPE(pobj))
00156     {
00157         case OBJ_TYPE_INT:
00158             sli_memset((unsigned char *)&(pb->val), '\0', n);
00159             break;
00160 
00161         case OBJ_TYPE_BYA:
00162             pitem = (pPmObj_t)((pPmBytearray_t)pobj)->val;
00163             sli_memcpy(&(pb->val[0]), &(((pPmBytes_t)pitem)->val[0]), n);
00164             break;
00165 
00166         case OBJ_TYPE_STR:
00167             sli_memcpy(&(pb->val[0]), &(((pPmString_t)pobj)->val[0]), n);
00168             break;
00169 
00170         case OBJ_TYPE_LST:
00171         case OBJ_TYPE_TUP:
00172             for (i = 0; i < n; i++)
00173             {
00174                 retval = seq_getSubscript(pobj, i, &pitem);
00175                 PM_RETURN_IF_ERROR(retval);
00176                 retval = bytes_getByteFromObj(pitem, &b);
00177                 PM_RETURN_IF_ERROR(retval);
00178                 pb->val[i] = b;
00179             }
00180             break;
00181     }
00182 
00183     *r_pobj = (pPmObj_t)pba;
00184     return retval;
00185 }
00186 
00187 
00188 PmReturn_t
00189 bytearray_getItem(pPmObj_t pobj, int16_t index, pPmObj_t *r_pobj)
00190 {
00191     PmReturn_t retval = PM_RET_OK;
00192     pPmBytearray_t pba;
00193     pPmBytes_t pb;
00194     int32_t n;
00195 
00196     pba = (pPmBytearray_t)pobj;
00197 
00198     /* Adjust a negative index */
00199     if (index < 0)
00200     {
00201         index += pba->length;
00202     }
00203 
00204     /* Check the bounds of the index */
00205     if ((index < 0) || (index >= pba->length))
00206     {
00207         PM_RAISE(retval, PM_RET_EX_INDX);
00208         return retval;
00209     }
00210 
00211     /* Create int from byte at index */
00212     pb = pba->val;
00213     n = (int32_t)pb->val[index];
00214     retval = int_new(n, r_pobj);
00215 
00216     return retval;
00217 }
00218 
00219 
00220 PmReturn_t
00221 bytearray_setItem(pPmObj_t pba, int16_t index, pPmObj_t pobj)
00222 {
00223     PmReturn_t retval;
00224     pPmBytes_t pb;
00225     uint8_t b = 0;
00226 
00227     /* Adjust a negative index */
00228     if (index < 0)
00229     {
00230         index += ((pPmBytearray_t)pba)->length;
00231     }
00232 
00233     /* Check the bounds of the index */
00234     if ((index < 0) || (index >= ((pPmBytearray_t)pba)->length))
00235     {
00236         PM_RAISE(retval, PM_RET_EX_INDX);
00237         return retval;
00238     }
00239 
00240     /* Set the item */
00241     retval = bytes_getByteFromObj(pobj, &b);
00242     pb = ((pPmBytearray_t)pba)->val;
00243     pb->val[index] = b;
00244 
00245     return retval;
00246 }
00247 
00248 
00249 #ifdef HAVE_PRINT
00250 PmReturn_t
00251 bytearray_print(pPmObj_t pobj)
00252 {
00253     PmReturn_t retval;
00254     pPmBytes_t pb;
00255 
00256     obj_print(PM_BYTEARRAY_STR, C_FALSE, C_FALSE);
00257     plat_putByte('(');
00258     plat_putByte('b');
00259     pb = ((pPmBytearray_t)pobj)->val;
00260     retval = string_printFormattedBytes(&(pb->val[0]),
00261                                         C_TRUE,
00262                                         ((pPmBytearray_t)pobj)->length);
00263     plat_putByte(')');
00264     return retval;
00265 }
00266 #endif /* HAVE_PRINT */
00267 #endif /* HAVE_BYTEARRAY */