~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/_static_tuple_c.c

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-10-13 06:08:53 UTC
  • mfrom: (4737.1.1 merge-2.0-into-devel)
  • Revision ID: pqm@pqm.ubuntu.com-20091013060853-erk2aaj80fnkrv25
(andrew) Merge lp:bzr/2.0 into lp:bzr, including fixes for #322807,
        #389413, #402623 and documentation improvements.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2009, 2010 Canonical Ltd
 
1
/* Copyright (C) 2009 Canonical Ltd
2
2
 * 
3
3
 * This program is free software; you can redistribute it and/or modify
4
4
 * it under the terms of the GNU General Public License as published by
140
140
StaticTuple_New(Py_ssize_t size)
141
141
{
142
142
    StaticTuple *stuple;
143
 
 
144
 
    if (size < 0 || size > 255) {
145
 
        /* Too big or too small */
146
 
        PyErr_SetString(PyExc_ValueError, "StaticTuple(...)"
147
 
            " takes from 0 to 255 items");
 
143
    if (size < 0) {
 
144
        PyErr_BadInternalCall();
148
145
        return NULL;
149
146
    }
 
147
 
150
148
    if (size == 0 && _empty_tuple != NULL) {
151
149
        Py_INCREF(_empty_tuple);
152
150
        return _empty_tuple;
176
174
}
177
175
 
178
176
 
179
 
static StaticTuple *
180
 
StaticTuple_FromSequence(PyObject *sequence)
181
 
{
182
 
    StaticTuple *new = NULL;
183
 
    PyObject *as_tuple = NULL;
184
 
    PyObject *item;
185
 
    Py_ssize_t i, size;
186
 
 
187
 
    if (StaticTuple_CheckExact(sequence)) {
188
 
        Py_INCREF(sequence);
189
 
        return (StaticTuple *)sequence;
190
 
    }
191
 
    if (!PySequence_Check(sequence)) {
192
 
        as_tuple = PySequence_Tuple(sequence);
193
 
        if (as_tuple == NULL)
194
 
            goto done;
195
 
        sequence = as_tuple;
196
 
    }
197
 
    size = PySequence_Size(sequence);
198
 
    if (size == -1) {
199
 
        goto done;
200
 
    }
201
 
    new = StaticTuple_New(size);
202
 
    if (new == NULL) {
203
 
        goto done;
204
 
    }
205
 
    for (i = 0; i < size; ++i) {
206
 
        // This returns a new reference, which we then 'steal' with 
207
 
        // StaticTuple_SET_ITEM
208
 
        item = PySequence_GetItem(sequence, i);
209
 
        if (item == NULL) {
210
 
            Py_DECREF(new);
211
 
            new = NULL;
212
 
            goto done;
213
 
        }
214
 
        StaticTuple_SET_ITEM(new, i, item);
215
 
    }
216
 
done:
217
 
    Py_XDECREF(as_tuple);
218
 
    return (StaticTuple *)new;
219
 
}
220
 
 
221
 
static StaticTuple *
222
 
StaticTuple_from_sequence(PyObject *self, PyObject *args, PyObject *kwargs)
223
 
{
224
 
    PyObject *sequence;
225
 
    if (!PyArg_ParseTuple(args, "O", &sequence))
226
 
        return NULL;
227
 
    return StaticTuple_FromSequence(sequence);
228
 
}
229
 
 
230
 
 
231
 
/* Check that all items we point to are 'valid' */
232
 
static int
233
 
StaticTuple_check_items(StaticTuple *self)
234
 
{
235
 
    int i;
236
 
    PyObject *obj;
237
 
 
238
 
    for (i = 0; i < self->size; ++i) {
239
 
        obj = self->items[i];
240
 
        if (obj == NULL) {
241
 
            PyErr_SetString(PyExc_RuntimeError, "StaticTuple(...)"
242
 
                " should not have a NULL entry.");
243
 
            return 0;
244
 
        }
245
 
        if (PyString_CheckExact(obj)
246
 
            || StaticTuple_CheckExact(obj)
247
 
            || obj == Py_None
248
 
            || PyBool_Check(obj)
249
 
            || PyInt_CheckExact(obj)
250
 
            || PyLong_CheckExact(obj)
251
 
            || PyFloat_CheckExact(obj)
252
 
            || PyUnicode_CheckExact(obj)
253
 
            ) continue;
254
 
        PyErr_Format(PyExc_TypeError, "StaticTuple(...)"
255
 
            " requires that all items are one of"
256
 
            " str, StaticTuple, None, bool, int, long, float, or unicode"
257
 
            " not %s.", Py_TYPE(obj)->tp_name);
258
 
        return 0;
259
 
    }
260
 
    return 1;
261
 
}
262
 
 
263
177
static PyObject *
264
178
StaticTuple_new_constructor(PyTypeObject *type, PyObject *args, PyObject *kwds)
265
179
{
277
191
    }
