2 # This file is Copyright 2010 Dean Hall.
4 # This file is part of the PyMite VM.
5 # The PyMite VM is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU GENERAL PUBLIC LICENSE Version 2.
8 # The PyMite VM is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 # A copy of the GNU GENERAL PUBLIC LICENSE Version 2
12 # is seen in the file COPYING in this directory.
17 #define __FILE_ID__ 0x19
22 * \brief VM Bytearray Type
24 * VM Bytearray object type operations.
31 #define ROUND_UP_TO_MUL_OF_FOUR(n) n = (((n) + 3) & ~3)
34 /* Returns a container that can hold at least n bytes */
37 bytes_new(int16_t n
, pPmObj_t
*r_pobj
)
39 PmReturn_t retval
= PM_RET_OK
;
40 pPmBytes_t pb
= C_NULL
;
42 ROUND_UP_TO_MUL_OF_FOUR(n
);
44 /* Allocate a container */
45 retval
= heap_getChunk(sizeof(PmBytes_t
) + n
, (uint8_t **)&pb
);
46 PM_RETURN_IF_ERROR(retval
);
47 OBJ_SET_TYPE(pb
, OBJ_TYPE_BYS
);
50 *r_pobj
= (pPmObj_t
)pb
;
55 /* Returns the int or one-char string as a byte */
58 bytes_getByteFromObj(pPmObj_t pobj
, uint8_t *b
)
60 PmReturn_t retval
= PM_RET_OK
;
62 if (OBJ_GET_TYPE(pobj
) == OBJ_TYPE_INT
)
64 if ((((pPmInt_t
)pobj
)->val
> 255) || (((pPmInt_t
)pobj
)->val
< 0))
66 PM_RAISE(retval
, PM_RET_EX_VAL
);
70 *b
= (uint8_t)((pPmInt_t
)pobj
)->val
;
73 else if (OBJ_GET_TYPE(pobj
) == OBJ_TYPE_STR
)
75 if (((pPmString_t
)pobj
)->length
!= 1)
77 PM_RAISE(retval
, PM_RET_EX_VAL
);
80 *b
= ((pPmString_t
)pobj
)->val
[0];
85 PM_RAISE(retval
, PM_RET_EX_TYPE
);
92 bytearray_new(pPmObj_t pobj
, pPmObj_t
*r_pobj
)
94 PmReturn_t retval
= PM_RET_OK
;
95 pPmBytearray_t pba
= C_NULL
;
96 pPmBytes_t pb
= C_NULL
;
103 /* If object is an instance, get the thing it is containing */
104 if (OBJ_GET_TYPE(pobj
) == OBJ_TYPE_CLI
)
106 retval
= dict_getItem((pPmObj_t
)((pPmInstance_t
)pobj
)->cli_attrs
,
109 PM_RETURN_IF_ERROR(retval
);
110 pobj
= (pPmObj_t
)pba
;
113 /* Get the requested length of the new bytearray */
114 switch (OBJ_GET_TYPE(pobj
))
117 i
= ((pPmInt_t
)pobj
)->val
;
118 if ((i
< 0) || (i
> 65535))
120 PM_RAISE(retval
, PM_RET_EX_VAL
);
127 n
= ((pPmString_t
)pobj
)->length
;
131 n
= ((pPmList_t
)pobj
)->length
;
135 n
= ((pPmTuple_t
)pobj
)->length
;
139 n
= ((pPmBytearray_t
)pobj
)->length
;
143 PM_RAISE(retval
, PM_RET_EX_TYPE
);
147 /* Allocate a bytearray */
148 retval
= heap_getChunk(sizeof(PmBytearray_t
), (uint8_t **)&pba
);
149 PM_RETURN_IF_ERROR(retval
);
150 OBJ_SET_TYPE(pba
, OBJ_TYPE_BYA
);
154 /* Allocate the bytes container */
155 heap_gcPushTempRoot((pPmObj_t
)pba
, &objid
);
156 retval
= bytes_new(n
, (pPmObj_t
*)&pb
);
157 heap_gcPopTempRoot(objid
);
158 PM_RETURN_IF_ERROR(retval
);
162 switch (OBJ_GET_TYPE(pobj
))
165 sli_memset((unsigned char *)&(pb
->val
), '\0', n
);
169 pitem
= (pPmObj_t
)((pPmBytearray_t
)pobj
)->val
;
170 sli_memcpy(&(pb
->val
[0]), &(((pPmBytes_t
)pitem
)->val
[0]), n
);
174 sli_memcpy(&(pb
->val
[0]), &(((pPmString_t
)pobj
)->val
[0]), n
);
179 for (i
= 0; i
< n
; i
++)
181 retval
= seq_getSubscript(pobj
, i
, &pitem
);
182 PM_RETURN_IF_ERROR(retval
);
183 retval
= bytes_getByteFromObj(pitem
, &b
);
184 PM_RETURN_IF_ERROR(retval
);
190 *r_pobj
= (pPmObj_t
)pba
;
196 bytearray_getItem(pPmObj_t pobj
, int16_t index
, pPmObj_t
*r_pobj
)
198 PmReturn_t retval
= PM_RET_OK
;
203 pba
= (pPmBytearray_t
)pobj
;
205 /* Adjust a negative index */
208 index
+= pba
->length
;
211 /* Check the bounds of the index */
212 if ((index
< 0) || (index
>= pba
->length
))
214 PM_RAISE(retval
, PM_RET_EX_INDX
);
218 /* Create int from byte at index */
220 n
= (int32_t)pb
->val
[index
];
221 retval
= int_new(n
, r_pobj
);
228 bytearray_setItem(pPmObj_t pba
, int16_t index
, pPmObj_t pobj
)
234 /* Adjust a negative index */
237 index
+= ((pPmBytearray_t
)pba
)->length
;
240 /* Check the bounds of the index */
241 if ((index
< 0) || (index
>= ((pPmBytearray_t
)pba
)->length
))
243 PM_RAISE(retval
, PM_RET_EX_INDX
);
248 retval
= bytes_getByteFromObj(pobj
, &b
);
249 pb
= ((pPmBytearray_t
)pba
)->val
;
257 bytearray_print(pPmObj_t pobj
)
262 obj_print(PM_BYTEARRAY_STR
, C_FALSE
, C_FALSE
);
265 pb
= ((pPmBytearray_t
)pobj
)->val
;
266 retval
= string_printFormattedBytes(&(pb
->val
[0]),
268 ((pPmBytearray_t
)pobj
)->length
);
272 #endif /* HAVE_BYTEARRAY */