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