278
192
    len = PyTuple_GET_SIZE(args);
279
193
    if (len < 0 || len > 255) {
280
 
        /* Check the length here so we can raise a TypeError instead of
281
 
         * StaticTuple_New's ValueError.
282
 
         */
283
 
        PyErr_SetString(PyExc_TypeError, "StaticTuple(...)"
 
194
        /* Too big or too small */
 
195
        PyErr_SetString(PyExc_ValueError, "StaticTuple.__init__(...)"
284
196
            " takes from 0 to 255 items");
285
197
        return NULL;
286
198
    }
290
202
    }
291
203
    for (i = 0; i < len; ++i) {
292
204
        obj = PyTuple_GET_ITEM(args, i);
 
205
        if (!PyString_CheckExact(obj)) {
 
206
            if (!StaticTuple_CheckExact(obj)) {
 
207
                PyErr_SetString(PyExc_TypeError, "StaticTuple.__init__(...)"
 
208
                    " requires that all items are strings or StaticTuple.");
 
209
                type->tp_dealloc((PyObject *)self);
 
210
                return NULL;
 
211
            }
 
212
        }
293
213
        Py_INCREF(obj);
294
214
        self->items[i] = obj;
295
215
    }
296
 
    if (!StaticTuple_check_items(self)) {
297
 
        type->tp_dealloc((PyObject *)self);
298
 
        return NULL;
299
 
    }
300
216
    return (PyObject *)self;
301
217
}
302
218
 
314
230
    if (tuple_repr == NULL) {
315
231
        return NULL;
316
232
    }
317
 
    result = PyString_FromFormat("StaticTuple%s",
318
 
                                 PyString_AsString(tuple_repr));
 
233
    result = PyString_FromFormat("%s%s", Py_TYPE(self)->tp_name,
 
234
                                         PyString_AsString(tuple_repr));
319
235
    return result;
320
236
}
321
237
 
495
411
            /* Both are StaticTuple types, so recurse */
496
412
            result = StaticTuple_richcompare(v_obj, w_obj, Py_EQ);
497
413
        } else {
498
 
            /* Fall back to generic richcompare */
499
 
            result = PyObject_RichCompare(v_obj, w_obj, Py_EQ);
 
414
            /* Not the same type, obviously they won't compare equal */
 
415
            break;
500
416
        }
501
417
        if (result == NULL) {
502
418
            return NULL; /* There seems to be an error */
503
419
        }
 
420
        if (result == Py_NotImplemented) {
 
421
            PyErr_BadInternalCall();
 
422
            Py_DECREF(result);
 
423
            return NULL;
 
424
        }
504
425
        if (result == Py_False) {
505
 
            // This entry is not identical, Shortcut for Py_EQ
 
426
            /* This entry is not identical
 
427
             * Shortcut for Py_EQ
 
428
             */
506
429
            if (op == Py_EQ) {
507
430
                return result;
508
431
            }
556
479
        /* Both are StaticTuple types, so recurse */
557
480
        return StaticTuple_richcompare(v_obj, w_obj, op);
558
481
    } else {
559
 
        return PyObject_RichCompare(v_obj, w_obj, op);
 
482
        Py_INCREF(Py_NotImplemented);
 
483
        return Py_NotImplemented;
560
484
    }
561
485
}
562
486
 
584
508
 
585
509
 
586
510
static PyObject *
587
 
StaticTuple_reduce(StaticTuple *self)
588
 
{
589
 
    PyObject *result = NULL, *as_tuple = NULL;
590
 
 
591
 
    result = PyTuple_New(2);
592
 
    if (!result) {
593
 
        return NULL;
594
 
    }
595
 
    as_tuple = StaticTuple_as_tuple(self);
596
 
    if (as_tuple == NULL) {
597
 
        Py_DECREF(result);
598
 
        return NULL;
599
 
    }
600
 
    Py_INCREF(&StaticTuple_Type);
601
 
    PyTuple_SET_ITEM(result, 0, (PyObject *)&StaticTuple_Type);
602
 
    PyTuple_SET_ITEM(result, 1, as_tuple);
603
 
    return result;
604
 
}
605
 
 
606
 
