~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/_static_tuple_c.c

  • Committer: John Arbash Meinel
  • Date: 2009-10-21 16:52:18 UTC
  • mfrom: (4761 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4771.
  • Revision ID: john@arbash-meinel.com-20091021165218-rxk2tt2ks7amc6m9
Bring in bzr.dev 4761 which includes CHKMap and CHKInventory tweaks.
It also brings in StaticTuple concatenation, and ability to hold None, etc.

Show diffs side-by-side

added added

removed removed

Lines of Context:
145
145
        return NULL;
146
146
    }
147
147
 
 
148
    if (size < 0 || size > 255) {
 
149
        /* Too big or too small */
 
150
        PyErr_SetString(PyExc_ValueError, "StaticTuple(...)"
 
151
            " takes from 0 to 255 items");
 
152
        return NULL;
 
153
    }
148
154
    if (size == 0 && _empty_tuple != NULL) {
149
155
        Py_INCREF(_empty_tuple);
150
156
        return _empty_tuple;
220
226
}
221
227
 
222
228
 
 
229
/* Check that all items we point to are 'valid' */
 
230
static int
 
231
StaticTuple_check_items(StaticTuple *self)
 
232
{
 
233
    int i;
 
234
    PyObject *obj;
 
235
 
 
236
    for (i = 0; i < self->size; ++i) {
 
237
        obj = self->items[i];
 
238
        if (obj == NULL) {
 
239
            PyErr_SetString(PyExc_RuntimeError, "StaticTuple(...)"
 
240
                " should not have a NULL entry.");
 
241
            return 0;
 
242
        }
 
243
        if (PyString_CheckExact(obj)
 
244
            || StaticTuple_CheckExact(obj)
 
245
            || obj == Py_None
 
246
            || PyBool_Check(obj)
 
247
            || PyInt_CheckExact(obj)
 
248
            || PyLong_CheckExact(obj)
 
249
            || PyFloat_CheckExact(obj)
 
250
            || PyUnicode_CheckExact(obj)
 
251
            ) continue;
 
252
        PyErr_Format(PyExc_TypeError, "StaticTuple(...)"
 
253
            " requires that all items are one of"
 
254
            " str, StaticTuple, None, bool, int, long, float, or unicode"
 
255
            " not %s.", Py_TYPE(obj)->tp_name);
 
256
        return 0;
 
257
    }
 
258
    return 1;
 
259
}
 
260
 
223
261
static PyObject *
224
262
StaticTuple_new_constructor(PyTypeObject *type, PyObject *args, PyObject *kwds)
225
263
{
236
274
        return NULL;
237
275
    }
238
276
    len = PyTuple_GET_SIZE(args);
239
 
    if (len < 0 || len > 255) {
240
 
        /* Too big or too small */
241
 
        PyErr_SetString(PyExc_ValueError, "StaticTuple.__init__(...)"
242
 
            " takes from 0 to 255 items");
243
 
        return NULL;
244
 
    }
245
277
    self = (StaticTuple *)StaticTuple_New(len);
246
278
    if (self == NULL) {
247
279
        return NULL;
248
280
    }
249
281
    for (i = 0; i < len; ++i) {
250
282
        obj = PyTuple_GET_ITEM(args, i);
251
 
        if (!PyString_CheckExact(obj)) {
252
 
            if (!StaticTuple_CheckExact(obj)) {
253
 
                PyErr_Format(PyExc_TypeError, "StaticTuple.__init__(...)"
254
 
                    " requires that all items are strings or StaticTuple"
255
 
                    " not %s", Py_TYPE(obj)->tp_name);
256
 
                type->tp_dealloc((PyObject *)self);
257
 
                return NULL;
258
 
            }
259
 
        }
260
283
        Py_INCREF(obj);
261
284
        self->items[i] = obj;
262
285
    }
 
286
    if (!StaticTuple_check_items(self)) {
 
287
        type->tp_dealloc((PyObject *)self);
 
288
        return NULL;
 
289
    }
