/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/_static_tuple_c.c

  • Committer: Jelmer Vernooij
  • Date: 2017-06-08 23:30:31 UTC
  • mto: This revision was merged to the branch mainline in revision 6690.
  • Revision ID: jelmer@jelmer.uk-20170608233031-3qavls2o7a1pqllj
Update imports.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include "_static_tuple_c.h"
27
27
#include "_export_c_api.h"
28
28
 
 
29
/* Pyrex 0.9.6.4 exports _simple_set_pyx_api as
 
30
 * import__simple_set_pyx(), while Pyrex 0.9.8.5 and Cython 0.11.3 export them
 
31
 * as import_breezy___simple_set_pyx(). As such, we just #define one to be
 
32
 * equivalent to the other in our internal code.
 
33
 */
 
34
#define import__simple_set_pyx import_breezy___simple_set_pyx
29
35
#include "_simple_set_pyx_api.h"
30
36
 
31
37
#if defined(__GNUC__)
236
242
                " should not have a NULL entry.");
237
243
            return 0;
238
244
        }
239
 
        if (PyBytes_CheckExact(obj)
 
245
        if (PyString_CheckExact(obj)
240
246
            || StaticTuple_CheckExact(obj)
241
247
            || obj == Py_None
242
248
            || PyBool_Check(obj)
243
 
#if PY_MAJOR_VERSION >= 3
244
 
#else
245
249
            || PyInt_CheckExact(obj)
246
 
#endif
247
250
            || PyLong_CheckExact(obj)
248
251
            || PyFloat_CheckExact(obj)
249
252
            || PyUnicode_CheckExact(obj)
311
314
    if (tuple_repr == NULL) {
312
315
        return NULL;
313
316
    }
314
 
#if PY_MAJOR_VERSION >= 3
315
 
    result = PyUnicode_FromFormat("StaticTuple%U", tuple_repr);
316
 
#else
317
317
    result = PyString_FromFormat("StaticTuple%s",
318
318
                                 PyString_AsString(tuple_repr));
319
 
#endif
320
319
    return result;
321
320
}
322
321
 
323
 
/* adapted from tuplehash(), is the specific hash value considered
324
 
 * 'stable'?
325
 
 */
326
 
 
327
 
#if PY_MAJOR_VERSION > 3 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 8)
328
 
/* Hash for tuples. This is a slightly simplified version of the xxHash
329
 
   non-cryptographic hash:
330
 
   - we do not use any parallellism, there is only 1 accumulator.
331
 
   - we drop the final mixing since this is just a permutation of the
332
 
     output space: it does not help against collisions.
333
 
   - at the end, we mangle the length with a single constant.
334
 
   For the xxHash specification, see
335
 
   https://github.com/Cyan4973/xxHash/blob/master/doc/xxhash_spec.md
336
 
 
337
 
   Below are the official constants from the xxHash specification. Optimizing
338
 
   compilers should emit a single "rotate" instruction for the
339
 
   _PyHASH_XXROTATE() expansion. If that doesn't happen for some important
340
 
   platform, the macro could be changed to expand to a platform-specific rotate
341
 
   spelling instead.
342
 
*/
343
 
#if SIZEOF_PY_UHASH_T > 4
344
 
#define _PyHASH_XXPRIME_1 ((Py_uhash_t)11400714785074694791ULL)
345
 
#define _PyHASH_XXPRIME_2 ((Py_uhash_t)14029467366897019727ULL)
346
 
#define _PyHASH_XXPRIME_5 ((Py_uhash_t)2870177450012600261ULL)
347
 
#define _PyHASH_XXROTATE(x) ((x << 31) | (x >> 33))  /* Rotate left 31 bits */
348
 
#else
349
 
#define _PyHASH_XXPRIME_1 ((Py_uhash_t)2654435761UL)
350
 
#define _PyHASH_XXPRIME_2 ((Py_uhash_t)2246822519UL)
351
 
#define _PyHASH_XXPRIME_5 ((Py_uhash_t)374761393UL)
352
 
#define _PyHASH_XXROTATE(x) ((x << 13) | (x >> 19))  /* Rotate left 13 bits */
353
 
#endif
354
 
 
355
 
/* Tests have shown that it's not worth to cache the hash value, see
356
 
   https://bugs.python.org/issue9685 */
357
 
static Py_hash_t
358
 
StaticTuple_hash(StaticTuple *self)
359
 
{
360
 
    Py_ssize_t i, len = self->size;
361
 
    PyObject **item = self->items;
362
 
 
363
 
#if STATIC_TUPLE_HAS_HASH
364
 
    if (self->hash != -1) {
365
 
        return self->hash;
366
 
    }
367
 
#endif
368
 
 
369
 
    Py_uhash_t acc = _PyHASH_XXPRIME_5;
370
 
    for (i = 0; i < len; i++) {
371
 
        Py_uhash_t lane = PyObject_Hash(item[i]);
372
 
        if (lane == (Py_uhash_t)-1) {
373
 
            return -1;
374
 
        }
375
 
        acc += lane * _PyHASH_XXPRIME_2;
376
 
        acc = _PyHASH_XXROTATE(acc);
377
 
        acc *= _PyHASH_XXPRIME_1;
378
 
    }
379
 
 
380
 
    /* Add input length, mangled to keep the historical value of hash(()). */
381
 
    acc += len ^ (_PyHASH_XXPRIME_5 ^ 3527539UL);
382
 
 
383
 
    if (acc == (Py_uhash_t)-1) {
384
 
        acc = 1546275796;
385
 
    }
386
 
 
387
 
#if STATIC_TUPLE_HAS_HASH
388
 
    self->hash = acc;
389
 
#endif
390
 
    return acc;
391
 
}
392
 
 
393
 
 
394
 
#else
395
322
static long
396
323
StaticTuple_hash(StaticTuple *self)
397
324
{
429
356
#endif
430
357
    return x;
431
358
}
432
 
#endif
433
359
 
434
360
static PyObject *
435
361
StaticTuple_richcompare_to_tuple(StaticTuple *v, PyObject *wt, int op)
436
362
{
437
363
    PyObject *vt;
438
364
    PyObject *result = NULL;
439
 
 
 
365
    
440
366
    vt = StaticTuple_as_tuple((StaticTuple *)v);
441
367
    if (vt == NULL) {
442
368
        goto done;
501
427
    } else if (w == Py_None) {
502
428
        // None is always less than the object
503
429
        switch (op) {
504
 
        case Py_NE:
505
 
#if PY_MAJOR_VERSION >= 3
506
 
#else
507
 
        case Py_GT:case Py_GE:
508
 
#endif
 
430
        case Py_NE:case Py_GT:case Py_GE:
509
431
            Py_INCREF(Py_True);
510
432
            return Py_True;
511
 
        case Py_EQ:
512
 
#if PY_MAJOR_VERSION >= 3
513
 
#else
514
 
        case Py_LT:case Py_LE:
515
 
#endif
 
433
        case Py_EQ:case Py_LT:case Py_LE:
516
434
            Py_INCREF(Py_False);
517
435
            return Py_False;
518
 
        default: // Should only happen on Python 3
519
 
            return Py_NotImplemented;
 
436
    default: // Should never happen
 
437
        return Py_NotImplemented;
520
438
        }
521
439
    } else {
522
440
        /* We don't special case this comparison, we just let python handle
560
478
    vlen = v_st->size;
561
479
    wlen = w_st->size;
562
480
    min_len = (vlen < wlen) ? vlen : wlen;
563
 
    string_richcompare = PyBytes_Type.tp_richcompare;
 
481
    string_richcompare = PyString_Type.tp_richcompare;
564
482
    for (i = 0; i < min_len; i++) {
565
483
        PyObject *result = NULL;
566
484
        v_obj = StaticTuple_GET_ITEM(v_st, i);
569
487
            /* Shortcut case, these must be identical */
570
488
            continue;
571
489
        }
572
 
        if (PyBytes_CheckExact(v_obj) && PyBytes_CheckExact(w_obj)) {
 
490
        if (PyString_CheckExact(v_obj) && PyString_CheckExact(w_obj)) {
573
491
            result = string_richcompare(v_obj, w_obj, Py_EQ);
574
492
        } else if (StaticTuple_CheckExact(v_obj) &&
575
493
                   StaticTuple_CheckExact(w_obj))
629
547
        return Py_True;
630
548
    }
631
549
    /* It is some other comparison, go ahead and do the real check. */
632
 
    if (PyBytes_CheckExact(v_obj) && PyBytes_CheckExact(w_obj))
 
550
    if (PyString_CheckExact(v_obj) && PyString_CheckExact(w_obj))
633
551
    {
634
552
        return string_richcompare(v_obj, w_obj, op);
635
553
    } else if (StaticTuple_CheckExact(v_obj) &&
761
679
    return obj;
762
680
}
763
681
 
764
 
#if PY_MAJOR_VERSION >= 3
765
 
#else
766
682
static PyObject *
767
683
StaticTuple_slice(StaticTuple *self, Py_ssize_t ilow, Py_ssize_t ihigh)
768
684
{
776
692
    Py_DECREF(as_tuple);
777
693
    return result;
778
694
}
779
 
#endif
780
 
 
781
 
static PyObject *
782
 
StaticTuple_subscript(StaticTuple *self, PyObject *key)
783
 
{
784
 
    PyObject *as_tuple, *result;
785
 
 
786
 
    as_tuple = StaticTuple_as_tuple(self);
787
 
    if (as_tuple == NULL) {
788
 
        return NULL;
789
 
    }
790
 
    result = PyTuple_Type.tp_as_mapping->mp_subscript(as_tuple, key);
791
 
    Py_DECREF(as_tuple);
792
 
    return result;
793
 
}
794
695
 
795
696
static int
796
697
StaticTuple_traverse(StaticTuple *self, visitproc visit, void *arg)
806
707
static PyObject *
807
708
StaticTuple_sizeof(StaticTuple *self)
808
709
{
809
 
    Py_ssize_t res;
 
710
        Py_ssize_t res;
810
711
 
811
 
    res = _PyObject_SIZE(&StaticTuple_Type) + (int)self->size * sizeof(void*);
812
 
    return PyInt_FromSsize_t(res);
 
712
        res = _PyObject_SIZE(&StaticTuple_Type) + (int)self->size * sizeof(void*);
 
713
        return PyInt_FromSsize_t(res);
813
714
}
814
715
 
815
716
 
858
759
    0,                              /* nb_or */
859
760
    0,                              /* nb_coerce */
860
761
};
861
 
 
 
762
    
862
763
 
863
764
static PySequenceMethods StaticTuple_as_sequence = {
864
765
    (lenfunc)StaticTuple_length,            /* sq_length */
865
766
    0,                              /* sq_concat */
866
767
    0,                              /* sq_repeat */
867
768
    (ssizeargfunc)StaticTuple_item,         /* sq_item */
868
 
#if PY_MAJOR_VERSION >= 3
869
 
#else
870
769
    (ssizessizeargfunc)StaticTuple_slice,   /* sq_slice */
871
 
#endif
872
770
    0,                              /* sq_ass_item */
873
771
    0,                              /* sq_ass_slice */
874
772
    0,                              /* sq_contains */
875
 
#if PY_MAJOR_VERSION >= 3
876
 
    0,                              /* sq_inplace_concat */
877
 
    0,                              /* sq_inplace_repeat */
878
 
#endif
879
 
};
880
 
 
881
 
 
882
 
static PyMappingMethods StaticTuple_as_mapping = {
883
 
    (lenfunc)StaticTuple_length,            /* mp_length */
884
 
    (binaryfunc)StaticTuple_subscript,      /* mp_subscript */
885
 
    0,                                      /* mp_ass_subscript */
886
 
};
 
773
};
 