static char StaticTuple_reduce_doc[] = "__reduce__() => tuple\n";
607
 
 
608
 
 
609
 
static PyObject *
610
 
StaticTuple_add(PyObject *v, PyObject *w)
611
 
{
612
 
    Py_ssize_t i, len_v, len_w;
613
 
    PyObject *item;
614
 
    StaticTuple *result;
615
 
     /* StaticTuples and plain tuples may be added (concatenated) to
616
 
      * StaticTuples.
617
 
      */
618
 
    if (StaticTuple_CheckExact(v)) {
619
 
        len_v = ((StaticTuple*)v)->size;
620
 
    } else if (PyTuple_Check(v)) {
621
 
        len_v = PyTuple_GET_SIZE(v);
622
 
    } else {
623
 
        Py_INCREF(Py_NotImplemented);
624
 
        return Py_NotImplemented;
625
 
    }
626
 
    if (StaticTuple_CheckExact(w)) {
627
 
        len_w = ((StaticTuple*)w)->size;
628
 
    } else if (PyTuple_Check(w)) {
629
 
        len_w = PyTuple_GET_SIZE(w);
630
 
    } else {
631
 
        Py_INCREF(Py_NotImplemented);
632
 
        return Py_NotImplemented;
633
 
    }
634
 
    result = StaticTuple_New(len_v + len_w);
635
 
    if (result == NULL)
636
 
        return NULL;
637
 
    for (i = 0; i < len_v; ++i) {
638
 
        // This returns a new reference, which we then 'steal' with 
639
 
        // StaticTuple_SET_ITEM
640
 
        item = PySequence_GetItem(v, i);
641
 
        if (item == NULL) {
642
 
            Py_DECREF(result);
643
 
            return NULL;
644
 
        }
645
 
        StaticTuple_SET_ITEM(result, i, item);
646
 
    }
647
 
    for (i = 0; i < len_w; ++i) {
648
 
        item = PySequence_GetItem(w, i);
649
 
        if (item == NULL) {
650
 
            Py_DECREF(result);
651
 
            return NULL;
652
 
        }
653
 
        StaticTuple_SET_ITEM(result, i+len_v, item);
654
 
    }
655
 
    if (!StaticTuple_check_items(result)) {
656
 
        Py_DECREF(result);
657
 
        return NULL;
658
 
    }
659
 
    return (PyObject *)result;
660
 
}
661
 
 
662
 
static PyObject *
663
511
StaticTuple_item(StaticTuple *self, Py_ssize_t offset)
664
512
{
665
513
    PyObject *obj;
703
551
    return 0;
704
552
}
705
553
 
706
 
 
707
 
static PyObject *
708
 
StaticTuple_sizeof(StaticTuple *self)
709
 
{
710
 
        Py_ssize_t res;
711
 
 
712
 
        res = _PyObject_SIZE(&StaticTuple_Type) + (int)self->size * sizeof(void*);
713
 
        return PyInt_FromSsize_t(res);
714
 
}
715
 
 
716
 
 
717
 
 
718
554
static char StaticTuple_doc[] =
719
555
    "C implementation of a StaticTuple structure."
720
556
    "\n This is used as StaticTuple(item1, item2, item3)"
729
565
    {"intern", (PyCFunction)StaticTuple_Intern, METH_NOARGS, StaticTuple_Intern_doc},
730
566
    {"_is_interned", (PyCFunction)StaticTuple__is_interned, METH_NOARGS,
731
567
     StaticTuple__is_interned_doc},
732
 
    {"from_sequence", (PyCFunction)StaticTuple_from_sequence,
733
 
     METH_STATIC | METH_VARARGS,
734
 
     "Create a StaticTuple from a given sequence. This functions"
735
 
     " the same as the tuple() constructor."},
736
 
    {"__reduce__", (PyCFunction)StaticTuple_reduce, METH_NOARGS, StaticTuple_reduce_doc},
737
 
    {"__sizeof__",  (PyCFunction)StaticTuple_sizeof, METH_NOARGS}, 
738
568
    {NULL, NULL} /* sentinel */
739
569
};
740
570
 
741
 
 
742
 
