LP-89 - Port OP_15.05.01 fixes. Release notes:
[librepilot.git] / flight / libraries / PyMite / vm / bytearray.c
blob0514a0658c15e018dba168e6c557fa6151844518
1 /*
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.
16 #undef __FILE_ID__
17 #define __FILE_ID__ 0x19
20 /**
21 * \file
22 * \brief VM Bytearray Type
24 * VM Bytearray object type operations.
27 #include "pm.h"
28 #ifdef HAVE_BYTEARRAY
31 #define ROUND_UP_TO_MUL_OF_FOUR(n) n = (((n) + 3) & ~3)
34 /* Returns a container that can hold at least n bytes */
35 static
36 PmReturn_t
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);
48 pb->length = n;
50 *r_pobj = (pPmObj_t)pb;
51 return retval;
55 /* Returns the int or one-char string as a byte */
56 static
57 PmReturn_t
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);
67 return retval;
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);
78 return retval;
80 *b = ((pPmString_t)pobj)->val[0];
83 else
85 PM_RAISE(retval, PM_RET_EX_TYPE);
87 return retval;
91 PmReturn_t
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;
97 pPmObj_t pitem;
98 int32_t i;
99 int16_t n;
100 uint8_t b;
101 uint8_t objid;
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,
107 PM_NONE,
108 (pPmObj_t *)&pba);
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))
116 case OBJ_TYPE_INT:
117 i = ((pPmInt_t)pobj)->val;
118 if ((i < 0) || (i > 65535))
120 PM_RAISE(retval, PM_RET_EX_VAL);
121 return retval;
123 n = i;
124 break;
126 case OBJ_TYPE_STR:
127 n = ((pPmString_t)pobj)->length;
128 break;
130 case OBJ_TYPE_LST:
131 n = ((pPmList_t)pobj)->length;
132 break;
134 case OBJ_TYPE_TUP:
135 n = ((pPmTuple_t)pobj)->length;
136 break;
138 case OBJ_TYPE_BYA:
139 n = ((pPmBytearray_t)pobj)->length;
140 break;
142 default:
143 PM_RAISE(retval, PM_RET_EX_TYPE);
144 return retval;
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);
151 pba->length = n;
152 pba->val = C_NULL;
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);
159 pba->val = pb;
161 /* Fill the bytes */
162 switch (OBJ_GET_TYPE(pobj))
164 case OBJ_TYPE_INT:
165 sli_memset((unsigned char *)&(pb->val), '\0', n);
166 break;
168 case OBJ_TYPE_BYA:
169 pitem = (pPmObj_t)((pPmBytearray_t)pobj)->val;
170 sli_memcpy(&(pb->val[0]), &(((pPmBytes_t)pitem)->val[0]), n);
171 break;
173 case OBJ_TYPE_STR:
174 sli_memcpy(&(pb->val[0]), &(((pPmString_t)pobj)->val[0]), n);
175 break;
177 case OBJ_TYPE_LST:
178 case OBJ_TYPE_TUP:
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);
185 pb->val[i] = b;
187 break;
190 *r_pobj = (pPmObj_t)pba;
191 return retval;
195 PmReturn_t
196 bytearray_getItem(pPmObj_t pobj, int16_t index, pPmObj_t *r_pobj)
198 PmReturn_t retval = PM_RET_OK;
199 pPmBytearray_t pba;
200 pPmBytes_t pb;
201 int32_t n;
203 pba = (pPmBytearray_t)pobj;
205 /* Adjust a negative index */
206 if (index < 0)
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);
215 return retval;
218 /* Create int from byte at index */
219 pb = pba->val;
220 n = (int32_t)pb->val[index];
221 retval = int_new(n, r_pobj);
223 return retval;
227 PmReturn_t
228 bytearray_setItem(pPmObj_t pba, int16_t index, pPmObj_t pobj)
230 PmReturn_t retval;
231 pPmBytes_t pb;
232 uint8_t b = 0;
234 /* Adjust a negative index */
235 if (index < 0)
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);
244 return retval;
247 /* Set the item */
248 retval = bytes_getByteFromObj(pobj, &b);
249 pb = ((pPmBytearray_t)pba)->val;
250 pb->val[index] = b;
252 return retval;
256 PmReturn_t
257 bytearray_print(pPmObj_t pobj)
259 PmReturn_t retval;
260 pPmBytes_t pb;
262 obj_print(PM_BYTEARRAY_STR, C_FALSE, C_FALSE);
263 plat_putByte('(');
264 plat_putByte('b');
265 pb = ((pPmBytearray_t)pobj)->val;
266 retval = string_printFormattedBytes(&(pb->val[0]),
267 C_TRUE,
268 ((pPmBytearray_t)pobj)->length);
269 plat_putByte(')');
270 return retval;
272 #endif /* HAVE_BYTEARRAY */