263
290
    return (PyObject *)self;
264
291
}
265
292
 
458
485
            /* Both are StaticTuple types, so recurse */
459
486
            result = StaticTuple_richcompare(v_obj, w_obj, Py_EQ);
460
487
        } else {
461
 
            /* Not the same type, obviously they won't compare equal */
462
 
            break;
 
488
            /* Fall back to generic richcompare */
 
489
            result = PyObject_RichCompare(v_obj, w_obj, Py_EQ);
463
490
        }
464
491
        if (result == NULL) {
465
492
            return NULL; /* There seems to be an error */
466
493
        }
467
 
        if (result == Py_NotImplemented) {
468
 
            Py_DECREF(result);
469
 
            /* One side must have had a string and the other a StaticTuple.
470
 
             * This clearly means that they are not equal.
471
 
             */
472
 
            if (op == Py_EQ) {
473
 
                Py_INCREF(Py_False);
474
 
                return Py_False;
475
 
            }
476
 
            result = PyObject_RichCompare(v_obj, w_obj, Py_EQ);
477
 
        }
478
494
        if (result == Py_False) {
479
 
            /* This entry is not identical
480
 
             * Shortcut for Py_EQ
481
 
             */
 
495
            // This entry is not identical, Shortcut for Py_EQ
482
496
            if (op == Py_EQ) {
483
497
                return result;
484
498
            }
532
546
        /* Both are StaticTuple types, so recurse */
533
547
        return StaticTuple_richcompare(v_obj, w_obj, op);
534
548
    } else {
535
 
        Py_INCREF(Py_NotImplemented);
536
 
        return Py_NotImplemented;
 
549
        return PyObject_RichCompare(v_obj, w_obj, op);
537
550
    }
538
551
}
539
552
 
561
574
 
562
575
 
563
576
static PyObject *
 
577
StaticTuple_add(PyObject *v, PyObject *w)
 
578
{
 
579
    Py_ssize_t i, len_v, len_w;
 
580
    PyObject *item;
 
581
    StaticTuple *result;
 
582
     /* StaticTuples and plain tuples may be added (concatenated) to
 
583
      * StaticTuples.
 
584
      */
 
585
    if (StaticTuple_CheckExact(v)) {
 
586
        len_v = ((StaticTuple*)v)->size;
 
587
    } else if (PyTuple_Check(v)) {
 
588
        len_v = PyTuple_GET_SIZE(v);
 
589
    } else {
 
590
        Py_INCREF(Py_NotImplemented);
 
591
        return Py_NotImplemented;
 
592
    }
 
593
    if (StaticTuple_CheckExact(w)) {
 
594
        len_w = ((StaticTuple*)w)->size;
 
595
    } else if (PyTuple_Check(w)) {
 
596
        len_w = PyTuple_GET_SIZE(w);
 
597
    } else {
 
598
        Py_INCREF(Py_NotImplemented);
 
599
        return Py_NotImplemented;
 
600
    }
 
601
    result = StaticTuple_New(len_v + len_w);
 
602
    if (result == NULL)
 
603
        return NULL;
 
604
    for (i = 0; i < len_v; ++i) {
 
605
        // This returns a new reference, which we then 'steal' with 
 
606
        // StaticTuple_SET_ITEM
 
607
        item = PySequence_GetItem(v, i);
 
608
        if (item == NULL) {
 
609
            Py_DECREF(result);
 
610
            return NULL;
 
611
        }
 
612
        StaticTuple_SET_ITEM(result, i, item);
 
613
    }
 
614
    for (i = 0; i < len_w; ++i) {
 
615
        item = PySequence_GetItem(w, i);
 
616
        if (item == NULL) {
 
617
            Py_DECREF(result);
 
618
            return NULL;
 
619
        }
 
620
        StaticTuple_SET_ITEM(result, i+len_v, item);
 
621
    }
 
622
    if (!StaticTuple_check_items(result)) {
 
623
        Py_DECREF(result);
 
624
        return NULL;
 
625
    }
 
626
    return (PyObject *)result;
 
627
}
 
