|
|
|
@ -7,7 +7,7 @@ |
|
|
|
|
* |
|
|
|
|
* |
|
|
|
|
* IDENTIFICATION |
|
|
|
|
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.25 1999/07/17 20:17:06 momjian Exp $ |
|
|
|
|
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.26 1999/08/14 19:29:35 tgl Exp $ |
|
|
|
|
* |
|
|
|
|
* NOTES |
|
|
|
|
* XXX a few of the following functions are duplicated to handle |
|
|
|
@ -57,6 +57,45 @@ makeList(void *elem,...) |
|
|
|
|
return retval; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* makeInteger |
|
|
|
|
*/ |
|
|
|
|
Value * |
|
|
|
|
makeInteger(long i) |
|
|
|
|
{ |
|
|
|
|
Value *v = makeNode(Value); |
|
|
|
|
|
|
|
|
|
v->type = T_Integer; |
|
|
|
|
v->val.ival = i; |
|
|
|
|
return v; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* makeFloat |
|
|
|
|
*/ |
|
|
|
|
Value * |
|
|
|
|
makeFloat(double d) |
|
|
|
|
{ |
|
|
|
|
Value *v = makeNode(Value); |
|
|
|
|
|
|
|
|
|
v->type = T_Float; |
|
|
|
|
v->val.dval = d; |
|
|
|
|
return v; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* makeString |
|
|
|
|
*/ |
|
|
|
|
Value * |
|
|
|
|
makeString(char *str) |
|
|
|
|
{ |
|
|
|
|
Value *v = makeNode(Value); |
|
|
|
|
|
|
|
|
|
v->type = T_String; |
|
|
|
|
v->val.str = str; |
|
|
|
|
return v; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* lcons |
|
|
|
|
* |
|
|
|
@ -115,6 +154,9 @@ lappendi(List *list, int datum) |
|
|
|
|
* nconc |
|
|
|
|
* |
|
|
|
|
* Concat l2 on to the end of l1 |
|
|
|
|
* |
|
|
|
|
* NB: l1 is destructively changed! Use nconc(listCopy(l1), l2) |
|
|
|
|
* if you need to make a merged list without touching the original lists. |
|
|
|
|
*/ |
|
|
|
|
List * |
|
|
|
|
nconc(List *l1, List *l2) |
|
|
|
@ -128,76 +170,13 @@ nconc(List *l1, List *l2) |
|
|
|
|
if (l1 == l2) |
|
|
|
|
elog(ERROR, "tryout to nconc a list to itself"); |
|
|
|
|
|
|
|
|
|
for (temp = l1; lnext(temp) != NULL; temp = lnext(temp)) |
|
|
|
|
for (temp = l1; lnext(temp) != NIL; temp = lnext(temp)) |
|
|
|
|
; |
|
|
|
|
|
|
|
|
|
lnext(temp) = l2; |
|
|
|
|
return l1; /* list1 is now list1+list2 */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef NOT_USED |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* makeInteger |
|
|
|
|
*/ |
|
|
|
|
Value * |
|
|
|
|
makeInteger(long i) |
|
|
|
|
{ |
|
|
|
|
Value *v = makeNode(Value); |
|
|
|
|
|
|
|
|
|
v->type = T_Integer; |
|
|
|
|
v->val.ival = i; |
|
|
|
|
return v; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* makeFloat |
|
|
|
|
*/ |
|
|
|
|
Value * |
|
|
|
|
makeFloat(double d) |
|
|
|
|
{ |
|
|
|
|
Value *v = makeNode(Value); |
|
|
|
|
|
|
|
|
|
v->type = T_Float; |
|
|
|
|
v->val.dval = d; |
|
|
|
|
return v; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* makeString |
|
|
|
|
*/ |
|
|
|
|
Value * |
|
|
|
|
makeString(char *str) |
|
|
|
|
{ |
|
|
|
|
Value *v = makeNode(Value); |
|
|
|
|
|
|
|
|
|
v->type = T_String; |
|
|
|
|
v->val.str = str; |
|
|
|
|
return v; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* nth |
|
|
|
|
* |
|
|
|
@ -243,7 +222,6 @@ set_nth(List *l, int n, void *elem) |
|
|
|
|
n--; |
|
|
|
|
} |
|
|
|
|
lfirst(l) = elem; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -268,6 +246,9 @@ length(List *l) |
|
|
|
|
* freeList |
|
|
|
|
* |
|
|
|
|
* Free the List nodes of a list |
|
|
|
|
* The pointed-to nodes, if any, are NOT freed. |
|
|
|
|
* This works for integer lists too. |
|
|
|
|
*
|
|
|
|
|
*/ |
|
|
|
|
void |
|
|
|
|
freeList(List *list) |
|
|
|
@ -281,73 +262,24 @@ freeList(List *list) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef NOT_USED |
|
|
|
|
/*
|
|
|
|
|
* 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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifdef NOT_USED |
|
|
|
|
/*
|
|
|
|
|
* 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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* same |
|
|
|
|
* |
|
|
|
|
* Returns t if two lists contain the same elements. |
|
|
|
|
* now defined in lispdep.c |
|
|
|
|
* Returns t if two lists contain the same elements |
|
|
|
|
* (but unlike equal(), they need not be in the same order) |
|
|
|
|
*
|
|
|
|
|
* |
|
|
|
|
* XXX only good for IntList -ay |
|
|
|
|
* XXX should be called samei() --- only good for IntList -ay |
|
|
|
|
*/ |
|
|
|
|
bool |
|
|
|
|
same(List *l1, List *l2) |
|
|
|
|
{ |
|
|
|
|
List *temp = NIL; |
|
|
|
|
List *temp; |
|
|
|
|
|
|
|
|
|
if (l1 == NULL) |
|
|
|
|
return l2 == NULL; |
|
|
|
|
if (l2 == NULL) |
|
|
|
|
return l1 == NULL; |
|
|
|
|
if (l1 == NIL) |
|
|
|
|
return l2 == NIL; |
|
|
|
|
if (l2 == NIL) |
|
|
|
|
return l1 == NIL; |
|
|
|
|
if (length(l1) == length(l2)) |
|
|
|
|
{ |
|
|
|
|
foreach(temp, l1) |
|
|
|
@ -361,70 +293,47 @@ same(List *l1, List *l2) |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Generate the union of two lists, |
|
|
|
|
* ie, l1 plus all members of l2 that are not already in l1. |
|
|
|
|
* |
|
|
|
|
* NOTE: if there are duplicates in l1 they will still be duplicate in the |
|
|
|
|
* result; but duplicates in l2 are discarded. |
|
|
|
|
* |
|
|
|
|
* The result is a fresh List, but it points to the same member nodes |
|
|
|
|
* as were in the inputs. |
|
|
|
|
*/ |
|
|
|
|
List * |
|
|
|
|
LispUnion(List *l1, List *l2) |
|
|
|
|
{ |
|
|
|
|
List *retval = NIL; |
|
|
|
|
List *i = NIL; |
|
|
|
|
List *j = NIL; |
|
|
|
|
|
|
|
|
|
if (l1 == NIL) |
|
|
|
|
return l2; /* XXX - should be copy of l2 */ |
|
|
|
|
|
|
|
|
|
if (l2 == NIL) |
|
|
|
|
return l1; /* XXX - should be copy of l1 */ |
|
|
|
|
List *retval = listCopy(l1); |
|
|
|
|
List *i; |
|
|
|
|
|
|
|
|
|
foreach(i, l1) |
|
|
|
|
{ |
|
|
|
|
foreach(j, l2) |
|
|
|
|
{ |
|
|
|
|
if (!equal(lfirst(i), lfirst(j))) |
|
|
|
|
foreach(i, l2) |
|
|
|
|
{ |
|
|
|
|
if (! member(lfirst(i), retval)) |
|
|
|
|
retval = lappend(retval, lfirst(i)); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
foreach(i, l2) |
|
|
|
|
retval = lappend(retval, lfirst(i)); |
|
|
|
|
|
|
|
|
|
return retval; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
List * |
|
|
|
|
LispUnioni(List *l1, List *l2) |
|
|
|
|
{ |
|
|
|
|
List *retval = NIL; |
|
|
|
|
List *i = NIL; |
|
|
|
|
List *j = NIL; |
|
|
|
|
|
|
|
|
|
if (l1 == NIL) |
|
|
|
|
return l2; /* XXX - should be copy of l2 */ |
|
|
|
|
|
|
|
|
|
if (l2 == NIL) |
|
|
|
|
return l1; /* XXX - should be copy of l1 */ |
|
|
|
|
List *retval = listCopy(l1); |
|
|
|
|
List *i; |
|
|
|
|
|
|
|
|
|
foreach(i, l1) |
|
|
|
|
{ |
|
|
|
|
foreach(j, l2) |
|
|
|
|
{ |
|
|
|
|
if (lfirsti(i) != lfirsti(j)) |
|
|
|
|
foreach(i, l2) |
|
|
|
|
{ |
|
|
|
|
if (! intMember(lfirsti(i), retval)) |
|
|
|
|
retval = lappendi(retval, lfirsti(i)); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
foreach(i, l2) |
|
|
|
|
retval = lappendi(retval, lfirsti(i)); |
|
|
|
|
|
|
|
|
|
return retval; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* member() |
|
|
|
|
* - nondestructive, returns t iff l1 is a member of the list |
|
|
|
|
* l2 |
|
|
|
|
* nondestructive, returns t iff l1 is a member of the list l2 |
|
|
|
|
*/ |
|
|
|
|
bool |
|
|
|
|
member(void *l1, List *l2) |
|
|
|
@ -432,8 +341,10 @@ member(void *l1, List *l2) |
|
|
|
|
List *i; |
|
|
|
|
|
|
|
|
|
foreach(i, l2) |
|
|
|
|
{ |
|
|
|
|
if (equal((Node *) l1, (Node *) lfirst(i))) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -443,14 +354,18 @@ intMember(int l1, List *l2) |
|
|
|
|
List *i; |
|
|
|
|
|
|
|
|
|
foreach(i, l2) |
|
|
|
|
{ |
|
|
|
|
if (l1 == lfirsti(i)) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* lremove - |
|
|
|
|
* only does pointer comparisons. Removes 'elem' from the the linked list. |
|
|
|
|
* lremove |
|
|
|
|
* Removes 'elem' from the the linked list. |
|
|
|
|
* This version matches 'elem' using simple pointer comparison. |
|
|
|
|
* See also LispRemove. |
|
|
|
|
*/ |
|
|
|
|
List * |
|
|
|
|
lremove(void *elem, List *list) |
|
|
|
@ -465,10 +380,10 @@ lremove(void *elem, List *list) |
|
|
|
|
break; |
|
|
|
|
prev = l; |
|
|
|
|
} |
|
|
|
|
if (l != NULL) |
|
|
|
|
if (l != NIL) |
|
|
|
|
{ |
|
|
|
|
if (prev == NIL) |
|
|
|
|
result = lnext(list); |
|
|
|
|
result = lnext(l); |
|
|
|
|
else |
|
|
|
|
lnext(prev) = lnext(l); |
|
|
|
|
} |
|
|
|
@ -477,54 +392,57 @@ lremove(void *elem, List *list) |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* LispRemove |
|
|
|
|
* Removes 'elem' from the the linked list. |
|
|
|
|
* This version matches 'elem' using equal(). |
|
|
|
|
* (If there is more than one equal list member, the first is removed.) |
|
|
|
|
* See also lremove. |
|
|
|
|
*/ |
|
|
|
|
List * |
|
|
|
|
LispRemove(void *elem, List *list) |
|
|
|
|
{ |
|
|
|
|
List *temp = NIL; |
|
|
|
|
List *l; |
|
|
|
|
List *prev = NIL; |
|
|
|
|
List *result = list; |
|
|
|
|
|
|
|
|
|
if (equal(elem, lfirst(list))) |
|
|
|
|
return lnext(list); |
|
|
|
|
|
|
|
|
|
temp = lnext(list); |
|
|
|
|
prev = list; |
|
|
|
|
while (temp != NIL) |
|
|
|
|
{ |
|
|
|
|
if (equal(elem, lfirst(temp))) |
|
|
|
|
foreach(l, list) |
|
|
|
|
{ |
|
|
|
|
lnext(prev) = lnext(temp); |
|
|
|
|
if (equal(elem, lfirst(l))) |
|
|
|
|
break; |
|
|
|
|
prev = l; |
|
|
|
|
} |
|
|
|
|
temp = lnext(temp); |
|
|
|
|
prev = lnext(prev); |
|
|
|
|
if (l != NIL) |
|
|
|
|
{ |
|
|
|
|
if (prev == NIL) |
|
|
|
|
result = lnext(l); |
|
|
|
|
else |
|
|
|
|
lnext(prev) = lnext(l); |
|
|
|
|
} |
|
|
|
|
return list; |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef NOT_USED |
|
|
|
|
|
|
|
|
|
List * |
|
|
|
|
intLispRemove(int elem, List *list) |
|
|
|
|
{ |
|
|
|
|
List *temp = NIL; |
|
|
|
|
List *l; |
|
|
|
|
List *prev = NIL; |
|
|
|
|
List *result = list; |
|
|
|
|
|
|
|
|
|
if (elem == lfirsti(list)) |
|
|
|
|
return lnext(list); |
|
|
|
|
|
|
|
|
|
temp = lnext(list); |
|
|
|
|
prev = list; |
|
|
|
|
while (temp != NIL) |
|
|
|
|
{ |
|
|
|
|
if (elem == lfirsti(temp)) |
|
|
|
|
foreach(l, list) |
|
|
|
|
{ |
|
|
|
|
lnext(prev) = lnext(temp); |
|
|
|
|
if (elem == lfirsti(l)) |
|
|
|
|
break; |
|
|
|
|
prev = l; |
|
|
|
|
} |
|
|
|
|
temp = lnext(temp); |
|
|
|
|
prev = lnext(prev); |
|
|
|
|
if (l != NIL) |
|
|
|
|
{ |
|
|
|
|
if (prev == NIL) |
|
|
|
|
result = lnext(l); |
|
|
|
|
else |
|
|
|
|
lnext(prev) = lnext(l); |
|
|
|
|
} |
|
|
|
|
return list; |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
@ -533,20 +451,23 @@ intLispRemove(int elem, List *list) |
|
|
|
|
* set_difference |
|
|
|
|
* |
|
|
|
|
* Return l1 without the elements in l2. |
|
|
|
|
* |
|
|
|
|
* The result is a fresh List, but it points to the same member nodes |
|
|
|
|
* as were in l1. |
|
|
|
|
*/ |
|
|
|
|
List * |
|
|
|
|
set_difference(List *l1, List *l2) |
|
|
|
|
{ |
|
|
|
|
List *temp1 = NIL; |
|
|
|
|
List *result = NIL; |
|
|
|
|
List *i; |
|
|
|
|
|
|
|
|
|
if (l2 == NIL) |
|
|
|
|
return l1; |
|
|
|
|
return listCopy(l1); /* slightly faster path for empty l2 */ |
|
|
|
|
|
|
|
|
|
foreach(temp1, l1) |
|
|
|
|
foreach(i, l1) |
|
|
|
|
{ |
|
|
|
|
if (!member(lfirst(temp1), l2)) |
|
|
|
|
result = lappend(result, lfirst(temp1)); |
|
|
|
|
if (! member(lfirst(i), l2)) |
|
|
|
|
result = lappend(result, lfirst(i)); |
|
|
|
|
} |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
@ -559,16 +480,16 @@ set_difference(List *l1, List *l2) |
|
|
|
|
List * |
|
|
|
|
set_differencei(List *l1, List *l2) |
|
|
|
|
{ |
|
|
|
|
List *temp1 = NIL; |
|
|
|
|
List *result = NIL; |
|
|
|
|
List *i; |
|
|
|
|
|
|
|
|
|
if (l2 == NIL) |
|
|
|
|
return l1; |
|
|
|
|
return listCopy(l1); /* slightly faster path for empty l2 */ |
|
|
|
|
|
|
|
|
|
foreach(temp1, l1) |
|
|
|
|
foreach(i, l1) |
|
|
|
|
{ |
|
|
|
|
if (!intMember(lfirsti(temp1), l2)) |
|
|
|
|
result = lappendi(result, lfirsti(temp1)); |
|
|
|
|
if (! intMember(lfirsti(i), l2)) |
|
|
|
|
result = lappendi(result, lfirsti(i)); |
|
|
|
|
} |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|