aboutsummaryrefslogtreecommitdiff
path: root/src/include/nodes/pg_list.h
blob: 8ab22560ce6d055f1367513d90825b4e0dc8a15e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*-------------------------------------------------------------------------
 *
 * pg_list.h
 *	  POSTGRES generic list package
 *
 *
 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * $Id: pg_list.h,v 1.41 2003/08/22 20:34:33 tgl Exp $
 *
 *-------------------------------------------------------------------------
 */
#ifndef PG_LIST_H
#define PG_LIST_H

#include "nodes/nodes.h"

/* ----------------------------------------------------------------
 *						node definitions
 * ----------------------------------------------------------------
 */

/*----------------------
 *		Value node
 *
 * The same Value struct is used for five node types: T_Integer,
 * T_Float, T_String, T_BitString, T_Null.
 *
 * Integral values are actually represented by a machine integer,
 * but both floats and strings are represented as strings.
 * Using T_Float as the node type simply indicates that
 * the contents of the string look like a valid numeric literal.
 *
 * (Before Postgres 7.0, we used a double to represent T_Float,
 * but that creates loss-of-precision problems when the value is
 * ultimately destined to be converted to NUMERIC.	Since Value nodes
 * are only used in the parsing process, not for runtime data, it's
 * better to use the more general representation.)
 *
 * Note that an integer-looking string will get lexed as T_Float if
 * the value is too large to fit in a 'long'.
 *
 * Nulls, of course, don't need the value part at all.
 *----------------------
 */
typedef struct Value
{
	NodeTag		type;			/* tag appropriately (eg. T_String) */
	union ValUnion
	{
		long		ival;		/* machine integer */
		char	   *str;		/* string */
	}			val;
} Value;

#define intVal(v)		(((Value *)(v))->val.ival)
#define floatVal(v)		atof(((Value *)(v))->val.str)
#define strVal(v)		(((Value *)(v))->val.str)


/*----------------------
 *		List node
 *
 * We support three types of lists:
 *	lists of pointers (in practice always pointers to Nodes, but declare as
 *		"void *" to minimize casting annoyances)
 *	lists of integers
 *	lists of Oids
 *
 * (At this writing, ints and Oids are the same size, but they may not always
 * be so; try to be careful to maintain the distinction.)
 *----------------------
 */
typedef struct List
{
	NodeTag		type;
	union
	{
		void	   *ptr_value;
		int			int_value;
		Oid			oid_value;
	}			elem;
	struct List *next;
} List;

#define    NIL			((List *) NULL)

/* ----------------
 *		accessor macros
 *
 * The general naming convention is that the base name xyz() is for the
 * pointer version, xyzi() is for integers, xyzo() is for Oids.  We don't
 * bother with multiple names if the same routine can handle all cases.
 * ----------------
 */

#define lfirst(l)								((l)->elem.ptr_value)
#define lfirsti(l)								((l)->elem.int_value)
#define lfirsto(l)								((l)->elem.oid_value)

#define lnext(l)								((l)->next)

#define lsecond(l)								lfirst(lnext(l))

#define lthird(l)								lfirst(lnext(lnext(l)))

#define lfourth(l)								lfirst(lnext(lnext(lnext(l))))

/*
 * foreach -
 *	  a convenience macro which loops through the list
 */
#define foreach(_elt_,_list_)	\
	for (_elt_ = (_list_); _elt_ != NIL; _elt_ = lnext(_elt_))

/*
 * Convenience macros for building fixed-length lists
 */
#define makeList1(x1)				lcons(x1, NIL)
#define makeList2(x1,x2)			lcons(x1, makeList1(x2))
#define makeList3(x1,x2,x3)			lcons(x1, makeList2(x2,x3))
#define makeList4(x1,x2,x3,x4)		lcons(x1, makeList3(x2,x3,x4))

#define makeListi1(x1)				lconsi(x1, NIL)
#define makeListi2(x1,x2)			lconsi(x1, makeListi1(x2))

#define makeListo1(x1)				lconso(x1, NIL)
#define makeListo2(x1,x2)			lconso(x1, makeListo1(x2))

/*
 * FastList is an optimization for building large lists.  The conventional
 * way to build a list is repeated lappend() operations, but that is O(N^2)
 * in the number of list items, which gets tedious for large lists.
 *
 * Note: there are some hacks in gram.y that rely on the head pointer (the
 * value-as-list) being the first field.
 */
typedef struct FastList
{
	List	   *head;
	List	   *tail;
} FastList;

#define FastListInit(fl)	( (fl)->head = (fl)->tail = NIL )
#define FastListFromList(fl, l)  \
	( (fl)->head = (l), (fl)->tail = llastnode((fl)->head) )
#define FastListValue(fl)	( (fl)->head )

#define makeFastList1(fl, x1)  \
	( (fl)->head = (fl)->tail = makeList1(x1) )


/*
 * function prototypes in nodes/list.c
 */
extern Value *makeInteger(long i);
extern Value *makeFloat(char *numericStr);
extern Value *makeString(char *str);
extern Value *makeBitString(char *str);

extern List *lcons(void *datum, List *list);
extern List *lconsi(int datum, List *list);
extern List *lconso(Oid datum, List *list);
extern List *lappend(List *list, void *datum);
extern List *lappendi(List *list, int datum);
extern List *lappendo(List *list, Oid datum);
extern List *nconc(List *list1, List *list2);
extern void FastAppend(FastList *fl, void *datum);
extern void FastAppendi(FastList *fl, int datum);
extern void FastAppendo(FastList *fl, Oid datum);
extern void FastConc(FastList *fl, List *cells);
extern void FastConcFast(FastList *fl, FastList *fl2);
extern void *nth(int n, List *l);
extern int	length(List *list);
extern void *llast(List *list);
extern List *llastnode(List *list);
extern bool member(void *datum, List *list);
extern bool ptrMember(void *datum, List *list);
extern bool intMember(int datum, List *list);
extern bool oidMember(Oid datum, List *list);
extern List *lremove(void *elem, List *list);
extern List *LispRemove(void *elem, List *list);
extern List *lremovei(int elem, List *list);
extern List *ltruncate(int n, List *list);

extern List *set_union(List *list1, List *list2);
extern List *set_uniono(List *list1, List *list2);
extern List *set_ptrUnion(List *list1, List *list2);
extern List *set_difference(List *list1, List *list2);
extern List *set_differenceo(List *list1, List *list2);
extern List *set_ptrDifference(List *list1, List *list2);

extern bool equali(List *list1, List *list2);
extern bool equalo(List *list1, List *list2);

extern void freeList(List *list);

/* in copyfuncs.c */
extern List *listCopy(List *list);

#endif   /* PG_LIST_H */