/*
|
* Licensed to the Apache Software Foundation (ASF) under one
|
* or more contributor license agreements. See the NOTICE file
|
* distributed with this work for additional information
|
* regarding copyright ownership. The ASF licenses this file
|
* to you under the Apache License, Version 2.0 (the
|
* "License"); you may not use this file except in compliance
|
* with the License. You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing,
|
* software distributed under the License is distributed on an
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
* KIND, either express or implied. See the License for the
|
* specific language governing permissions and limitations
|
* under the License.
|
*/
|
|
#include "postgres.h"
|
|
#include "utils/age_graphid_ds.h"
|
|
/* defines */
|
/*
|
* A simple linked list node for graphid lists (int64). PG's implementation
|
* has too much overhead for this type of list as it only directly supports
|
* regular ints, not int64s, of which a graphid currently is.
|
*/
|
typedef struct GraphIdNode
|
{
|
graphid id;
|
struct GraphIdNode *next;
|
} GraphIdNode;
|
|
/* a container for a linked list of GraphIdNodes */
|
typedef struct ListGraphId
|
{
|
GraphIdNode *head;
|
GraphIdNode *tail;
|
int64 size;
|
} ListGraphId;
|
|
/* declarations */
|
|
/* definitions */
|
/* return the next GraphIdNode */
|
GraphIdNode *next_GraphIdNode(GraphIdNode *node)
|
{
|
return node->next;
|
}
|
|
/* return the graphid */
|
graphid get_graphid(GraphIdNode *node)
|
{
|
return node->id;
|
}
|
|
/* get the size of the passed stack */
|
int64 get_stack_size(ListGraphId *stack)
|
{
|
return stack->size;
|
}
|
|
/* return a reference to the head entry in the stack, or NULL if empty */
|
GraphIdNode *peek_stack_head(ListGraphId *stack)
|
{
|
if (stack == NULL)
|
{
|
return NULL;
|
}
|
|
return stack->head;
|
}
|
|
/* return a reference to the tail entry in the stack */
|
GraphIdNode *peek_stack_tail(ListGraphId *stack)
|
{
|
return stack->tail;
|
}
|
|
/* return a reference to the head entry of a list */
|
GraphIdNode *get_list_head(ListGraphId *list)
|
{
|
return list->head;
|
}
|
|
/* get the size of the passed list */
|
int64 get_list_size(ListGraphId *list)
|
{
|
return list->size;
|
}
|
|
/*
|
* Helper function to add a graphid to the end of a ListGraphId container.
|
* If the container is NULL, it creates the container with the entry.
|
*/
|
ListGraphId *append_graphid(ListGraphId *container, graphid id)
|
{
|
GraphIdNode *new_node = NULL;
|
|
/* create the new link */
|
new_node = palloc0(sizeof(GraphIdNode));
|
new_node->id = id;
|
new_node->next = NULL;
|
|
/*
|
* If the container is NULL then this is a new list. So, create the
|
* container and add in the new link.
|
*/
|
if (container == NULL)
|
{
|
container = palloc0(sizeof(ListGraphId));
|
container->head = new_node;
|
container->tail = new_node;
|
container->size = 1;
|
}
|
/* otherwise, this is an existing list, append id */
|
else
|
{
|
container->tail->next = new_node;
|
container->tail = new_node;
|
container->size++;
|
}
|
|
return container;
|
}
|
|
/* free (delete) a ListGraphId list */
|
void free_ListGraphId(ListGraphId *container)
|
{
|
GraphIdNode *curr_node = NULL;
|
GraphIdNode *next_node = NULL;
|
|
/* if the container is NULL we don't need to delete anything */
|
if (container == NULL)
|
{
|
return;
|
}
|
|
/* otherwise, start from the head, free, and delete the links */
|
curr_node = container->head;
|
while (curr_node != NULL)
|
{
|
next_node = curr_node->next;
|
/* we can do this because this is just a list of ints */
|
pfree(curr_node);
|
curr_node = next_node;
|
}
|
|
/* free the container */
|
pfree(container);
|
}
|
|
/* helper function to create a new, empty, graphid stack */
|
ListGraphId *new_graphid_stack(void)
|
{
|
ListGraphId *stack = NULL;
|
|
/* allocate the container for the stack */
|
stack = palloc0(sizeof(ListGraphId));
|
|
/* set it to its initial values */
|
stack->head = NULL;
|
stack->tail = NULL;
|
stack->size = 0;
|
|
/* return the new stack */
|
return stack;
|
}
|
|
/* helper function to free a graphid stack's contents but, not the container */
|
void free_graphid_stack(ListGraphId *stack)
|
{
|
Assert(stack != NULL);
|
|
if (stack == NULL)
|
{
|
elog(ERROR, "free_graphid_stack: NULL stack");
|
}
|
|
/* while there are entries */
|
while (stack->head != NULL)
|
{
|
/* get the next element in the stack */
|
GraphIdNode *next = stack->head->next;
|
|
/* free the head element */
|
pfree(stack->head);
|
/* move the head to the next */
|
stack->head = next;
|
}
|
|
/* reset the tail and size */
|
stack->tail = NULL;
|
stack->size = 0;
|
}
|
|
/*
|
* Helper function for a generic push graphid (int64) to a stack. If the stack
|
* is NULL, it will error out.
|
*/
|
void push_graphid_stack(ListGraphId *stack, graphid id)
|
{
|
GraphIdNode *new_node = NULL;
|
|
Assert(stack != NULL);
|
|
if (stack == NULL)
|
{
|
elog(ERROR, "push_graphid_stack: NULL stack");
|
}
|
|
/* create the new element */
|
new_node = palloc0(sizeof(GraphIdNode));
|
new_node->id = id;
|
|
/* insert (push) the new element on the top */
|
new_node->next = stack->head;
|
stack->head = new_node;
|
stack->size++;
|
}
|
|
/*
|
* Helper function for a generic pop graphid (int64) from a stack. If the stack
|
* is empty, it will error out. You should verify that the stack isn't empty
|
* prior to calling.
|
*/
|
graphid pop_graphid_stack(ListGraphId *stack)
|
{
|
GraphIdNode *node = NULL;
|
graphid id;
|
|
Assert(stack != NULL);
|
Assert(stack->size != 0);
|
|
if (stack == NULL)
|
{
|
elog(ERROR, "pop_graphid_stack: NULL stack");
|
}
|
|
if (stack->size <= 0)
|
{
|
elog(ERROR, "pop_graphid_stack: empty stack");
|
}
|
|
|
/* remove the element from the top of the stack */
|
node = stack->head;
|
id = node->id;
|
stack->head = stack->head->next;
|
stack->size--;
|
/* free the element */
|
pfree(node);
|
|
/* return the id */
|
return id;
|
}
|