static PyNumberMethods StaticTuple_as_number = {
743
 
    (binaryfunc) StaticTuple_add,   /* nb_add */
744
 
    0,                              /* nb_subtract */
745
 
    0,                              /* nb_multiply */
746
 
    0,                              /* nb_divide */
747
 
    0,                              /* nb_remainder */
748
 
    0,                              /* nb_divmod */
749
 
    0,                              /* nb_power */
750
 
    0,                              /* nb_negative */
751
 
    0,                              /* nb_positive */
752
 
    0,                              /* nb_absolute */
753
 
    0,                              /* nb_nonzero */
754
 
    0,                              /* nb_invert */
755
 
    0,                              /* nb_lshift */
756
 
    0,                              /* nb_rshift */
757
 
    0,                              /* nb_and */
758
 
    0,                              /* nb_xor */
759
 
    0,                              /* nb_or */
760
 
    0,                              /* nb_coerce */
761
 
};
762
 
    
763
 
 
764
571
static PySequenceMethods StaticTuple_as_sequence = {
765
572
    (lenfunc)StaticTuple_length,            /* sq_length */
766
573
    0,                              /* sq_concat */
782
589
PyTypeObject StaticTuple_Type = {
783
590
    PyObject_HEAD_INIT(NULL)
784
591
    0,                                           /* ob_size */
785
 
    "bzrlib._static_tuple_c.StaticTuple",        /* tp_name */
 
592
    "StaticTuple",                               /* tp_name */
786
593
    sizeof(StaticTuple),                         /* tp_basicsize */
787
594
    sizeof(PyObject *),                          /* tp_itemsize */
788
595
    (destructor)StaticTuple_dealloc,             /* tp_dealloc */
791
598
    0,                                           /* tp_setattr */
792
599
    0,                                           /* tp_compare */
793
600
    (reprfunc)StaticTuple_repr,                  /* tp_repr */
794
 
    &StaticTuple_as_number,                      /* tp_as_number */
 
601
    0,                                           /* tp_as_number */
795
602
    &StaticTuple_as_sequence,                    /* tp_as_sequence */
796
603
    0,                                           /* tp_as_mapping */
797
604
    (hashfunc)StaticTuple_hash,                  /* tp_hash */
798
605
    0,                                           /* tp_call */
799
606
    0,                                           /* tp_str */
800
 
    0,                                           /* tp_getattro */
 
607
    PyObject_GenericGetAttr,                     /* tp_getattro */
801
608
    0,                                           /* tp_setattro */
802
609
    0,                                           /* tp_as_buffer */
803
 
    /* Py_TPFLAGS_CHECKTYPES tells the number operations that they shouldn't
804
 
     * try to 'coerce' but instead stuff like 'add' will check it arguments.
805
 
     */
806
 
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES,  /* tp_flags*/
 
610
    Py_TPFLAGS_DEFAULT,                          /* tp_flags*/
807
611
    StaticTuple_doc,                             /* tp_doc */
808
612
    /* gc.get_referents checks the IS_GC flag before it calls tp_traverse
809
613
     * And we don't include this object in the garbage collector because we
880
684
        "StaticTuple *(Py_ssize_t)");
881
685
    _export_function(m, "StaticTuple_Intern", StaticTuple_Intern,
882
686
        "StaticTuple *(StaticTuple *)");
883
 
    _export_function(m, "StaticTuple_FromSequence", StaticTuple_FromSequence,
884
 
        "StaticTuple *(PyObject *)");
885
687
    _export_function(m, "_StaticTuple_CheckExact", _StaticTuple_CheckExact,
886
688
        "int(PyObject *)");
887
689
}
907
709
     */
908
710
    set_module = PyImport_ImportModule("bzrlib._simple_set_pyx");
909
711
    if (set_module == NULL) {
 
712
        // fprintf(stderr, "Failed to import bzrlib._simple_set_pyx\n");
910
713
        goto end;
911
714
    }
912
715
    /* Add the _simple_set_pyx into sys.modules at the appropriate location. */
913
716
    sys_module = PyImport_ImportModule("sys");
914
717
    if (sys_module == NULL) {
 
718
        // fprintf(stderr, "Failed to import sys\n");
915
719
        goto end;
916
720
    }
917
721
    modules = PyObject_GetAttrString(sys_module, "modules");
918
722
    if (modules == NULL || !PyDict_Check(modules)) {
 
723
        // fprintf(stderr, "Failed to find sys.modules\n");
919
724
        goto end;
920
725
    }
921
726
    PyDict_SetItemString(modules, "_simple_set_pyx", set_module);
934
739
{
935
740
    PyObject* m;
936
741
 
937
 
    StaticTuple_Type.tp_getattro = PyObject_GenericGetAttr;
938
742
    if (PyType_Ready(&StaticTuple_Type) < 0)
939
743
        return;
940
744
 
954
758
    setup_empty_tuple(m);
955
759
    setup_c_api(m);
956
760
}
957
 
 
958
 
// vim: tabstop=4 sw=4 expandtab