bytearray.c

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

Generated on Mon Oct 18 07:40:47 2010 for Python-on-a-chip by  doxygen 1.5.9