~mikeowen/pybindgen/pybindgen-extend-containers

« back to all changes in this revision

Viewing changes to pybindgen/container.py

  • Committer: Mike Owen
  • Date: 2013-02-07 08:10:46 UTC
  • Revision ID: mikeowen@llnl.gov-20130207081046-1tqrmo2wndssuveo
Beginning the process of adding more sequence methods to the default
pybindgen container wrappers.

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
    TypeConfigurationError, NotSupportedError
10
10
 
11
11
from typehandlers import codesink
12
 
from pytypeobject import PyTypeObject
 
12
from pytypeobject import PyTypeObject, PySequenceMethods
13
13
import settings
14
14
import utils
15
15
 
134
134
        self._pystruct = None
135
135
        self.pytypestruct = "***GIVE ME A NAME***"
136
136
        self.pytype = PyTypeObject()
 
137
        self.pyseq = PySequenceMethods()
137
138
 
138
139
        self.iter_pytypestruct = "***GIVE ME A NAME***"
139
140
        self.iter_pytype = PyTypeObject()
254
255
        self._iter_pystruct = "Py%s%sIter" % (prefix, self.mangled_full_name)
255
256
        self.iter_pytypestruct = "Py%s%sIter_Type" % (prefix,  self.mangled_full_name)
256
257
 
 
258
        self.sequence_methods_name = "%s__py_sequence_methods" % self.mangled_full_name
 
259
        self.pyseq.slots['variable'] = self.sequence_methods_name
 
260
 
257
261
        ## re-register the class type handlers, now with class full name
258
262
        self.register_alias(self.full_name)
259
263
 
339
343
 
340
344
    python_full_name = property(_get_python_full_name)
341
345
 
342
 
 
343
346
    def generate(self, code_sink, module, docstring=None):
344
347
        """Generates the class to a code sink"""
345
348
 
370
373
        self._generate_destructor(code_sink)
371
374
        self._generate_iter_methods(code_sink)
372
375
        self._generate_container_constructor(code_sink)
 
376
 
 
377
        # Generate the sequence methods
 
378
        self._generate_len_method(code_sink)
 
379
        self._generate_concat_method(code_sink)
 
380
        self._generate_repeat_method(code_sink)
 
381
        self._generate_item_method(code_sink)
 
382
 
373
383
        self._generate_type_structure(code_sink, docstring)
374
384
        
375
385
    def _generate_type_structure(self, code_sink, docstring):
376
386
        """generate the type structure"""
377
387
 
 
388
        self.pyseq.generate(code_sink)
 
389
 
378
390
        self.pytype.slots.setdefault("tp_basicsize", "sizeof(%s)" % (self.pystruct,))
379
391
        self.pytype.slots.setdefault("tp_flags", "Py_TPFLAGS_DEFAULT")
380
392
        self.pytype.slots.setdefault("typestruct", self.pytypestruct)
381
393
        self.pytype.slots.setdefault("tp_name", self.python_full_name)
 
394
        self.pytype.slots.setdefault("tp_as_sequence", '&' + self.sequence_methods_name)
382
395
        self.pytype.generate(code_sink)
383
396
 
384
397
        self.iter_pytype.slots.setdefault("tp_basicsize", "sizeof(%s)" % (self.iter_pystruct,))
508
521
        
509
522
 
510
523
 
 
524
    def _generate_len_method(self, code_sink):
 
525
        container_sq_len_function_name = "_wrap_%s__sq_len" % self.pystruct
 
526
        subst_vars = {
 
527
            'WRAPPER_NAME' : container_sq_len_function_name,
 
528
            'PYSTRUCT'     : self.pystruct,
 
529
            }
 
530
        code_sink.writeln(r'''
 
531
 
 
532
static Py_ssize_t
 
533
%(WRAPPER_NAME)s (%(PYSTRUCT)s *py_self)
 
534
{
 
535
    Py_ssize_t result;
 
536
    result = py_self->obj->size();
 
537
    return result;
 
538
}
 
539
 
 
540
''' % subst_vars)
 
541
        self.pyseq.slots.setdefault("sq_length", container_sq_len_function_name)
 
542
 
 
543
 
 
544
    def _generate_concat_method(self, code_sink):
 
545
        container_sq_concat_function_name = "_wrap_%s__sq_concat" % self.pystruct
 
546
        subst_vars = {
 
547
            'WRAPPER_NAME' : container_sq_concat_function_name,
 
548
            'PYSTRUCT'     : self.pystruct,
 
549
            'PYTYPESTRUCT' : self.pytypestruct,
 
550
            'CTYPE'        : self.full_name,
 
551
            'ADD_VALUE'    : self.container_traits.add_value_method,
 
552
            }
 
553
        code_sink.writeln(r'''
 
554
 
 
555
static PyObject*
 
556
%(WRAPPER_NAME)s (%(PYSTRUCT)s *py_self, %(PYSTRUCT)s *py_rhs)
 
557
{
 
558
    PyObject *py_result;
 
559
    %(PYSTRUCT)s *result;
 
560
    %(CTYPE)s::iterator itr;
 
561
    result = PyObject_GC_New(%(PYSTRUCT)s, &%(PYTYPESTRUCT)s);
 
562
    result->obj = new %(CTYPE)s(*(py_self->obj));
 
563
    for (itr = py_rhs->obj->begin(); itr != py_rhs->obj->end(); ++itr) {
 
564
        result->obj->%(ADD_VALUE)s(*itr);
 
565
    }
 
566
    py_result = Py_BuildValue((char *) "N", result);
 
567
    return py_result;
 
568
}
 
569
 
 
570
''' % subst_vars)
 
571
        self.pyseq.slots.setdefault("sq_concat", container_sq_concat_function_name)
 
572
 
 
573
 
 
574
    def _generate_repeat_method(self, code_sink):
 
575
        container_sq_repeat_function_name = "_wrap_%s__sq_repeat" % self.pystruct
 
576
        subst_vars = {
 
577
            'WRAPPER_NAME' : container_sq_repeat_function_name,
 
578
            'PYSTRUCT'     : self.pystruct,
 
579
            'PYTYPESTRUCT' : self.pytypestruct,
 
580
            'CTYPE'        : self.full_name,
 
581
            'ADD_VALUE'    : self.container_traits.add_value_method,
 
582
            }
 
583
        code_sink.writeln(r'''
 
584
 
 
585
static PyObject*
 
586
%(WRAPPER_NAME)s (%(PYSTRUCT)s *py_self, Py_ssize_t n)
 
587
{
 
588
    PyObject *py_result;
 
589
    %(PYSTRUCT)s *result;
 
590
    %(CTYPE)s::iterator itr;
 
591
    Py_ssize_t i;
 
592
    result = PyObject_GC_New(%(PYSTRUCT)s, &%(PYTYPESTRUCT)s);
 
593
    result->obj = new %(CTYPE)s();
 
594
    for (i = 0; i != n; ++i) {
 
595
        for (itr = py_self->obj->begin(); itr != py_self->obj->end(); ++itr) {
 
596
            result->obj->%(ADD_VALUE)s(*itr);
 
597
        }
 
598
    }
 
599
    py_result = Py_BuildValue((char *) "N", result);
 
600
    return py_result;
 
601
}
 
602
 
 
603
''' % subst_vars)
 
604
        self.pyseq.slots.setdefault("sq_repeat", container_sq_repeat_function_name)
 
605
 
 
606
 
 
607
 
 
608
    def _generate_item_method(self, code_sink):
 
609
        item_c_to_python_converter = self.module.get_root().generate_c_to_python_type_converter(self.value_type, code_sink)
 
610
        container_sq_item_function_name = "_wrap_%s__sq_item" % self.pystruct
 
611
        subst_vars = {
 
612
            'WRAPPER_NAME' : container_sq_item_function_name,
 
613
            'PYSTRUCT'     : self.pystruct,
 
614
            'PYTYPESTRUCT' : self.pytypestruct,
 
615
            'CTYPE'        : self.full_name,
 
616
            'ITEM_CTYPE'   : self.value_type.ctype,
 
617
            'VALUE_CONV'   : item_c_to_python_converter,
 
618
            }
 
619
        code_sink.writeln(r'''
 
620
 
 
621
static PyObject*
 
622
%(WRAPPER_NAME)s (%(PYSTRUCT)s *py_self, int i)
 
623
{
 
624
    PyObject *py_result;
 
625
    %(ITEM_CTYPE)s result;
 
626
    int j, n;
 
627
    n = py_self->obj->size();
 
628
    j = i %% n;
 
629
    if (j >= n) {
 
630
      PyErr_SetString(PyExc_IndexError, "Container index out of range");
 
631
    } else {
 
632
        py_result = %(VALUE_CONV)s(&(py_self->obj->at(j)));
 
633
    }
 
634
    return py_result;
 
635
}
 
636
 
 
637
''' % subst_vars)
 
638
        self.pyseq.slots.setdefault("sq_item", container_sq_item_function_name)
 
639
 
 
640
 
 
641
 
511
642
    def _generate_container_constructor(self, code_sink):
512
643
        container_tp_init_function_name = "_wrap_%s__tp_init" % (self.pystruct,)
513
644
        item_python_to_c_converter = self.module.get_root().generate_python_to_c_type_converter(self.value_type, code_sink)