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