774
 
 
775
/* TODO: Implement StaticTuple_as_mapping.
 
776
 *       The only thing we really want to support from there is mp_subscript,
 
777
 *       so that we could support extended slicing (foo[::2]). Not worth it
 
778
 *       yet, though.
 
779
 */
887
780
 
888
781
 
889
782
PyTypeObject StaticTuple_Type = {
890
 
    PyVarObject_HEAD_INIT(NULL, 0)
 
783
    PyObject_HEAD_INIT(NULL)
 
784
    0,                                           /* ob_size */
891
785
    "breezy._static_tuple_c.StaticTuple",        /* tp_name */
892
786
    sizeof(StaticTuple),                         /* tp_basicsize */
893
787
    sizeof(PyObject *),                          /* tp_itemsize */
899
793
    (reprfunc)StaticTuple_repr,                  /* tp_repr */
900
794
    &StaticTuple_as_number,                      /* tp_as_number */
901
795
    &StaticTuple_as_sequence,                    /* tp_as_sequence */
902
 
    &StaticTuple_as_mapping,                     /* tp_as_mapping */
 
796
    0,                                           /* tp_as_mapping */
903
797
    (hashfunc)StaticTuple_hash,                  /* tp_hash */
904
798
    0,                                           /* tp_call */
905
799
    0,                                           /* tp_str */
993
887
}
994
888
 
