/*------------------------------------------------------------------------- * * list.c * implementation for PostgreSQL generic linked list package * * * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * src/backend/nodes/list.c * *------------------------------------------------------------------------- */ #include "postgres.h" #include "nodes/pg_list.h" #define IsPointerList(l) ((l) == NIL || IsA((l), List)) #define IsIntegerList(l) ((l) == NIL || IsA((l), IntList)) #define IsOidList(l) ((l) == NIL || IsA((l), OidList)) static List * new_list(NodeTag type); static void new_tail_cell(List *list); static void new_head_cell(List *list); static void check_list_invariants(const List *list); /* * ------------- * Definitions * ------------- */ static List * new_list(NodeTag type) { List *new_list; ListCell *new_head; new_head = (ListCell *) palloc(sizeof(*new_head)); new_head->next = NULL; /* new_head->data is left undefined! */ new_list = (List *) palloc(sizeof(*new_list)); new_list->type = type; new_list->length = 1; new_list->head = new_head; new_list->tail = new_head; return new_list; } static void new_tail_cell(List *list) { ListCell *new_tail; new_tail = (ListCell *) palloc(sizeof(*new_tail)); new_tail->next = NULL; list->tail->next = new_tail; list->tail = new_tail; list->length++; } static void new_head_cell(List *list) { ListCell *new_head; new_head = (ListCell *) palloc(sizeof(*new_head)); new_head->next = list->head; list->head = new_head; list->length++; } static void check_list_invariants(const List *list) { if (list == NIL) return; Assert(list->length > 0); Assert(list->head != NULL); Assert(list->tail != NULL); Assert(list->type == T_List || list->type == T_IntList || list->type == T_OidList); if (list->length == 1) Assert(list->head == list->tail); if (list->length == 2) Assert(list->head->next == list->tail); Assert(list->tail->next == NULL); } List * lappend(List *list, void *datum) { Assert(IsPointerList(list)); if (list == NIL) list = new_list(T_List); else new_tail_cell(list); lfirst(list->tail) = datum; check_list_invariants(list); return list; } List * lcons(void *datum, List *list) { Assert(IsPointerList(list)); if (list == NIL) list = new_list(T_List); else new_head_cell(list); lfirst(list->head) = datum; check_list_invariants(list); return list; }