summaryrefslogtreecommitdiffstats
path: root/src/include/lib/qunique.h
blob: 95d9fef637a37ad2c4d479779a006c96733c4148 (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
/*-------------------------------------------------------------------------
 *
 * qunique.h
 *		inline array unique functions
 * Portions Copyright (c) 2019-2020, PostgreSQL Global Development Group
 *
 * IDENTIFICATION
 *		src/include/lib/qunique.h
 *-------------------------------------------------------------------------
 */

#ifndef QUNIQUE_H
#define QUNIQUE_H

/*
 * Remove duplicates from a pre-sorted array, according to a user-supplied
 * comparator.  Usually the array should have been sorted with qsort() using
 * the same arguments.  Return the new size.
 */
static inline size_t
qunique(void *array, size_t elements, size_t width,
		int (*compare) (const void *, const void *))
{
	char	   *bytes = (char *) array;
	size_t		i,
				j;

	if (elements <= 1)
		return elements;

	for (i = 1, j = 0; i < elements; ++i)
	{
		if (compare(bytes + i * width, bytes + j * width) != 0 &&
			++j != i)
			memcpy(bytes + j * width, bytes + i * width, width);
	}

	return j + 1;
}

/*
 * Like qunique(), but takes a comparator with an extra user data argument
 * which is passed through, for compatibility with qsort_arg().
 */
static inline size_t
qunique_arg(void *array, size_t elements, size_t width,
			int (*compare) (const void *, const void *, void *),
			void *arg)
{
	char	   *bytes = (char *) array;
	size_t		i,
				j;

	if (elements <= 1)
		return elements;

	for (i = 1, j = 0; i < elements; ++i)
	{
		if (compare(bytes + i * width, bytes + j * width, arg) != 0 &&
			++j != i)
			memcpy(bytes + j * width, bytes + i * width, width);
	}

	return j + 1;
}

#endif							/* QUNIQUE_H */