995
889
 
996
 
PYMOD_INIT_FUNC(_static_tuple_c)
 
890
static int
 
891
_workaround_pyrex_096(void)
 
892
{
 
893
    /* Work around an incompatibility in how pyrex 0.9.6 exports a module,
 
894
     * versus how pyrex 0.9.8 and cython 0.11 export it.
 
895
     * Namely 0.9.6 exports import__simple_set_pyx and tries to
 
896
     * "import _simple_set_pyx" but it is available only as
 
897
     * "import breezy._simple_set_pyx"
 
898
     * It is a shame to hack up sys.modules, but that is what we've got to do.
 
899
     */
 
900
    PyObject *sys_module = NULL, *modules = NULL, *set_module = NULL;
 
901
    int retval = -1;
 
902
 
 
903
    /* Clear out the current ImportError exception, and try again. */
 
904
    PyErr_Clear();
 
905
    /* Note that this only seems to work if somewhere else imports
 
906
     * breezy._simple_set_pyx before importing breezy._static_tuple_c
 
907
     */
 
908
    set_module = PyImport_ImportModule("breezy._simple_set_pyx");
 
909
    if (set_module == NULL) {
 
910
        goto end;
 
911
    }
 
912
    /* Add the _simple_set_pyx into sys.modules at the appropriate location. */
 
913
    sys_module = PyImport_ImportModule("sys");
 
914
    if (sys_module == NULL) {
 
915
        goto end;
 
916
    }
 
917
    modules = PyObject_GetAttrString(sys_module, "modules");
 
918
    if (modules == NULL || !PyDict_Check(modules)) {
 
919
        goto end;
 
920
    }
 
921
    PyDict_SetItemString(modules, "_simple_set_pyx", set_module);
 
922
    /* Now that we have hacked it in, try the import again. */
 
923
    retval = import_breezy___simple_set_pyx();
 
924
end:
 
925
    Py_XDECREF(set_module);
 
926
    Py_XDECREF(sys_module);
 
927
    Py_XDECREF(modules);
 
928
    return retval;
 
929
}
 
