aboutsummaryrefslogtreecommitdiff
path: root/src/include/common/pg_crc.h
blob: f496659baf1a16d4b92fbbde72d50165927a8af6 (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
/*
 * pg_crc.h
 *
 * PostgreSQL CRC support
 *
 * See Ross Williams' excellent introduction
 * A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS, available from
 * http://www.ross.net/crc/ or several other net sites.
 *
 * We have three slightly different variants of a 32-bit CRC calculation:
 * CRC-32C (Castagnoli polynomial), CRC-32 (Ethernet polynomial), and a legacy
 * CRC-32 version that uses the lookup table in a funny way. They all consist
 * of four macros:
 *
 * INIT_<variant>(crc)
 *		Initialize a CRC accumulator
 *
 * COMP_<variant>(crc, data, len)
 *		Accumulate some (more) bytes into a CRC
 *
 * FIN_<variant>(crc)
 *		Finish a CRC calculation
 *
 * EQ_<variant>(c1, c2)
 *		Check for equality of two CRCs.
 *
 * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/common/pg_crc.h
 */
#ifndef PG_CRC_H
#define PG_CRC_H

/* ugly hack to let this be used in frontend and backend code on Cygwin */
#ifdef FRONTEND
#define CRCDLLIMPORT
#else
#define CRCDLLIMPORT PGDLLIMPORT
#endif

typedef uint32 pg_crc32;

#ifdef HAVE__BUILTIN_BSWAP32
#define BSWAP32(x) __builtin_bswap32(x)
#else
#define BSWAP32(x) (((x << 24) & 0xff000000) | \
					((x << 8) & 0x00ff0000) | \
					((x >> 8) & 0x0000ff00) | \
					((x >> 24) & 0x000000ff))
#endif

/*
 * CRC calculation using the CRC-32C (Castagnoli) polynomial.
 *
 * We use all-ones as the initial register contents and final bit inversion.
 * This is the same algorithm used e.g. in iSCSI. See RFC 3385 for more
 * details on the choice of polynomial.
 *
 * On big-endian systems, the intermediate value is kept in reverse byte
 * order, to avoid byte-swapping during the calculation. FIN_CRC32C reverses
 * the bytes to the final order.
 */
#define INIT_CRC32C(crc) ((crc) = 0xFFFFFFFF)
#ifdef WORDS_BIGENDIAN
#define FIN_CRC32C(crc)	((crc) = BSWAP32(crc) ^ 0xFFFFFFFF)
#else
#define FIN_CRC32C(crc)	((crc) ^= 0xFFFFFFFF)
#endif
#define COMP_CRC32C(crc, data, len)	\
	((crc) = pg_comp_crc32c((crc), (data), (len)))
#define EQ_CRC32C(c1, c2) ((c1) == (c2))

extern pg_crc32 pg_comp_crc32c(pg_crc32 crc, const void *data, size_t len);

/*
 * CRC-32, the same used e.g. in Ethernet.
 *
 * This is currently only used in ltree and hstore contrib modules. It uses
 * the same lookup table as the legacy algorithm below. New code should
 * use the Castagnoli version instead.
 */
#define INIT_TRADITIONAL_CRC32(crc) ((crc) = 0xFFFFFFFF)
#define FIN_TRADITIONAL_CRC32(crc)	((crc) ^= 0xFFFFFFFF)
#define COMP_TRADITIONAL_CRC32(crc, data, len)	\
	COMP_CRC32_NORMAL_TABLE(crc, data, len, pg_crc32_table)
#define EQ_TRADITIONAL_CRC32(c1, c2) ((c1) == (c2))

/* Sarwate's algorithm, for use with a "normal" lookup table */
#define COMP_CRC32_NORMAL_TABLE(crc, data, len, table)			  \
do {															  \
	const unsigned char *__data = (const unsigned char *) (data); \
	uint32		__len = (len); \
\
	while (__len-- > 0) \
	{ \
		int		__tab_index = ((int) (crc) ^ *__data++) & 0xFF; \
		(crc) = table[__tab_index] ^ ((crc) >> 8); \
	} \
} while (0)

/*
 * The CRC algorithm used for WAL et al in pre-9.5 versions.
 *
 * This closely resembles the normal CRC-32 algorithm, but is subtly
 * different. Using Williams' terms, we use the "normal" table, but with
 * "reflected" code. That's bogus, but it was like that for years before
 * anyone noticed. It does not correspond to any polynomial in a normal CRC
 * algorithm, so it's not clear what the error-detection properties of this
 * algorithm actually are.
 *
 * We still need to carry this around because it is used in a few on-disk
 * structures that need to be pg_upgradeable. It should not be used in new
 * code.
 */
#define INIT_LEGACY_CRC32(crc) ((crc) = 0xFFFFFFFF)
#define FIN_LEGACY_CRC32(crc)	((crc) ^= 0xFFFFFFFF)
#define COMP_LEGACY_CRC32(crc, data, len)	\
	COMP_CRC32_REFLECTED_TABLE(crc, data, len, pg_crc32_table)
#define EQ_LEGACY_CRC32(c1, c2) ((c1) == (c2))

/*
 * Sarwate's algorithm, for use with a "reflected" lookup table (but in the
 * legacy algorithm, we actually use it on a "normal" table, see above)
 */
#define COMP_CRC32_REFLECTED_TABLE(crc, data, len, table) \
do {															  \
	const unsigned char *__data = (const unsigned char *) (data); \
	uint32		__len = (len); \
\
	while (__len-- > 0) \
	{ \
		int		__tab_index = ((int) ((crc) >> 24) ^ *__data++) & 0xFF;	\
		(crc) = table[__tab_index] ^ ((crc) << 8); \
	} \
} while (0)

/* Constant tables for CRC-32C and CRC-32 polynomials */
extern CRCDLLIMPORT const uint32 pg_crc32c_table[8][256];
extern CRCDLLIMPORT const uint32 pg_crc32_table[256];

#endif   /* PG_CRC_H */