Branch data Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * pqformat.h
4 : : * Definitions for formatting and parsing frontend/backend messages
5 : : *
6 : : * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 : : * Portions Copyright (c) 1994, Regents of the University of California
8 : : *
9 : : * src/include/libpq/pqformat.h
10 : : *
11 : : *-------------------------------------------------------------------------
12 : : */
13 : : #ifndef PQFORMAT_H
14 : : #define PQFORMAT_H
15 : :
16 : : #include "lib/stringinfo.h"
17 : : #include "mb/pg_wchar.h"
18 : : #include "port/pg_bswap.h"
19 : :
20 : : extern void pq_beginmessage(StringInfo buf, char msgtype);
21 : : extern void pq_beginmessage_reuse(StringInfo buf, char msgtype);
22 : : extern void pq_endmessage(StringInfo buf);
23 : : extern void pq_endmessage_reuse(StringInfo buf);
24 : :
25 : : extern void pq_sendbytes(StringInfo buf, const void *data, int datalen);
26 : : extern void pq_sendcountedtext(StringInfo buf, const char *str, int slen);
27 : : extern void pq_sendtext(StringInfo buf, const char *str, int slen);
28 : : extern void pq_sendstring(StringInfo buf, const char *str);
29 : : extern void pq_send_ascii_string(StringInfo buf, const char *str);
30 : : extern void pq_sendfloat4(StringInfo buf, float4 f);
31 : : extern void pq_sendfloat8(StringInfo buf, float8 f);
32 : :
33 : : /*
34 : : * Append a [u]int8 to a StringInfo buffer, which already has enough space
35 : : * preallocated.
36 : : *
37 : : * The use of pg_restrict allows the compiler to optimize the code based on
38 : : * the assumption that buf, buf->len, buf->data and *buf->data don't
39 : : * overlap. Without the annotation buf->len etc cannot be kept in a register
40 : : * over subsequent pq_writeintN calls.
41 : : *
42 : : * The use of StringInfoData * rather than StringInfo is due to MSVC being
43 : : * overly picky and demanding a * before a restrict.
44 : : */
45 : : static inline void
46 : 144196 : pq_writeint8(StringInfoData *pg_restrict buf, uint8 i)
47 : : {
48 : 144196 : uint8 ni = i;
49 : :
50 [ + - ]: 144196 : Assert(buf->len + (int) sizeof(uint8) <= buf->maxlen);
51 : 144196 : memcpy(buf->data + buf->len, &ni, sizeof(uint8));
52 : 144196 : buf->len += sizeof(uint8);
53 : 144196 : }
54 : :
55 : : /*
56 : : * Append a [u]int16 to a StringInfo buffer, which already has enough space
57 : : * preallocated.
58 : : */
59 : : static inline void
60 : 439289 : pq_writeint16(StringInfoData *pg_restrict buf, uint16 i)
61 : : {
62 : 439289 : uint16 ni = pg_hton16(i);
63 : :
64 [ + - ]: 439289 : Assert(buf->len + (int) sizeof(uint16) <= buf->maxlen);
65 : 439289 : memcpy(buf->data + buf->len, &ni, sizeof(uint16));
66 : 439289 : buf->len += sizeof(uint16);
67 : 439289 : }
68 : :
69 : : /*
70 : : * Append a [u]int32 to a StringInfo buffer, which already has enough space
71 : : * preallocated.
72 : : */
73 : : static inline void
74 : 433426 : pq_writeint32(StringInfoData *pg_restrict buf, uint32 i)
75 : : {
76 : 433426 : uint32 ni = pg_hton32(i);
77 : :
78 [ + - ]: 433426 : Assert(buf->len + (int) sizeof(uint32) <= buf->maxlen);
79 : 433426 : memcpy(buf->data + buf->len, &ni, sizeof(uint32));
80 : 433426 : buf->len += sizeof(uint32);
81 : 433426 : }
82 : :
83 : : /*
84 : : * Append a [u]int64 to a StringInfo buffer, which already has enough space
85 : : * preallocated.
86 : : */
87 : : static inline void
88 : 981 : pq_writeint64(StringInfoData *pg_restrict buf, uint64 i)
89 : : {
90 : 981 : uint64 ni = pg_hton64(i);
91 : :
92 [ + - ]: 981 : Assert(buf->len + (int) sizeof(uint64) <= buf->maxlen);
93 : 981 : memcpy(buf->data + buf->len, &ni, sizeof(uint64));
94 : 981 : buf->len += sizeof(uint64);
95 : 981 : }
96 : :
97 : : /*
98 : : * Append a null-terminated text string (with conversion) to a buffer with
99 : : * preallocated space.
100 : : *
101 : : * NB: The pre-allocated space needs to be sufficient for the string after
102 : : * converting to client encoding.
103 : : *
104 : : * NB: passed text string must be null-terminated, and so is the data
105 : : * sent to the frontend.
106 : : */
107 : : static inline void
108 : 75199 : pq_writestring(StringInfoData *pg_restrict buf, const char *pg_restrict str)
109 : : {
110 : 75199 : int slen = strlen(str);
111 : 75199 : char *p;
112 : :
113 : 75199 : p = pg_server_to_client(str, slen);
114 [ + - ]: 75199 : if (p != str) /* actual conversion has been done? */
115 : 0 : slen = strlen(p);
116 : :
117 [ + - ]: 75199 : Assert(buf->len + slen + 1 <= buf->maxlen);
118 : :
119 : 75199 : memcpy(buf->data + buf->len, p, slen + 1);
120 : 75199 : buf->len += slen + 1;
121 : :
122 [ + - ]: 75199 : if (p != str)
123 : 0 : pfree(p);
124 : 75199 : }
125 : :
126 : : /* append a binary [u]int8 to a StringInfo buffer */
127 : : static inline void
128 : 144196 : pq_sendint8(StringInfo buf, uint8 i)
129 : : {
130 : 144196 : enlargeStringInfo(buf, sizeof(uint8));
131 : 144196 : pq_writeint8(buf, i);
132 : 144196 : }
133 : :
134 : : /* append a binary [u]int16 to a StringInfo buffer */
135 : : static inline void
136 : 213692 : pq_sendint16(StringInfo buf, uint16 i)
137 : : {
138 : 213692 : enlargeStringInfo(buf, sizeof(uint16));
139 : 213692 : pq_writeint16(buf, i);
140 : 213692 : }
141 : :
142 : : /* append a binary [u]int32 to a StringInfo buffer */
143 : : static inline void
144 : 207829 : pq_sendint32(StringInfo buf, uint32 i)
145 : : {
146 : 207829 : enlargeStringInfo(buf, sizeof(uint32));
147 : 207829 : pq_writeint32(buf, i);
148 : 207829 : }
149 : :
150 : : /* append a binary [u]int64 to a StringInfo buffer */
151 : : static inline void
152 : 981 : pq_sendint64(StringInfo buf, uint64 i)
153 : : {
154 : 981 : enlargeStringInfo(buf, sizeof(uint64));
155 : 981 : pq_writeint64(buf, i);
156 : 981 : }
157 : :
158 : : /* append a binary byte to a StringInfo buffer */
159 : : static inline void
160 : 144196 : pq_sendbyte(StringInfo buf, uint8 byt)
161 : : {
162 : 144196 : pq_sendint8(buf, byt);
163 : 144196 : }
164 : :
165 : : /*
166 : : * Append a binary integer to a StringInfo buffer
167 : : *
168 : : * This function is deprecated; prefer use of the functions above.
169 : : */
170 : : static inline void
171 : 0 : pq_sendint(StringInfo buf, uint32 i, int b)
172 : : {
173 [ # # # # ]: 0 : switch (b)
174 : : {
175 : : case 1:
176 : 0 : pq_sendint8(buf, (uint8) i);
177 : 0 : break;
178 : : case 2:
179 : 0 : pq_sendint16(buf, (uint16) i);
180 : 0 : break;
181 : : case 4:
182 : 0 : pq_sendint32(buf, (uint32) i);
183 : 0 : break;
184 : : default:
185 [ # # # # ]: 0 : elog(ERROR, "unsupported integer size %d", b);
186 : 0 : break;
187 : : }
188 : 0 : }
189 : :
190 : :
191 : : extern void pq_begintypsend(StringInfo buf);
192 : : extern bytea *pq_endtypsend(StringInfo buf);
193 : :
194 : : extern void pq_puttextmessage(char msgtype, const char *str);
195 : : extern void pq_putemptymessage(char msgtype);
196 : :
197 : : extern int pq_getmsgbyte(StringInfo msg);
198 : : extern unsigned int pq_getmsgint(StringInfo msg, int b);
199 : : extern int64 pq_getmsgint64(StringInfo msg);
200 : : extern float4 pq_getmsgfloat4(StringInfo msg);
201 : : extern float8 pq_getmsgfloat8(StringInfo msg);
202 : : extern const char *pq_getmsgbytes(StringInfo msg, int datalen);
203 : : extern void pq_copymsgbytes(StringInfo msg, void *buf, int datalen);
204 : : extern char *pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes);
205 : : extern const char *pq_getmsgstring(StringInfo msg);
206 : : extern const char *pq_getmsgrawstring(StringInfo msg);
207 : : extern void pq_getmsgend(StringInfo msg);
208 : :
209 : : #endif /* PQFORMAT_H */
|