
/*
 * 
 * POSTGRES Data Base Management System
 * 
 * Copyright (c) 1988 Regents of the University of California
 * 
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for educational, research, and non-profit purposes and
 * without fee is hereby granted, provided that the above copyright
 * notice appear in all copies and that both that copyright notice and
 * this permission notice appear in supporting documentation, and that
 * the name of the University of California not be used in advertising
 * or publicity pertaining to distribution of the software without
 * specific, written prior permission.  Permission to incorporate this
 * software into commercial products can be obtained from the Campus
 * Software Office, 295 Evans Hall, University of California, Berkeley,
 * Ca., 94720 provided only that the the requestor give the University
 * of California a free licence to any derived software for educational
 * and research purposes.  The University of California makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 * 
 */



/*
 * blocks.c --
 *	Handling portal buffer blocks.
 */

#include <sys/types.h>

#include "c.h"

#include "libpq.h"
#include "exception.h"

RcsId ("$Header: blocks.c,v 1.1 89/01/17 05:55:13 cimarron Exp $");

PortalEntry *portals[MAXPORTALS];

/* Allocate memory space. */
caddr_t
mem_alloc (size)
	size_t size;
{
    extern	caddr_t	malloc();
    caddr_t addr;

    if (size <= 0)
	libpq_raise(MemoryError, form("Invalid argument to malloc()."));

    addr = malloc (size);
    if (addr == NULL)
	libpq_raise(MemoryError, form("Cannot Allocate space."));

    return (addr);
}

/* Allocate a new portal buffer. */
PortalBuffer *
addPortal ()
{
    PortalBuffer *portal;
    
    portal = (PortalBuffer *) mem_alloc (sizeof (PortalBuffer));
    portal->rule_p = 0;
    portal->no_tuples = 0;
    portal->no_groups = 0;
    portal->groups = NULL;

    return (portal);
}

/* Add a new tuple group to the portal. */
GroupBuffer *
addGroup (portal)
	PortalBuffer *portal;
{
    GroupBuffer *group, *group1;

    group = (GroupBuffer *) mem_alloc (sizeof (GroupBuffer));
    /* Initialize the new group buffer. */
    group->no_tuples  = 0;
    group->no_fields = 0;
    group->types = NULL;
    group->tuples = NULL;
    group->next = NULL;
    
    if ((group1 = portal->groups) == NULL)
	portal->groups = group;
    else {
	while (group1->next != NULL) 
	    group1 = group1->next;
	group1->next = group;
    }
    
    return (group);
}

/* Allocate n type blocks. */
TypeBlock *
addTypes (n)
	int n;
{
    TypeBlock *types;

    types = (TypeBlock *) mem_alloc (n * sizeof (TypeBlock));

    return (types);
}

/* Allocate a tuple block. */
TupleBlock *
addTuples ()
{
    TupleBlock *tuples;

    tuples = (TupleBlock *) mem_alloc (sizeof (TupleBlock));
    tuples->next = NULL;

    return (tuples);
}

/* Allocate a tuple of n fields (attributes). */
char **
addTuple (n)
{
    return ( (char **) mem_alloc (n * sizeof (char *)));
}

/* Allocate n bytes for a value. */
char *
addValues (n)
	int n;
{
    return (mem_alloc (n));
}

/* Allocate a portal entry. */
PortalEntry *
addPortalEntry ()
{
    return ((PortalEntry *) mem_alloc (sizeof (PortalEntry)));
}

/* Free a portal entry in the portal table, the portal is freed separately. */
void
freePortalEntry (i)
{
    free (portals[i]);
    portals[i] = NULL;
}


/* 
 * Free up the space used by a portal 
 */

void 
freeTypes (types)
TypeBlock *types;
{
    free (types);
}

void
freeTuples (tuples, no_tuples, no_fields)
TupleBlock *tuples;
{
    int i, j;
    
    if (no_tuples > TupleBlockSize) {
	freeTuples (tuples->next, no_tuples - TupleBlockSize, no_fields);
	no_tuples = TupleBlockSize;
    }
    /* For each tuple, free all its attribute values. */
    for (i = 0; i < no_tuples; i++) {
	for (j = 0; j < no_fields; j++)
	    if (tuples->values[i][j] != NULL)
		free (tuples->values[i][j]);
	free (tuples->values[i]);
    }
    free (tuples);
}

void
freeGroup (group)
	GroupBuffer *group;
{
    if (group->next != NULL)
	freeGroup (group->next);
    if (group->types != NULL)
	freeTypes (group->types);
    if (group->tuples != NULL)
	freeTuples (group->tuples, group->no_tuples);
    free (group);
}

void
freePortal (portal)
	PortalBuffer *portal;
{
    if (portal->groups != NULL)
	freeGroup (portal->groups);
    free (portal);
}