628
 
 
629
static PyObject *
564
630
StaticTuple_item(StaticTuple *self, Py_ssize_t offset)
565
631
{
566
632
    PyObject *obj;
625
691
    {NULL, NULL} /* sentinel */
626
692
};
627
693
 
 
694
 
 
695
static PyNumberMethods StaticTuple_as_number = {
 
696
    (binaryfunc) StaticTuple_add,   /* nb_add */
 
697
    0,                              /* nb_subtract */
 
698
    0,                              /* nb_multiply */
 
699
    0,                              /* nb_divide */
 
700
    0,                              /* nb_remainder */
 
701
    0,                              /* nb_divmod */
 
702
    0,                              /* nb_power */
 
703
    0,                              /* nb_negative */
 
704
    0,                              /* nb_positive */
 
705
    0,                              /* nb_absolute */
 
706
    0,                              /* nb_nonzero */
 
707
    0,                              /* nb_invert */
 
708
    0,                              /* nb_lshift */
 
709
    0,                              /* nb_rshift */
 
710
    0,                              /* nb_and */
 
711
    0,                              /* nb_xor */
 
712
    0,                              /* nb_or */
 
713
    0,                              /* nb_coerce */
 
714
};
 
715
    
 
716
 
628
717
static PySequenceMethods StaticTuple_as_sequence = {
629
718
    (lenfunc)StaticTuple_length,            /* sq_length */
630
719
    0,                              /* sq_concat */
655
744
    0,                                           /* tp_setattr */
656
745
    0,                                           /* tp_compare */
657
746
    (reprfunc)StaticTuple_repr,                  /* tp_repr */
658
 
    0,                                           /* tp_as_number */
 
747
    &StaticTuple_as_number,                      /* tp_as_number */
659
748
    &StaticTuple_as_sequence,                    /* tp_as_sequence */
660
749
    0,                                           /* tp_as_mapping */
661
750
    (hashfunc)StaticTuple_hash,                  /* tp_hash */
664
753
    0,                                           /* tp_getattro */
665
754
    0,                                           /* tp_setattro */
666
755
    0,                                           /* tp_as_buffer */
667
 
    Py_TPFLAGS_DEFAULT,                          /* tp_flags*/
 
756
    /* Py_TPFLAGS_CHECKTYPES tells the number operations that they shouldn't
 
757
     * try to 'coerce' but instead stuff like 'add' will check it arguments.
 
758
     */
 
759
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES,  /* tp_flags*/
668
760
    StaticTuple_doc,                             /* tp_doc */
669
761
    /* gc.get_referents checks the IS_GC flag before it calls tp_traverse
670
762
     * And we don't include this object in the garbage collector because we
768
860
     */
769
861
    set_module = PyImport_ImportModule("bzrlib._simple_set_pyx");
770
862
    if (set_module == NULL) {
771
 
        // fprintf(stderr, "Failed to import bzrlib._simple_set_pyx\n");
772
863
        goto end;
773
864
    }
774
865
    /* Add the _simple_set_pyx into sys.modules at the appropriate location. */
775
866
    sys_module = PyImport_ImportModule("sys");
776
867
    if (sys_module == NULL) {
777
 
        // fprintf(stderr, "Failed to import sys\n");
778
868
        goto end;
779
869
    }
780
870
    modules = PyObject_GetAttrString(sys_module, "modules");
781
871
    if (modules == NULL || !PyDict_Check(modules)) {
782
 
        // fprintf(stderr, "Failed to find sys.modules\n");
783
872
        goto end;
784
873
    }
785
874
    PyDict_SetItemString(modules, "_simple_set_pyx", set_module);
818
907
    setup_empty_tuple(m);
819
908
    setup_c_api(m);
820
909
}
 
910
 
 
911
// vim: tabstop=4 sw=4 expandtab