blob: 960d78af05c5012aca92a9fa7d6b31581ed8df73 [file] [log] [blame]
/* Tuple object implementation */
#include <stdio.h>
#include "PROTO.h"
#include "object.h"
#include "stringobject.h"
#include "tupleobject.h"
#include "intobject.h"
#include "objimpl.h"
#include "errors.h"
typedef struct {
OB_VARHEAD
object *ob_item[1];
} tupleobject;
object *
newtupleobject(size)
register int size;
{
register int i;
register tupleobject *op;
if (size < 0) {
err_badcall();
return NULL;
}
op = (tupleobject *)
malloc(sizeof(tupleobject) + size * sizeof(object *));
if (op == NULL)
return err_nomem();
NEWREF(op);
op->ob_type = &Tupletype;
op->ob_size = size;
for (i = 0; i < size; i++)
op->ob_item[i] = NULL;
return (object *) op;
}
int
gettuplesize(op)
register object *op;
{
if (!is_tupleobject(op)) {
err_badcall();
return -1;
}
else
return ((tupleobject *)op)->ob_size;
}
object *
gettupleitem(op, i)
register object *op;
register int i;
{
if (!is_tupleobject(op)) {
err_badcall();
return NULL;
}
if (i < 0 || i >= ((tupleobject *)op) -> ob_size) {
err_setstr(IndexError, "tuple index out of range");
return NULL;
}
return ((tupleobject *)op) -> ob_item[i];
}
int
settupleitem(op, i, newitem)
register object *op;
register int i;
register object *newitem;
{
register object *olditem;
if (!is_tupleobject(op)) {
if (newitem != NULL)
DECREF(newitem);
err_badcall();
return -1;
}
if (i < 0 || i >= ((tupleobject *)op) -> ob_size) {
if (newitem != NULL)
DECREF(newitem);
err_setstr(IndexError, "tuple assignment index out of range");
return -1;
}
olditem = ((tupleobject *)op) -> ob_item[i];
((tupleobject *)op) -> ob_item[i] = newitem;
if (olditem != NULL)
DECREF(olditem);
return 0;
}
/* Methods */
static void
tupledealloc(op)
register tupleobject *op;
{
register int i;
for (i = 0; i < op->ob_size; i++) {
if (op->ob_item[i] != NULL)
DECREF(op->ob_item[i]);
}
free((ANY *)op);
}
static void
tupleprint(op, fp, flags)
tupleobject *op;
FILE *fp;
int flags;
{
int i;
fprintf(fp, "(");
for (i = 0; i < op->ob_size && !StopPrint; i++) {
if (i > 0) {
fprintf(fp, ", ");
}
printobject(op->ob_item[i], fp, flags);
}
if (op->ob_size == 1)
fprintf(fp, ",");
fprintf(fp, ")");
}
object *
tuplerepr(v)
tupleobject *v;
{
object *s, *t, *comma;
int i;
s = newstringobject("(");
comma = newstringobject(", ");
for (i = 0; i < v->ob_size && s != NULL; i++) {
if (i > 0)
joinstring(&s, comma);
t = reprobject(v->ob_item[i]);
joinstring(&s, t);
if (t != NULL)
DECREF(t);
}
DECREF(comma);
if (v->ob_size == 1) {
t = newstringobject(",");
joinstring(&s, t);
DECREF(t);
}
t = newstringobject(")");
joinstring(&s, t);
DECREF(t);
return s;
}
static int
tuplecompare(v, w)
register tupleobject *v, *w;
{
register int len =
(v->ob_size < w->ob_size) ? v->ob_size : w->ob_size;
register int i;
for (i = 0; i < len; i++) {
int cmp = cmpobject(v->ob_item[i], w->ob_item[i]);
if (cmp != 0)
return cmp;
}
return v->ob_size - w->ob_size;
}
static int
tuplelength(a)
tupleobject *a;
{
return a->ob_size;
}
static object *
tupleitem(a, i)
register tupleobject *a;
register int i;
{
if (i < 0 || i >= a->ob_size) {
err_setstr(IndexError, "tuple index out of range");
return NULL;
}
INCREF(a->ob_item[i]);
return a->ob_item[i];
}
static object *
tupleslice(a, ilow, ihigh)
register tupleobject *a;
register int ilow, ihigh;
{
register tupleobject *np;
register int i;
if (ilow < 0)
ilow = 0;
if (ihigh > a->ob_size)
ihigh = a->ob_size;
if (ihigh < ilow)
ihigh = ilow;
if (ilow == 0 && ihigh == a->ob_size) {
/* XXX can only do this if tuples are immutable! */
INCREF(a);
return (object *)a;
}
np = (tupleobject *)newtupleobject(ihigh - ilow);
if (np == NULL)
return NULL;
for (i = ilow; i < ihigh; i++) {
object *v = a->ob_item[i];
INCREF(v);
np->ob_item[i - ilow] = v;
}
return (object *)np;
}
static object *
tupleconcat(a, bb)
register tupleobject *a;
register object *bb;
{
register int size;
register int i;
tupleobject *np;
if (!is_tupleobject(bb)) {
err_badarg();
return NULL;
}
#define b ((tupleobject *)bb)
size = a->ob_size + b->ob_size;
np = (tupleobject *) newtupleobject(size);
if (np == NULL) {
return err_nomem();
}
for (i = 0; i < a->ob_size; i++) {
object *v = a->ob_item[i];
INCREF(v);
np->ob_item[i] = v;
}
for (i = 0; i < b->ob_size; i++) {
object *v = b->ob_item[i];
INCREF(v);
np->ob_item[i + a->ob_size] = v;
}
return (object *)np;
#undef b
}
static sequence_methods tuple_as_sequence = {
tuplelength, /*sq_length*/
tupleconcat, /*sq_concat*/
0, /*sq_repeat*/
tupleitem, /*sq_item*/
tupleslice, /*sq_slice*/
0, /*sq_ass_item*/
0, /*sq_ass_slice*/
};
typeobject Tupletype = {
OB_HEAD_INIT(&Typetype)
0,
"tuple",
sizeof(tupleobject) - sizeof(object *),
sizeof(object *),
tupledealloc, /*tp_dealloc*/
tupleprint, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
tuplecompare, /*tp_compare*/
tuplerepr, /*tp_repr*/
0, /*tp_as_number*/
&tuple_as_sequence, /*tp_as_sequence*/
0, /*tp_as_mapping*/
};