update credits
[librepilot.git] / flight / libraries / PyMite / vm / seq.c
blob4c6f5bf41d09a0a0746af5181794a1db252b6b75
1 /*
2 # This file is Copyright 2006, 2007, 2009, 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__ 0x14
20 /**
21 * \file
22 * \brief Sequence
24 * Functions that operate on sequences
28 #include "pm.h"
32 * Compares two sequence objects
33 * Assumes both objects are of same type (guaranteed by obj_compare)
35 int8_t
36 seq_compare(pPmObj_t pobj1, pPmObj_t pobj2)
38 int16_t l1;
39 int16_t l2;
40 pPmObj_t pa;
41 pPmObj_t pb;
42 PmReturn_t retval;
43 int8_t retcompare;
45 /* Get the lengths of supported types or return differ */
46 if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_TUP)
48 l1 = ((pPmTuple_t)pobj1)->length;
49 l2 = ((pPmTuple_t)pobj2)->length;
51 else if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_LST)
53 l1 = ((pPmList_t)pobj1)->length;
54 l2 = ((pPmList_t)pobj2)->length;
57 #ifdef HAVE_BYTEARRAY
58 else if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_BYA)
60 /* Return if the lengths differ */
61 l1 = ((pPmBytearray_t)pobj1)->length;
62 l2 = ((pPmBytearray_t)pobj2)->length;
63 if (l1 != l2)
65 return C_DIFFER;
68 return sli_strncmp((char const *)&(((pPmBytes_t)((pPmBytearray_t)pobj1)->val)->val),
69 (char const *)&(((pPmBytes_t)((pPmBytearray_t)pobj2)->val)->val),
70 l1)
71 ? C_DIFFER : C_SAME;
73 #endif /* HAVE_BYTEARRAY */
75 else
77 return C_DIFFER;
80 /* Return if the lengths differ */
81 if (l1 != l2)
83 return C_DIFFER;
86 /* Compare all items in the sequences */
87 while (--l1 >= 0)
89 retval = seq_getSubscript(pobj1, l1, &pa);
90 if (retval != PM_RET_OK)
92 return C_DIFFER;
94 retval = seq_getSubscript(pobj2, l1, &pb);
95 if (retval != PM_RET_OK)
97 return C_DIFFER;
99 retcompare = obj_compare(pa, pb);
100 if (retcompare != C_SAME)
102 return retcompare;
106 return C_SAME;
110 /* Returns the length of the sequence */
111 PmReturn_t
112 seq_getLength(pPmObj_t pobj, int16_t *r_index)
114 PmReturn_t retval = PM_RET_OK;
116 switch (OBJ_GET_TYPE(pobj))
118 case OBJ_TYPE_STR:
119 *r_index = ((pPmString_t)pobj)->length;
120 break;
122 case OBJ_TYPE_TUP:
123 *r_index = ((pPmTuple_t)pobj)->length;
124 break;
126 case OBJ_TYPE_LST:
127 *r_index = ((pPmList_t)pobj)->length;
128 break;
130 #ifdef HAVE_BYTEARRAY
131 case OBJ_TYPE_BYA:
132 *r_index = ((pPmBytearray_t)pobj)->length;
133 break;
134 #endif /* HAVE_BYTEARRAY */
136 default:
137 /* Raise TypeError, non-sequence object */
138 PM_RAISE(retval, PM_RET_EX_TYPE);
139 break;
142 return retval;
146 /* Returns the object sequence[index] */
147 PmReturn_t
148 seq_getSubscript(pPmObj_t pobj, int16_t index, pPmObj_t *r_pobj)
150 PmReturn_t retval;
151 uint8_t c;
153 switch (OBJ_GET_TYPE(pobj))
155 case OBJ_TYPE_STR:
156 /* Adjust for negative index */
157 if (index < 0)
159 index += ((pPmString_t)pobj)->length;
162 /* Raise IndexError if index is out of bounds */
163 if ((index < 0) || (index > ((pPmString_t)pobj)->length))
165 PM_RAISE(retval, PM_RET_EX_INDX);
166 break;
169 /* Get the character from the string */
170 c = ((pPmString_t)pobj)->val[index];
172 /* Create a new string from the character */
173 retval = string_newFromChar(c, r_pobj);
174 break;
176 case OBJ_TYPE_TUP:
177 /* Get the tuple item */
178 retval = tuple_getItem(pobj, index, r_pobj);
179 break;
181 case OBJ_TYPE_LST:
182 /* Get the list item */
183 retval = list_getItem(pobj, index, r_pobj);
184 break;
186 #ifdef HAVE_BYTEARRAY
187 case OBJ_TYPE_BYA:
188 retval = bytearray_getItem(pobj, index, r_pobj);
189 break;
190 #endif /* HAVE_BYTEARRAY */
192 default:
193 /* Raise TypeError, unsubscriptable object */
194 PM_RAISE(retval, PM_RET_EX_TYPE);
195 break;
198 return retval;
202 PmReturn_t
203 seqiter_getNext(pPmObj_t pobj, pPmObj_t *r_pitem)
205 PmReturn_t retval;
206 int16_t length;
208 C_ASSERT(pobj != C_NULL);
209 C_ASSERT(*r_pitem != C_NULL);
210 C_ASSERT(OBJ_GET_TYPE(pobj) == OBJ_TYPE_SQI);
213 * Raise TypeError if sequence iterator's object is not a sequence
214 * otherwise, the get sequence's length
216 retval = seq_getLength(((pPmSeqIter_t)pobj)->si_sequence, &length);
217 PM_RETURN_IF_ERROR(retval);
219 /* Raise StopIteration if at the end of the sequence */
220 if (((pPmSeqIter_t)pobj)->si_index == length)
222 /* Make null the pointer to the sequence */
223 ((pPmSeqIter_t)pobj)->si_sequence = C_NULL;
224 PM_RAISE(retval, PM_RET_EX_STOP);
225 return retval;
228 /* Get the item at the current index */
229 retval = seq_getSubscript(((pPmSeqIter_t)pobj)->si_sequence,
230 ((pPmSeqIter_t)pobj)->si_index, r_pitem);
232 /* Increment the index */
233 ((pPmSeqIter_t)pobj)->si_index++;
235 return retval;
239 PmReturn_t
240 seqiter_new(pPmObj_t pobj, pPmObj_t *r_pobj)
242 PmReturn_t retval;
243 uint8_t *pchunk;
244 pPmSeqIter_t psi;
246 C_ASSERT(pobj != C_NULL);
247 C_ASSERT(*r_pobj != C_NULL);
249 /* Raise a TypeError if pobj is not a sequence */
250 if ((OBJ_GET_TYPE(pobj) != OBJ_TYPE_STR)
251 && (OBJ_GET_TYPE(pobj) != OBJ_TYPE_TUP)
252 && (OBJ_GET_TYPE(pobj) != OBJ_TYPE_LST))
254 PM_RAISE(retval, PM_RET_EX_TYPE);
255 return retval;
258 /* Alloc a chunk for the sequence iterator obj */
259 retval = heap_getChunk(sizeof(PmSeqIter_t), &pchunk);
260 PM_RETURN_IF_ERROR(retval);
262 /* Set the sequence iterator's fields */
263 psi = (pPmSeqIter_t)pchunk;
264 OBJ_SET_TYPE(psi, OBJ_TYPE_SQI);
265 psi->si_sequence = pobj;
266 psi->si_index = 0;
268 *r_pobj = (pPmObj_t)psi;
269 return retval;