PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
char.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * char.c
4 * Functions for the built-in type "char" (not to be confused with
5 * bpchar, which is the SQL CHAR(n) type).
6 *
7 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
9 *
10 *
11 * IDENTIFICATION
12 * src/backend/utils/adt/char.c
13 *
14 *-------------------------------------------------------------------------
15 */
16#include "postgres.h"
17
18#include <limits.h>
19
20#include "libpq/pqformat.h"
21#include "utils/fmgrprotos.h"
22#include "varatt.h"
23
24#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
25#define TOOCTAL(c) ((c) + '0')
26#define FROMOCTAL(c) ((unsigned char) (c) - '0')
27
28
29/*****************************************************************************
30 * USER I/O ROUTINES *
31 *****************************************************************************/
32
33/*
34 * charin - converts "x" to 'x'
35 *
36 * This accepts the formats charout produces. If we have multibyte input
37 * that is not in the form '\ooo', then we take its first byte as the value
38 * and silently discard the rest; this is a backwards-compatibility provision.
39 */
42{
43 char *ch = PG_GETARG_CSTRING(0);
44
45 if (strlen(ch) == 4 && ch[0] == '\\' &&
46 ISOCTAL(ch[1]) && ISOCTAL(ch[2]) && ISOCTAL(ch[3]))
47 PG_RETURN_CHAR((FROMOCTAL(ch[1]) << 6) +
48 (FROMOCTAL(ch[2]) << 3) +
49 FROMOCTAL(ch[3]));
50 /* This will do the right thing for a zero-length input string */
51 PG_RETURN_CHAR(ch[0]);
52}
53
54/*
55 * charout - converts 'x' to "x"
56 *
57 * The possible output formats are:
58 * 1. 0x00 is represented as an empty string.
59 * 2. 0x01..0x7F are represented as a single ASCII byte.
60 * 3. 0x80..0xFF are represented as \ooo (backslash and 3 octal digits).
61 * Case 3 is meant to match the traditional "escape" format of bytea.
62 */
65{
66 char ch = PG_GETARG_CHAR(0);
67 char *result = (char *) palloc(5);
68
69 if (IS_HIGHBIT_SET(ch))
70 {
71 result[0] = '\\';
72 result[1] = TOOCTAL(((unsigned char) ch) >> 6);
73 result[2] = TOOCTAL((((unsigned char) ch) >> 3) & 07);
74 result[3] = TOOCTAL(((unsigned char) ch) & 07);
75 result[4] = '\0';
76 }
77 else
78 {
79 /* This produces acceptable results for 0x00 as well */
80 result[0] = ch;
81 result[1] = '\0';
82 }
83 PG_RETURN_CSTRING(result);
84}
85
86/*
87 * charrecv - converts external binary format to char
88 *
89 * The external representation is one byte, with no character set
90 * conversion. This is somewhat dubious, perhaps, but in many
91 * cases people use char for a 1-byte binary type.
92 */
95{
97
99}
100
101/*
102 * charsend - converts char to binary format
103 */
104Datum
106{
107 char arg1 = PG_GETARG_CHAR(0);
109
111 pq_sendbyte(&buf, arg1);
113}
114
115/*****************************************************************************
116 * PUBLIC ROUTINES *
117 *****************************************************************************/
118
119/*
120 * NOTE: comparisons are done as though char is unsigned (uint8).
121 * Conversions to and from integer are done as though char is signed (int8).
122 *
123 * You wanted consistency?
124 */
125
126Datum
128{
129 char arg1 = PG_GETARG_CHAR(0);
130 char arg2 = PG_GETARG_CHAR(1);
131
132 PG_RETURN_BOOL(arg1 == arg2);
133}
134
135Datum
137{
138 char arg1 = PG_GETARG_CHAR(0);
139 char arg2 = PG_GETARG_CHAR(1);
140
141 PG_RETURN_BOOL(arg1 != arg2);
142}
143
144Datum
146{
147 char arg1 = PG_GETARG_CHAR(0);
148 char arg2 = PG_GETARG_CHAR(1);
149
150 PG_RETURN_BOOL((uint8) arg1 < (uint8) arg2);
151}
152
153Datum
155{
156 char arg1 = PG_GETARG_CHAR(0);
157 char arg2 = PG_GETARG_CHAR(1);
158
159 PG_RETURN_BOOL((uint8) arg1 <= (uint8) arg2);
160}
161
162Datum
164{
165 char arg1 = PG_GETARG_CHAR(0);
166 char arg2 = PG_GETARG_CHAR(1);
167
168 PG_RETURN_BOOL((uint8) arg1 > (uint8) arg2);
169}
170
171Datum
173{
174 char arg1 = PG_GETARG_CHAR(0);
175 char arg2 = PG_GETARG_CHAR(1);
176
177 PG_RETURN_BOOL((uint8) arg1 >= (uint8) arg2);
178}
179
180
181Datum
183{
184 char arg1 = PG_GETARG_CHAR(0);
185
186 PG_RETURN_INT32((int32) ((int8) arg1));
187}
188
189Datum
191{
192 int32 arg1 = PG_GETARG_INT32(0);
193
194 if (arg1 < SCHAR_MIN || arg1 > SCHAR_MAX)
196 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
197 errmsg("\"char\" out of range")));
198
199 PG_RETURN_CHAR((int8) arg1);
200}
201
202
203Datum
205{
206 text *arg1 = PG_GETARG_TEXT_PP(0);
207 char *ch = VARDATA_ANY(arg1);
208 char result;
209
210 /*
211 * Conversion rules are the same as in charin(), but here we need to
212 * handle the empty-string case honestly.
213 */
214 if (VARSIZE_ANY_EXHDR(arg1) == 4 && ch[0] == '\\' &&
215 ISOCTAL(ch[1]) && ISOCTAL(ch[2]) && ISOCTAL(ch[3]))
216 result = (FROMOCTAL(ch[1]) << 6) +
217 (FROMOCTAL(ch[2]) << 3) +
218 FROMOCTAL(ch[3]);
219 else if (VARSIZE_ANY_EXHDR(arg1) > 0)
220 result = ch[0];
221 else
222 result = '\0';
223
224 PG_RETURN_CHAR(result);
225}
226
227Datum
229{
230 char arg1 = PG_GETARG_CHAR(0);
231 text *result = palloc(VARHDRSZ + 4);
232
233 /*
234 * Conversion rules are the same as in charout(), but here we need to be
235 * honest about converting 0x00 to an empty string.
236 */
237 if (IS_HIGHBIT_SET(arg1))
238 {
239 SET_VARSIZE(result, VARHDRSZ + 4);
240 (VARDATA(result))[0] = '\\';
241 (VARDATA(result))[1] = TOOCTAL(((unsigned char) arg1) >> 6);
242 (VARDATA(result))[2] = TOOCTAL((((unsigned char) arg1) >> 3) & 07);
243 (VARDATA(result))[3] = TOOCTAL(((unsigned char) arg1) & 07);
244 }
245 else if (arg1 != '\0')
246 {
247 SET_VARSIZE(result, VARHDRSZ + 1);
248 *(VARDATA(result)) = arg1;
249 }
250 else
251 SET_VARSIZE(result, VARHDRSZ);
252
253 PG_RETURN_TEXT_P(result);
254}
uint8_t uint8
Definition: c.h:500
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1126
#define VARHDRSZ
Definition: c.h:663
int8_t int8
Definition: c.h:496
int32_t int32
Definition: c.h:498
Datum charge(PG_FUNCTION_ARGS)
Definition: char.c:172
Datum charle(PG_FUNCTION_ARGS)
Definition: char.c:154
Datum chareq(PG_FUNCTION_ARGS)
Definition: char.c:127
Datum charrecv(PG_FUNCTION_ARGS)
Definition: char.c:94
Datum chargt(PG_FUNCTION_ARGS)
Definition: char.c:163
Datum chartoi4(PG_FUNCTION_ARGS)
Definition: char.c:182
#define ISOCTAL(c)
Definition: char.c:24
Datum text_char(PG_FUNCTION_ARGS)
Definition: char.c:204
Datum charne(PG_FUNCTION_ARGS)
Definition: char.c:136
Datum charin(PG_FUNCTION_ARGS)
Definition: char.c:41
Datum charsend(PG_FUNCTION_ARGS)
Definition: char.c:105
#define FROMOCTAL(c)
Definition: char.c:26
#define TOOCTAL(c)
Definition: char.c:25
Datum charlt(PG_FUNCTION_ARGS)
Definition: char.c:145
Datum charout(PG_FUNCTION_ARGS)
Definition: char.c:64
Datum char_text(PG_FUNCTION_ARGS)
Definition: char.c:228
Datum i4tochar(PG_FUNCTION_ARGS)
Definition: char.c:190
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define PG_GETARG_CHAR(n)
Definition: fmgr.h:273
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_CHAR(x)
Definition: fmgr.h:358
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
void * palloc(Size size)
Definition: mcxt.c:1317
static char * buf
Definition: pg_test_fsync.c:72
uintptr_t Datum
Definition: postgres.h:69
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
int pq_getmsgbyte(StringInfo msg)
Definition: pqformat.c:399
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
static void pq_sendbyte(StringInfo buf, uint8 byt)
Definition: pqformat.h:160
StringInfoData * StringInfo
Definition: stringinfo.h:54
Definition: c.h:658
#define VARDATA(PTR)
Definition: varatt.h:278
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317