aboutsummaryrefslogtreecommitdiff
path: root/src/backend/nodes/list.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/nodes/list.c')
-rw-r--r--src/backend/nodes/list.c438
1 files changed, 438 insertions, 0 deletions
diff --git a/src/backend/nodes/list.c b/src/backend/nodes/list.c
new file mode 100644
index 00000000000..20617747c25
--- /dev/null
+++ b/src/backend/nodes/list.c
@@ -0,0 +1,438 @@
+/*-------------------------------------------------------------------------
+ *
+ * list.c--
+ * various list handling routines
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.1.1.1 1996/07/09 06:21:32 scrappy Exp $
+ *
+ * NOTES
+ * XXX a few of the following functions are duplicated to handle
+ * List of pointers and List of integers separately. Some day,
+ * someone should unify them. - ay 11/2/94
+ * This file needs cleanup.
+ *
+ * HISTORY
+ * AUTHOR DATE MAJOR EVENT
+ * Andrew Yu Oct, 1994 file creation
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <stdarg.h>
+#include "postgres.h"
+#include "nodes/pg_list.h"
+#include "nodes/parsenodes.h"
+#include "utils/builtins.h" /* for namecpy */
+#include "utils/elog.h"
+#include "utils/palloc.h"
+
+List *
+makeList(void *elem, ...)
+{
+ va_list args;
+ List *retval = NIL;
+ List *temp = NIL;
+ List *tempcons = NIL;
+
+ va_start(args, elem);
+
+ temp = elem;
+ while (temp != (void *) -1) {
+ temp = lcons(temp, NIL);
+ if (tempcons == NIL)
+ retval = temp;
+ else
+ lnext(tempcons) = temp;
+ tempcons = temp;
+
+ temp = va_arg(args, void *);
+ }
+
+ va_end(args);
+
+ return (retval);
+}
+
+List *
+lcons(void *datum, List *list)
+{
+ List *l = makeNode(List);
+ lfirst(l) = datum;
+ lnext(l) = list;
+ return l;
+}
+
+List *
+lappend(List *list, void *obj)
+{
+ return nconc(list, lcons(obj, NIL));
+}
+
+Value *
+makeInteger(long i)
+{
+ Value *v = makeNode(Value);
+ v->type = T_Integer;
+ v->val.ival = i;
+ return v;
+}
+
+Value *
+makeFloat(double d)
+{
+ Value *v = makeNode(Value);
+ v->type = T_Float;
+ v->val.dval = d;
+ return v;
+}
+
+Value *
+makeString(char *str)
+{
+ Value *v = makeNode(Value);
+ v->type = T_String;
+ v->val.str = str;
+ return v;
+}
+
+/* n starts with 0 */
+void *
+nth(int n, List *l)
+{
+ /* XXX assume list is long enough */
+ while(n > 0) {
+ l = lnext(l);
+ n--;
+ }
+ return lfirst(l);
+}
+
+/* this is here solely for rt_store. Get rid of me some day! */
+void
+set_nth(List *l, int n, void *elem)
+{
+ /* XXX assume list is long enough */
+ while(n > 0) {
+ l = lnext(l);
+ n--;
+ }
+ lfirst(l) = elem;
+ return;
+}
+
+int
+length(List *l)
+{
+ int i=0;
+ while(l!=NIL) {
+ l = lnext(l);
+ i++;
+ }
+ return i;
+}
+
+void
+freeList(List *list)
+{
+ while(list!=NIL) {
+ List *l = list;
+ list = lnext(list);
+ pfree(l);
+ }
+}
+
+/*
+ * below are for backwards compatibility
+ */
+List *
+append(List *l1, List *l2)
+{
+ List *newlist, *newlist2, *p;
+
+ if (l1==NIL)
+ return copyObject(l2);
+
+ newlist = copyObject(l1);
+ newlist2 = copyObject(l2);
+
+ for (p=newlist; lnext(p)!=NIL; p=lnext(p))
+ ;
+ lnext(p) = newlist2;
+ return newlist;
+}
+
+/*
+ * below are for backwards compatibility
+ */
+List *
+intAppend(List *l1, List *l2)
+{
+ List *newlist, *newlist2, *p;
+
+ if (l1==NIL)
+ return listCopy(l2);
+
+ newlist = listCopy(l1);
+ newlist2 = listCopy(l2);
+
+ for (p=newlist; lnext(p)!=NIL; p=lnext(p))
+ ;
+ lnext(p) = newlist2;
+ return newlist;
+}
+
+List *
+nconc(List *l1, List *l2)
+{
+ List *temp;
+
+ if (l1 == NIL)
+ return l2;
+ if (l2 == NIL)
+ return l1;
+ if (l1 == l2)
+ elog(WARN, "tryout to nconc a list to itself");
+
+ for (temp = l1; lnext(temp)!=NULL; temp = lnext(temp))
+ ;
+
+ lnext(temp) = l2;
+ return(l1); /* list1 is now list1[]list2 */
+}
+
+
+List *
+nreverse(List *list)
+{
+ List *rlist = NIL;
+ List *p = NIL;
+
+ if(list==NULL)
+ return(NIL);
+
+ if (length(list) == 1)
+ return(list);
+
+ for (p = list; p!=NULL; p = lnext(p)) {
+ rlist = lcons(lfirst(p),rlist);
+ }
+
+ lfirst(list) = lfirst(rlist);
+ lnext(list) = lnext(rlist);
+ return(list);
+}
+
+/*
+ * same
+ *
+ * Returns t if two lists contain the same elements.
+ * now defined in lispdep.c
+ *
+ * XXX only good for IntList -ay
+ */
+bool
+same(List *foo, List *bar)
+{
+ List *temp = NIL;
+
+ if (foo == NULL)
+ return (bar==NULL);
+ if (bar == NULL)
+ return (foo==NULL);
+ if (length(foo) == length(bar)) {
+ foreach (temp,foo) {
+ if (!intMember((int)lfirst(temp),bar))
+ return(false);
+ }
+ return(true);
+ }
+ return(false);
+
+}
+
+List *
+LispUnion(List *foo, List *bar)
+{
+ List *retval = NIL;
+ List *i = NIL;
+ List *j = NIL;
+
+ if (foo==NIL)
+ return(bar); /* XXX - should be copy of bar */
+
+ if (bar==NIL)
+ return(foo); /* XXX - should be copy of foo */
+
+ foreach (i,foo) {
+ foreach (j,bar) {
+ if (! equal(lfirst(i), lfirst(j))) {
+ retval = lappend(retval,lfirst(i));
+ break;
+ }
+ }
+ }
+ foreach(i,bar) {
+ retval = lappend(retval,lfirst(i));
+ }
+
+ return(retval);
+}
+
+List *
+LispUnioni(List *foo, List *bar)
+{
+ List *retval = NIL;
+ List *i = NIL;
+ List *j = NIL;
+
+ if (foo==NIL)
+ return(bar); /* XXX - should be copy of bar */
+
+ if (bar==NIL)
+ return(foo); /* XXX - should be copy of foo */
+
+ foreach (i,foo) {
+ foreach (j,bar) {
+ if (lfirsti(i) != lfirsti(j)) {
+ retval = lappendi(retval,lfirst(i));
+ break;
+ }
+ }
+ }
+ foreach(i,bar) {
+ retval = lappendi(retval, lfirsti(i));
+ }
+
+ return(retval);
+}
+
+/*
+ * member()
+ * - nondestructive, returns t iff foo is a member of the list
+ * bar
+ */
+bool
+member(void *foo, List *bar)
+{
+ List *i;
+ foreach (i,bar)
+ if (equal((Node*)(lfirst(i)),(Node*)foo))
+ return(true);
+ return(false);
+}
+
+bool
+intMember(int foo, List *bar)
+{
+ List *i;
+ foreach (i,bar)
+ if (foo == (int)lfirst(i))
+ return(true);
+ return(false);
+}
+
+/*
+ * lremove -
+ * only does pointer comparisons. Removes 'elem' from the the linked list.
+ */
+List *
+lremove(void *elem, List *list)
+{
+ List *l;
+ List *prev = NIL;
+ List *result = list;
+
+ foreach(l, list) {
+ if (elem == lfirst(l))
+ break;
+ prev = l;
+ }
+ if (l!=NULL) {
+ if (prev == NIL) {
+ result = lnext(list);
+ } else {
+ lnext(prev) = lnext(l);
+ }
+ }
+ return result;
+}
+
+List *
+LispRemove(void *elem, List *list)
+{
+ List *temp = NIL;
+ List *prev = NIL;
+
+ if (equal(elem, lfirst(list)))
+ return lnext(list);
+
+ temp = lnext(list);
+ prev = list;
+ while(temp!=NIL) {
+ if (equal(elem, lfirst(temp))) {
+ lnext(prev) = lnext(temp);
+ break;
+ }
+ temp = lnext(temp);
+ prev = lnext(prev);
+ }
+ return(list);
+}
+
+List *
+intLispRemove(int elem, List *list)
+{
+ List *temp = NIL;
+ List *prev = NIL;
+
+ if (elem == (int)lfirst(list))
+ return lnext(list);
+
+ temp = lnext(list);
+ prev = list;
+ while(temp!=NIL) {
+ if (elem == (int)lfirst(temp)) {
+ lnext(prev) = lnext(temp);
+ break;
+ }
+ temp = lnext(temp);
+ prev = lnext(prev);
+ }
+ return(list);
+}
+
+List *
+set_difference(List *list1, List *list2)
+{
+ List *temp1 = NIL;
+ List *result = NIL;
+
+ if (list2==NIL)
+ return(list1);
+
+ foreach (temp1, list1) {
+ if (!member(lfirst(temp1), list2))
+ result = lappend(result, lfirst(temp1));
+ }
+ return(result);
+}
+
+List *
+set_differencei(List *list1, List *list2)
+{
+ List *temp1 = NIL;
+ List *result = NIL;
+
+ if (list2==NIL)
+ return(list1);
+
+ foreach (temp1, list1) {
+ if (!intMember(lfirsti(temp1), list2))
+ result = lappendi(result, lfirst(temp1));
+ }
+ return(result);
+}
+