📄 list.c
字号:
/*------------------------------------------------------------------------- * * list.c * various list handling routines * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /usr/local/cvsroot/pgsql/src/backend/nodes/list.c,v 1.21 1999/05/25 16:09:08 momjian 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"/* * makeList * * Take varargs, terminated by -1, and make a List */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;}/* * lcons * * Add obj to the front of list, or make a new list if 'list' is NIL */List *lcons(void *obj, List *list){ List *l = makeNode(List); lfirst(l) = obj; lnext(l) = list; return l;}/* * lconsi * * Same as lcons, but for integer data */List *lconsi(int datum, List *list){ List *l = makeNode(List); lfirsti(l) = datum; lnext(l) = list; return l;}/* * lappend * * Add obj to the end of list, or make a new list if 'list' is NIL * * MORE EXPENSIVE THAN lcons */List *lappend(List *list, void *obj){ return nconc(list, lcons(obj, NIL));}/* * lappendi * * Same as lappend, but for integers */List *lappendi(List *list, int datum){ return nconc(list, lconsi(datum, NIL));}/* * nconc * * Concat l2 on to the end of l1 */List *nconc(List *l1, List *l2){ List *temp; if (l1 == NIL) return l2; if (l2 == NIL) return l1; if (l1 == l2) elog(ERROR, "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 */}#ifdef NOT_USEDList *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 * * Get the n'th element of the list. First element is 0th. */void *nth(int n, List *l){ /* XXX assume list is long enough */ while (n > 0) { l = lnext(l); n--; } return lfirst(l);}/* * nthi * * Same as nthi, but for integers */intnthi(int n, List *l){ /* XXX assume list is long enough */ while (n > 0) { l = lnext(l); n--; } return lfirsti(l);}/* this is here solely for rt_store. Get rid of me some day! */voidset_nth(List *l, int n, void *elem){ /* XXX assume list is long enough */ while (n > 0) { l = lnext(l); n--; } lfirst(l) = elem; return;}/* * length * * Get the length of l */intlength(List *l){ int i = 0; while (l != NIL) { l = lnext(l); i++; } return i;}/* * freeList * * Free the List nodes of a list */voidfreeList(List *list){ while (list != NIL) { List *l = list; list = lnext(list); pfree(l); }}#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 * * XXX only good for IntList -ay */boolsame(List *l1, List *l2){ List *temp = NIL; if (l1 == NULL) return l2 == NULL; if (l2 == NULL) return l1 == NULL; if (length(l1) == length(l2)) { foreach(temp, l1) { if (!intMember(lfirsti(temp), l2)) return false; } return true; } return false;}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 */ foreach(i, l1) { foreach(j, l2) { if (!equal(lfirst(i), lfirst(j))) { 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 */ foreach(i, l1) { foreach(j, l2) { if (lfirsti(i) != lfirsti(j)) { 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 */boolmember(void *l1, List *l2){ List *i; foreach(i, l2) if (equal((Node *) l1, (Node *) lfirst(i))) return true; return false;}boolintMember(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. */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;}/* * LispRemove */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;}#ifdef NOT_USEDList *intLispRemove(int elem, List *list){ List *temp = NIL; List *prev = NIL; if (elem == lfirsti(list)) return lnext(list); temp = lnext(list); prev = list; while (temp != NIL) { if (elem == lfirsti(temp)) { lnext(prev) = lnext(temp); break; } temp = lnext(temp); prev = lnext(prev); } return list;}#endif/* * set_difference * * Return l1 without the elements in l2. */List *set_difference(List *l1, List *l2){ List *temp1 = NIL; List *result = NIL; if (l2 == NIL) return l1; foreach(temp1, l1) { if (!member(lfirst(temp1), l2)) result = lappend(result, lfirst(temp1)); } return result;}/* * set_differencei * * Same as set_difference, but for integers */List *set_differencei(List *l1, List *l2){ List *temp1 = NIL; List *result = NIL; if (l2 == NIL) return l1; foreach(temp1, l1) { if (!intMember(lfirsti(temp1), l2)) result = lappendi(result, lfirsti(temp1)); } return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -