home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyth_os2.zip / python-1.0.2 / Objects / tupleobject.c < prev    next >
C/C++ Source or Header  |  1994-04-22  |  10KB  |  457 lines

  1. /***********************************************************
  2. Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
  3. Amsterdam, The Netherlands.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Stichting Mathematisch
  12. Centrum or CWI not be used in advertising or publicity pertaining to
  13. distribution of the software without specific, written prior permission.
  14.  
  15. STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
  16. THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
  18. FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  20. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  21. OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25. /* Tuple object implementation */
  26.  
  27. #include "allobjects.h"
  28.  
  29. #ifndef MAXSAVESIZE
  30. #define MAXSAVESIZE    20
  31. #endif
  32.  
  33. #if MAXSAVESIZE > 0
  34. /* Entries 1 upto MAXSAVESIZE are free lists, entry 0 is the empty
  35.    tuple () of which at most one instance will be allocated.
  36. */
  37. static tupleobject *free_tuples[MAXSAVESIZE];
  38. #endif
  39. #ifdef COUNT_ALLOCS
  40. int fast_tuple_allocs;
  41. int tuple_zero_allocs;
  42. #endif
  43.  
  44. object *
  45. newtupleobject(size)
  46.     register int size;
  47. {
  48.     register int i;
  49.     register tupleobject *op;
  50.     if (size < 0) {
  51.         err_badcall();
  52.         return NULL;
  53.     }
  54. #if MAXSAVESIZE > 0
  55.     if (size == 0 && free_tuples[0]) {
  56.         op = free_tuples[0];
  57.         INCREF(op);
  58. #ifdef COUNT_ALLOCS
  59.         tuple_zero_allocs++;
  60. #endif
  61.         return (object *) op;
  62.     }
  63.     if (0 < size && size < MAXSAVESIZE && (op = free_tuples[size]) != NULL) {
  64.         free_tuples[size] = (tupleobject *) op->ob_item[0];
  65. #ifdef COUNT_ALLOCS
  66.         fast_tuple_allocs++;
  67. #endif
  68.     } else
  69. #endif
  70.     {
  71.         op = (tupleobject *)
  72.             malloc(sizeof(tupleobject) + size * sizeof(object *));
  73.         if (op == NULL)
  74.             return err_nomem();
  75.     }
  76.     op->ob_type = &Tupletype;
  77.     op->ob_size = size;
  78.     for (i = 0; i < size; i++)
  79.         op->ob_item[i] = NULL;
  80.     NEWREF(op);
  81. #if MAXSAVESIZE > 0
  82.     if (size == 0) {
  83.         free_tuples[0] = op;
  84.         INCREF(op);    /* extra INCREF so that this is never freed */
  85.     }
  86. #endif
  87.     return (object *) op;
  88. }
  89.  
  90. int
  91. gettuplesize(op)
  92.     register object *op;
  93. {
  94.     if (!is_tupleobject(op)) {
  95.         err_badcall();
  96.         return -1;
  97.     }
  98.     else
  99.         return ((tupleobject *)op)->ob_size;
  100. }
  101.  
  102. object *
  103. gettupleitem(op, i)
  104.     register object *op;
  105.     register int i;
  106. {
  107.     if (!is_tupleobject(op)) {
  108.         err_badcall();
  109.         return NULL;
  110.     }
  111.     if (i < 0 || i >= ((tupleobject *)op) -> ob_size) {
  112.         err_setstr(IndexError, "tuple index out of range");
  113.         return NULL;
  114.     }
  115.     return ((tupleobject *)op) -> ob_item[i];
  116. }
  117.  
  118. int
  119. settupleitem(op, i, newitem)
  120.     register object *op;
  121.     register int i;
  122.     register object *newitem;
  123. {
  124.     register object *olditem;
  125.     if (!is_tupleobject(op)) {
  126.         XDECREF(newitem);
  127.         err_badcall();
  128.         return -1;
  129.     }
  130.     if (i < 0 || i >= ((tupleobject *)op) -> ob_size) {
  131.         XDECREF(newitem);
  132.         err_setstr(IndexError, "tuple assignment index out of range");
  133.         return -1;
  134.     }
  135.     olditem = ((tupleobject *)op) -> ob_item[i];
  136.     ((tupleobject *)op) -> ob_item[i] = newitem;
  137.     XDECREF(olditem);
  138.     return 0;
  139. }
  140.  
  141. /* Methods */
  142.  
  143. static void
  144. tupledealloc(op)
  145.     register tupleobject *op;
  146. {
  147.     register int i;
  148.     for (i = 0; i < op->ob_size; i++)
  149.         XDECREF(op->ob_item[i]);
  150. #if MAXSAVESIZE > 0
  151.     if (0 < op->ob_size && op->ob_size < MAXSAVESIZE) {
  152.         op->ob_item[0] = (object *) free_tuples[op->ob_size];
  153.         free_tuples[op->ob_size] = op;
  154.     } else
  155. #endif
  156.         free((ANY *)op);
  157. }
  158.  
  159. static int
  160. tupleprint(op, fp, flags)
  161.     tupleobject *op;
  162.     FILE *fp;
  163.     int flags;
  164. {
  165.     int i;
  166.     fprintf(fp, "(");
  167.     for (i = 0; i < op->ob_size; i++) {
  168.         if (i > 0)
  169.             fprintf(fp, ", ");
  170.         if (printobject(op->ob_item[i], fp, 0) != 0)
  171.             return -1;
  172.     }
  173.     if (op->ob_size == 1)
  174.         fprintf(fp, ",");
  175.     fprintf(fp, ")");
  176.     return 0;
  177. }
  178.  
  179. static object *
  180. tuplerepr(v)
  181.     tupleobject *v;
  182. {
  183.     object *s, *comma;
  184.     int i;
  185.     s = newstringobject("(");
  186.     comma = newstringobject(", ");
  187.     for (i = 0; i < v->ob_size && s != NULL; i++) {
  188.         if (i > 0)
  189.             joinstring(&s, comma);
  190.         joinstring_decref(&s, reprobject(v->ob_item[i]));
  191.     }
  192.     DECREF(comma);
  193.     if (v->ob_size == 1)
  194.         joinstring_decref(&s, newstringobject(","));
  195.     joinstring_decref(&s, newstringobject(")"));
  196.     return s;
  197. }
  198.  
  199. static int
  200. tuplecompare(v, w)
  201.     register tupleobject *v, *w;
  202. {
  203.     register int len =
  204.         (v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
  205.     register int i;
  206.     for (i = 0; i < len; i++) {
  207.         int cmp = cmpobject(v->ob_item[i], w->ob_item[i]);
  208.         if (cmp != 0)
  209.             return cmp;
  210.     }
  211.     return v->ob_size - w->ob_size;
  212. }
  213.  
  214. static long
  215. tuplehash(v)
  216.     tupleobject *v;
  217. {
  218.     register long x, y;
  219.     register int len = v->ob_size;
  220.     register object **p;
  221.     x = 0x345678L;
  222.     p = v->ob_item;
  223.     while (--len >= 0) {
  224.         y = hashobject(*p++);
  225.         if (y == -1)
  226.             return -1;
  227.         x = (x + x + x) ^ y;
  228.     }
  229.     x ^= v->ob_size;
  230.     if (x == -1)
  231.         x = -2;
  232.     return x;
  233. }
  234.  
  235. static int
  236. tuplelength(a)
  237.     tupleobject *a;
  238. {
  239.     return a->ob_size;
  240. }
  241.  
  242. static object *
  243. tupleitem(a, i)
  244.     register tupleobject *a;
  245.     register int i;
  246. {
  247.     if (i < 0 || i >= a->ob_size) {
  248.         err_setstr(IndexError, "tuple index out of range");
  249.         return NULL;
  250.     }
  251.     INCREF(a->ob_item[i]);
  252.     return a->ob_item[i];
  253. }
  254.  
  255. static object *
  256. tupleslice(a, ilow, ihigh)
  257.     register tupleobject *a;
  258.     register int ilow, ihigh;
  259. {
  260.     register tupleobject *np;
  261.     register int i;
  262.     if (ilow < 0)
  263.         ilow = 0;
  264.     if (ihigh > a->ob_size)
  265.         ihigh = a->ob_size;
  266.     if (ihigh < ilow)
  267.         ihigh = ilow;
  268.     if (ilow == 0 && ihigh == a->ob_size) {
  269.         /* XXX can only do this if tuples are immutable! */
  270.         INCREF(a);
  271.         return (object *)a;
  272.     }
  273.     np = (tupleobject *)newtupleobject(ihigh - ilow);
  274.     if (np == NULL)
  275.         return NULL;
  276.     for (i = ilow; i < ihigh; i++) {
  277.         object *v = a->ob_item[i];
  278.         INCREF(v);
  279.         np->ob_item[i - ilow] = v;
  280.     }
  281.     return (object *)np;
  282. }
  283.  
  284. object *
  285. gettupleslice(op, i, j)
  286.     object *op;
  287.     int i, j;
  288. {
  289.     if (op == NULL || !is_tupleobject(op)) {
  290.         err_badcall();
  291.         return NULL;
  292.     }
  293.     return tupleslice((tupleobject *)op, i, j);
  294. }
  295.  
  296. static object *
  297. tupleconcat(a, bb)
  298.     register tupleobject *a;
  299.     register object *bb;
  300. {
  301.     register int size;
  302.     register int i;
  303.     tupleobject *np;
  304.     if (!is_tupleobject(bb)) {
  305.         err_badarg();
  306.         return NULL;
  307.     }
  308. #define b ((tupleobject *)bb)
  309.     size = a->ob_size + b->ob_size;
  310.     np = (tupleobject *) newtupleobject(size);
  311.     if (np == NULL) {
  312.         return NULL;
  313.     }
  314.     for (i = 0; i < a->ob_size; i++) {
  315.         object *v = a->ob_item[i];
  316.         INCREF(v);
  317.         np->ob_item[i] = v;
  318.     }
  319.     for (i = 0; i < b->ob_size; i++) {
  320.         object *v = b->ob_item[i];
  321.         INCREF(v);
  322.         np->ob_item[i + a->ob_size] = v;
  323.     }
  324.     return (object *)np;
  325. #undef b
  326. }
  327.  
  328. static object *
  329. tuplerepeat(a, n)
  330.     tupleobject *a;
  331.     int n;
  332. {
  333.     int i, j;
  334.     int size;
  335.     tupleobject *np;
  336.     object **p;
  337.     if (n < 0)
  338.         n = 0;
  339.     if (a->ob_size*n == a->ob_size) {
  340.         /* Since tuples are immutable, we can return a shared
  341.            copy in this case */
  342.         INCREF(a);
  343.         return (object *)a;
  344.     }
  345.     size = a->ob_size * n;
  346.     np = (tupleobject *) newtupleobject(size);
  347.     if (np == NULL)
  348.         return NULL;
  349.     p = np->ob_item;
  350.     for (i = 0; i < n; i++) {
  351.         for (j = 0; j < a->ob_size; j++) {
  352.             *p = a->ob_item[j];
  353.             INCREF(*p);
  354.             p++;
  355.         }
  356.     }
  357.     return (object *) np;
  358. }
  359.  
  360. static sequence_methods tuple_as_sequence = {
  361.     (inquiry)tuplelength, /*sq_length*/
  362.     (binaryfunc)tupleconcat, /*sq_concat*/
  363.     (intargfunc)tuplerepeat, /*sq_repeat*/
  364.     (intargfunc)tupleitem, /*sq_item*/
  365.     (intintargfunc)tupleslice, /*sq_slice*/
  366.     0,        /*sq_ass_item*/
  367.     0,        /*sq_ass_slice*/
  368. };
  369.  
  370. typeobject Tupletype = {
  371.     OB_HEAD_INIT(&Typetype)
  372.     0,
  373.     "tuple",
  374.     sizeof(tupleobject) - sizeof(object *),
  375.     sizeof(object *),
  376.     (destructor)tupledealloc, /*tp_dealloc*/
  377.     (printfunc)tupleprint, /*tp_print*/
  378.     0,        /*tp_getattr*/
  379.     0,        /*tp_setattr*/
  380.     (cmpfunc)tuplecompare, /*tp_compare*/
  381.     (reprfunc)tuplerepr, /*tp_repr*/
  382.     0,        /*tp_as_number*/
  383.     &tuple_as_sequence,    /*tp_as_sequence*/
  384.     0,        /*tp_as_mapping*/
  385.     (hashfunc)tuplehash, /*tp_hash*/
  386. };
  387.  
  388. /* The following function breaks the notion that tuples are immutable:
  389.    it changes the size of a tuple.  We get away with this only if there
  390.    is only one module referencing the object.  You can also think of it
  391.    as creating a new tuple object and destroying the old one, only
  392.    more efficiently.  In any case, don't use this if the tuple may
  393.    already be known to some other part of the code...
  394.    If last_is_sticky is set, the tuple will grow or shrink at the
  395.    front, otherwise it will grow or shrink at the end. */
  396.  
  397. int
  398. resizetuple(pv, newsize, last_is_sticky)
  399.     object **pv;
  400.     int newsize;
  401.     int last_is_sticky;
  402. {
  403.     register tupleobject *v;
  404.     register tupleobject *sv;
  405.     int i;
  406.     int sizediff;
  407.  
  408.     v = (tupleobject *) *pv;
  409.     sizediff = newsize - v->ob_size;
  410.     if (!is_tupleobject(v) || v->ob_refcnt != 1) {
  411.         *pv = 0;
  412.         DECREF(v);
  413.         err_badcall();
  414.         return -1;
  415.     }
  416.     if (sizediff == 0)
  417.         return 0;
  418.     /* XXX UNREF/NEWREF interface should be more symmetrical */
  419. #ifdef REF_DEBUG
  420.     --ref_total;
  421. #endif
  422.     UNREF(v);
  423.     if (last_is_sticky && sizediff < 0) {
  424.         /* shrinking: move entries to the front and zero moved entries */
  425.         for (i = 0; i < newsize; i++) {
  426.             XDECREF(v->ob_item[i]);
  427.             v->ob_item[i] = v->ob_item[i - sizediff];
  428.             v->ob_item[i - sizediff] = NULL;
  429.         }
  430.     }
  431.     for (i = newsize; i < v->ob_size; i++) {
  432.         XDECREF(v->ob_item[i]);
  433.         v->ob_item[i] = NULL;
  434.     }
  435.     sv = (tupleobject *)
  436.         realloc((char *)v,
  437.             sizeof(tupleobject) + newsize * sizeof(object *));
  438.     *pv = (object *) sv;
  439.     if (sv == NULL) {
  440.         DEL(v);
  441.         err_nomem();
  442.         return -1;
  443.     }
  444.     NEWREF(sv);
  445.     for (i = sv->ob_size; i < newsize; i++)
  446.         sv->ob_item[i] = NULL;
  447.     if (last_is_sticky && sizediff > 0) {
  448.         /* growing: move entries to the end and zero moved entries */
  449.         for (i = newsize - 1; i >= sizediff; i--) {
  450.             sv->ob_item[i] = sv->ob_item[i - sizediff];
  451.             sv->ob_item[i - sizediff] = NULL;
  452.         }
  453.     }
  454.     sv->ob_size = newsize;
  455.     return 0;
  456. }
  457.