Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * pqformat.h
4 : * Definitions for formatting and parsing frontend/backend messages
5 : *
6 : * Portions Copyright (c) 1996-2024, 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 4531310 : pq_writeint8(StringInfoData *pg_restrict buf, uint8 i)
47 : {
48 4531310 : uint8 ni = i;
49 :
50 : Assert(buf->len + (int) sizeof(uint8) <= buf->maxlen);
51 4531310 : memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(uint8));
52 4531310 : buf->len += sizeof(uint8);
53 4531310 : }
54 :
55 : /*
56 : * Append a [u]int16 to a StringInfo buffer, which already has enough space
57 : * preallocated.
58 : */
59 : static inline void
60 10096462 : pq_writeint16(StringInfoData *pg_restrict buf, uint16 i)
61 : {
62 10096462 : uint16 ni = pg_hton16(i);
63 :
64 : Assert(buf->len + (int) sizeof(uint16) <= buf->maxlen);
65 10096462 : memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(uint16));
66 10096462 : buf->len += sizeof(uint16);
67 10096462 : }
68 :
69 : /*
70 : * Append a [u]int32 to a StringInfo buffer, which already has enough space
71 : * preallocated.
72 : */
73 : static inline void
74 32543048 : pq_writeint32(StringInfoData *pg_restrict buf, uint32 i)
75 : {
76 32543048 : uint32 ni = pg_hton32(i);
77 :
78 : Assert(buf->len + (int) sizeof(uint32) <= buf->maxlen);
79 32543048 : memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(uint32));
80 32543048 : buf->len += sizeof(uint32);
81 32543048 : }
82 :
83 : /*
84 : * Append a [u]int64 to a StringInfo buffer, which already has enough space
85 : * preallocated.
86 : */
87 : static inline void
88 2491444 : pq_writeint64(StringInfoData *pg_restrict buf, uint64 i)
89 : {
90 2491444 : uint64 ni = pg_hton64(i);
91 :
92 : Assert(buf->len + (int) sizeof(uint64) <= buf->maxlen);
93 2491444 : memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(uint64));
94 2491444 : buf->len += sizeof(uint64);
95 2491444 : }
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 881406 : pq_writestring(StringInfoData *pg_restrict buf, const char *pg_restrict str)
109 : {
110 881406 : int slen = strlen(str);
111 : char *p;
112 :
113 881406 : p = pg_server_to_client(str, slen);
114 881406 : if (p != str) /* actual conversion has been done? */
115 34 : slen = strlen(p);
116 :
117 : Assert(buf->len + slen + 1 <= buf->maxlen);
118 :
119 881406 : memcpy(((char *pg_restrict) buf->data + buf->len), p, slen + 1);
120 881406 : buf->len += slen + 1;
121 :
122 881406 : if (p != str)
123 34 : pfree(p);
124 881406 : }
125 :
126 : /* append a binary [u]int8 to a StringInfo buffer */
127 : static inline void
128 4531310 : pq_sendint8(StringInfo buf, uint8 i)
129 : {
130 4531310 : enlargeStringInfo(buf, sizeof(uint8));
131 4531310 : pq_writeint8(buf, i);
132 4531310 : }
133 :
134 : /* append a binary [u]int16 to a StringInfo buffer */
135 : static inline void
136 7452244 : pq_sendint16(StringInfo buf, uint16 i)
137 : {
138 7452244 : enlargeStringInfo(buf, sizeof(uint16));
139 7452244 : pq_writeint16(buf, i);
140 7452244 : }
141 :
142 : /* append a binary [u]int32 to a StringInfo buffer */
143 : static inline void
144 29898830 : pq_sendint32(StringInfo buf, uint32 i)
145 : {
146 29898830 : enlargeStringInfo(buf, sizeof(uint32));
147 29898830 : pq_writeint32(buf, i);
148 29898830 : }
149 :
150 : /* append a binary [u]int64 to a StringInfo buffer */
151 : static inline void
152 2491444 : pq_sendint64(StringInfo buf, uint64 i)
153 : {
154 2491444 : enlargeStringInfo(buf, sizeof(uint64));
155 2491444 : pq_writeint64(buf, i);
156 2491444 : }
157 :
158 : /* append a binary byte to a StringInfo buffer */
159 : static inline void
160 4531280 : pq_sendbyte(StringInfo buf, uint8 byt)
161 : {
162 4531280 : pq_sendint8(buf, byt);
163 4531280 : }
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 230246 : pq_sendint(StringInfo buf, uint32 i, int b)
172 : {
173 230246 : switch (b)
174 : {
175 0 : case 1:
176 0 : pq_sendint8(buf, (uint8) i);
177 0 : break;
178 0 : case 2:
179 0 : pq_sendint16(buf, (uint16) i);
180 0 : break;
181 230246 : case 4:
182 230246 : pq_sendint32(buf, (uint32) i);
183 230246 : break;
184 0 : default:
185 0 : elog(ERROR, "unsupported integer size %d", b);
186 : break;
187 : }
188 230246 : }
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, char *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 */
|