1 /*
2  * Python object definition of the sequence and iterator object of stores
3  *
4  * Copyright (C) 2011-2021, Joachim Metz <joachim.metz@gmail.com>
5  *
6  * Refer to AUTHORS for acknowledgements.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <common.h>
23 #include <types.h>
24 
25 #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI )
26 #include <stdlib.h>
27 #endif
28 
29 #include "pyvshadow_libcerror.h"
30 #include "pyvshadow_libvshadow.h"
31 #include "pyvshadow_python.h"
32 #include "pyvshadow_store.h"
33 #include "pyvshadow_stores.h"
34 
35 PySequenceMethods pyvshadow_stores_sequence_methods = {
36 	/* sq_length */
37 	(lenfunc) pyvshadow_stores_len,
38 	/* sq_concat */
39 	0,
40 	/* sq_repeat */
41 	0,
42 	/* sq_item */
43 	(ssizeargfunc) pyvshadow_stores_getitem,
44 	/* sq_slice */
45 	0,
46 	/* sq_ass_item */
47 	0,
48 	/* sq_ass_slice */
49 	0,
50 	/* sq_contains */
51 	0,
52 	/* sq_inplace_concat */
53 	0,
54 	/* sq_inplace_repeat */
55 	0
56 };
57 
58 PyTypeObject pyvshadow_stores_type_object = {
59 	PyVarObject_HEAD_INIT( NULL, 0 )
60 
61 	/* tp_name */
62 	"pyvshadow.stores",
63 	/* tp_basicsize */
64 	sizeof( pyvshadow_stores_t ),
65 	/* tp_itemsize */
66 	0,
67 	/* tp_dealloc */
68 	(destructor) pyvshadow_stores_free,
69 	/* tp_print */
70 	0,
71 	/* tp_getattr */
72 	0,
73 	/* tp_setattr */
74 	0,
75 	/* tp_compare */
76 	0,
77 	/* tp_repr */
78 	0,
79 	/* tp_as_number */
80 	0,
81 	/* tp_as_sequence */
82 	&pyvshadow_stores_sequence_methods,
83 	/* tp_as_mapping */
84 	0,
85 	/* tp_hash */
86 	0,
87 	/* tp_call */
88 	0,
89 	/* tp_str */
90 	0,
91 	/* tp_getattro */
92 	0,
93 	/* tp_setattro */
94 	0,
95 	/* tp_as_buffer */
96 	0,
97 	/* tp_flags */
98 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,
99 	/* tp_doc */
100 	"pyvshadow sequence and iterator object of stores",
101 	/* tp_traverse */
102 	0,
103 	/* tp_clear */
104 	0,
105 	/* tp_richcompare */
106 	0,
107 	/* tp_weaklistoffset */
108 	0,
109 	/* tp_iter */
110 	(getiterfunc) pyvshadow_stores_iter,
111 	/* tp_iternext */
112 	(iternextfunc) pyvshadow_stores_iternext,
113 	/* tp_methods */
114 	0,
115 	/* tp_members */
116 	0,
117 	/* tp_getset */
118 	0,
119 	/* tp_base */
120 	0,
121 	/* tp_dict */
122 	0,
123 	/* tp_descr_get */
124 	0,
125 	/* tp_descr_set */
126 	0,
127 	/* tp_dictoffset */
128 	0,
129 	/* tp_init */
130 	(initproc) pyvshadow_stores_init,
131 	/* tp_alloc */
132 	0,
133 	/* tp_new */
134 	0,
135 	/* tp_free */
136 	0,
137 	/* tp_is_gc */
138 	0,
139 	/* tp_bases */
140 	NULL,
141 	/* tp_mro */
142 	NULL,
143 	/* tp_cache */
144 	NULL,
145 	/* tp_subclasses */
146 	NULL,
147 	/* tp_weaklist */
148 	NULL,
149 	/* tp_del */
150 	0
151 };
152 
153 /* Creates a new stores sequence and iterator object
154  * Returns a Python object if successful or NULL on error
155  */
pyvshadow_stores_new(PyObject * parent_object,PyObject * (* get_item_by_index)(PyObject * parent_object,int index),int number_of_items)156 PyObject *pyvshadow_stores_new(
157            PyObject *parent_object,
158            PyObject* (*get_item_by_index)(
159                         PyObject *parent_object,
160                         int index ),
161            int number_of_items )
162 {
163 	pyvshadow_stores_t *sequence_object = NULL;
164 	static char *function               = "pyvshadow_stores_new";
165 
166 	if( parent_object == NULL )
167 	{
168 		PyErr_Format(
169 		 PyExc_ValueError,
170 		 "%s: invalid parent object.",
171 		 function );
172 
173 		return( NULL );
174 	}
175 	if( get_item_by_index == NULL )
176 	{
177 		PyErr_Format(
178 		 PyExc_ValueError,
179 		 "%s: invalid get item by index function.",
180 		 function );
181 
182 		return( NULL );
183 	}
184 	/* Make sure the stores values are initialized
185 	 */
186 	sequence_object = PyObject_New(
187 	                   struct pyvshadow_stores,
188 	                   &pyvshadow_stores_type_object );
189 
190 	if( sequence_object == NULL )
191 	{
192 		PyErr_Format(
193 		 PyExc_MemoryError,
194 		 "%s: unable to create sequence object.",
195 		 function );
196 
197 		goto on_error;
198 	}
199 	sequence_object->parent_object     = parent_object;
200 	sequence_object->get_item_by_index = get_item_by_index;
201 	sequence_object->current_index     = 0;
202 	sequence_object->number_of_items   = number_of_items;
203 
204 	Py_IncRef(
205 	 (PyObject *) sequence_object->parent_object );
206 
207 	return( (PyObject *) sequence_object );
208 
209 on_error:
210 	if( sequence_object != NULL )
211 	{
212 		Py_DecRef(
213 		 (PyObject *) sequence_object );
214 	}
215 	return( NULL );
216 }
217 
218 /* Initializes a stores sequence and iterator object
219  * Returns 0 if successful or -1 on error
220  */
pyvshadow_stores_init(pyvshadow_stores_t * sequence_object)221 int pyvshadow_stores_init(
222      pyvshadow_stores_t *sequence_object )
223 {
224 	static char *function = "pyvshadow_stores_init";
225 
226 	if( sequence_object == NULL )
227 	{
228 		PyErr_Format(
229 		 PyExc_ValueError,
230 		 "%s: invalid sequence object.",
231 		 function );
232 
233 		return( -1 );
234 	}
235 	/* Make sure the stores values are initialized
236 	 */
237 	sequence_object->parent_object     = NULL;
238 	sequence_object->get_item_by_index = NULL;
239 	sequence_object->current_index     = 0;
240 	sequence_object->number_of_items   = 0;
241 
242 	PyErr_Format(
243 	 PyExc_NotImplementedError,
244 	 "%s: initialize of stores not supported.",
245 	 function );
246 
247 	return( -1 );
248 }
249 
250 /* Frees a stores sequence object
251  */
pyvshadow_stores_free(pyvshadow_stores_t * sequence_object)252 void pyvshadow_stores_free(
253       pyvshadow_stores_t *sequence_object )
254 {
255 	struct _typeobject *ob_type = NULL;
256 	static char *function       = "pyvshadow_stores_free";
257 
258 	if( sequence_object == NULL )
259 	{
260 		PyErr_Format(
261 		 PyExc_ValueError,
262 		 "%s: invalid sequence object.",
263 		 function );
264 
265 		return;
266 	}
267 	ob_type = Py_TYPE(
268 	           sequence_object );
269 
270 	if( ob_type == NULL )
271 	{
272 		PyErr_Format(
273 		 PyExc_ValueError,
274 		 "%s: missing ob_type.",
275 		 function );
276 
277 		return;
278 	}
279 	if( ob_type->tp_free == NULL )
280 	{
281 		PyErr_Format(
282 		 PyExc_ValueError,
283 		 "%s: invalid ob_type - missing tp_free.",
284 		 function );
285 
286 		return;
287 	}
288 	if( sequence_object->parent_object != NULL )
289 	{
290 		Py_DecRef(
291 		 (PyObject *) sequence_object->parent_object );
292 	}
293 	ob_type->tp_free(
294 	 (PyObject*) sequence_object );
295 }
296 
297 /* The stores len() function
298  */
pyvshadow_stores_len(pyvshadow_stores_t * sequence_object)299 Py_ssize_t pyvshadow_stores_len(
300             pyvshadow_stores_t *sequence_object )
301 {
302 	static char *function = "pyvshadow_stores_len";
303 
304 	if( sequence_object == NULL )
305 	{
306 		PyErr_Format(
307 		 PyExc_ValueError,
308 		 "%s: invalid sequence object.",
309 		 function );
310 
311 		return( -1 );
312 	}
313 	return( (Py_ssize_t) sequence_object->number_of_items );
314 }
315 
316 /* The stores getitem() function
317  */
pyvshadow_stores_getitem(pyvshadow_stores_t * sequence_object,Py_ssize_t item_index)318 PyObject *pyvshadow_stores_getitem(
319            pyvshadow_stores_t *sequence_object,
320            Py_ssize_t item_index )
321 {
322 	PyObject *store_object = NULL;
323 	static char *function  = "pyvshadow_stores_getitem";
324 
325 	if( sequence_object == NULL )
326 	{
327 		PyErr_Format(
328 		 PyExc_ValueError,
329 		 "%s: invalid sequence object.",
330 		 function );
331 
332 		return( NULL );
333 	}
334 	if( sequence_object->get_item_by_index == NULL )
335 	{
336 		PyErr_Format(
337 		 PyExc_ValueError,
338 		 "%s: invalid sequence object - missing get item by index function.",
339 		 function );
340 
341 		return( NULL );
342 	}
343 	if( sequence_object->number_of_items < 0 )
344 	{
345 		PyErr_Format(
346 		 PyExc_ValueError,
347 		 "%s: invalid sequence object - invalid number of items.",
348 		 function );
349 
350 		return( NULL );
351 	}
352 	if( ( item_index < 0 )
353 	 || ( item_index >= (Py_ssize_t) sequence_object->number_of_items ) )
354 	{
355 		PyErr_Format(
356 		 PyExc_ValueError,
357 		 "%s: invalid invalid item index value out of bounds.",
358 		 function );
359 
360 		return( NULL );
361 	}
362 	store_object = sequence_object->get_item_by_index(
363 	                sequence_object->parent_object,
364 	                (int) item_index );
365 
366 	return( store_object );
367 }
368 
369 /* The stores iter() function
370  */
pyvshadow_stores_iter(pyvshadow_stores_t * sequence_object)371 PyObject *pyvshadow_stores_iter(
372            pyvshadow_stores_t *sequence_object )
373 {
374 	static char *function = "pyvshadow_stores_iter";
375 
376 	if( sequence_object == NULL )
377 	{
378 		PyErr_Format(
379 		 PyExc_ValueError,
380 		 "%s: invalid sequence object.",
381 		 function );
382 
383 		return( NULL );
384 	}
385 	Py_IncRef(
386 	 (PyObject *) sequence_object );
387 
388 	return( (PyObject *) sequence_object );
389 }
390 
391 /* The stores iternext() function
392  */
pyvshadow_stores_iternext(pyvshadow_stores_t * sequence_object)393 PyObject *pyvshadow_stores_iternext(
394            pyvshadow_stores_t *sequence_object )
395 {
396 	PyObject *store_object = NULL;
397 	static char *function  = "pyvshadow_stores_iternext";
398 
399 	if( sequence_object == NULL )
400 	{
401 		PyErr_Format(
402 		 PyExc_ValueError,
403 		 "%s: invalid sequence object.",
404 		 function );
405 
406 		return( NULL );
407 	}
408 	if( sequence_object->get_item_by_index == NULL )
409 	{
410 		PyErr_Format(
411 		 PyExc_ValueError,
412 		 "%s: invalid sequence object - missing get item by index function.",
413 		 function );
414 
415 		return( NULL );
416 	}
417 	if( sequence_object->current_index < 0 )
418 	{
419 		PyErr_Format(
420 		 PyExc_ValueError,
421 		 "%s: invalid sequence object - invalid current index.",
422 		 function );
423 
424 		return( NULL );
425 	}
426 	if( sequence_object->number_of_items < 0 )
427 	{
428 		PyErr_Format(
429 		 PyExc_ValueError,
430 		 "%s: invalid sequence object - invalid number of items.",
431 		 function );
432 
433 		return( NULL );
434 	}
435 	if( sequence_object->current_index >= sequence_object->number_of_items )
436 	{
437 		PyErr_SetNone(
438 		 PyExc_StopIteration );
439 
440 		return( NULL );
441 	}
442 	store_object = sequence_object->get_item_by_index(
443 	                sequence_object->parent_object,
444 	                sequence_object->current_index );
445 
446 	if( store_object != NULL )
447 	{
448 		sequence_object->current_index++;
449 	}
450 	return( store_object );
451 }
452 
453