930
 
 
931
 
 
932
PyMODINIT_FUNC
 
933
init_static_tuple_c(void)
997
934
{
998
935
    PyObject* m;
999
936
 
1000
937
    StaticTuple_Type.tp_getattro = PyObject_GenericGetAttr;
1001
 
    if (PyType_Ready(&StaticTuple_Type) < 0) {
1002
 
        return PYMOD_ERROR;
1003
 
    }
 
938
    if (PyType_Ready(&StaticTuple_Type) < 0)
 
939
        return;
1004
940
 
1005
 
    PYMOD_CREATE(m, "_static_tuple_c",
1006
 
                 "C implementation of a StaticTuple structure",
1007
 
                 static_tuple_c_methods);
1008
 
    if (m == NULL) {
1009
 
      return PYMOD_ERROR;
1010
 
    }
 
941
    m = Py_InitModule3("_static_tuple_c", static_tuple_c_methods,
 
942
                       "C implementation of a StaticTuple structure");
 
943
    if (m == NULL)
 
944
      return;
1011
945
 
1012
946
    Py_INCREF(&StaticTuple_Type);
1013
947
    PyModule_AddObject(m, "StaticTuple", (PyObject *)&StaticTuple_Type);
1014
 
    if (import_breezy___simple_set_pyx() == -1) {
1015
 
        return PYMOD_ERROR;
 
948
    if (import_breezy___simple_set_pyx() == -1
 
949
        && _workaround_pyrex_096() == -1)
 
950
    {
 
951
        return;
1016
952
    }
1017
953
    setup_interned_tuples(m);
1018
954
    setup_empty_tuple(m);
1019
955
    setup_c_api(m);
1020
 
 
1021
 
    return PYMOD_SUCCESS(m);
1022
956
}
1023
957
 
1024
958
// vim: tabstop=4 sw=4 expandtab