1/*-------------------------------------------------------------------------
2 *
3 * pqformat.h
4 * Definitions for formatting and parsing frontend/backend messages
5 *
6 * Portions Copyright (c) 1996-2019, 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
20extern void pq_beginmessage(StringInfo buf, char msgtype);
21extern void pq_beginmessage_reuse(StringInfo buf, char msgtype);
22extern void pq_endmessage(StringInfo buf);
23extern void pq_endmessage_reuse(StringInfo buf);
24
25extern void pq_sendbytes(StringInfo buf, const char *data, int datalen);
26extern void pq_sendcountedtext(StringInfo buf, const char *str, int slen,
27 bool countincludesself);
28extern void pq_sendtext(StringInfo buf, const char *str, int slen);
29extern void pq_sendstring(StringInfo buf, const char *str);
30extern void pq_send_ascii_string(StringInfo buf, const char *str);
31extern void pq_sendfloat4(StringInfo buf, float4 f);
32extern 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 */
46static inline void
47pq_writeint8(StringInfoData *pg_restrict buf, uint8 i)
48{
49 uint8 ni = i;
50
51 Assert(buf->len + (int) sizeof(uint8) <= buf->maxlen);
52 memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(uint8));
53 buf->len += sizeof(uint8);
54}
55
56/*
57 * Append a [u]int16 to a StringInfo buffer, which already has enough space
58 * preallocated.
59 */
60static inline void
61pq_writeint16(StringInfoData *pg_restrict buf, uint16 i)
62{
63 uint16 ni = pg_hton16(i);
64
65 Assert(buf->len + (int) sizeof(uint16) <= buf->maxlen);
66 memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(uint16));
67 buf->len += sizeof(uint16);
68}
69
70/*
71 * Append a [u]int32 to a StringInfo buffer, which already has enough space
72 * preallocated.
73 */
74static inline void
75pq_writeint32(StringInfoData *pg_restrict buf, uint32 i)
76{
77 uint32 ni = pg_hton32(i);
78
79 Assert(buf->len + (int) sizeof(uint32) <= buf->maxlen);
80 memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(uint32));
81 buf->len += sizeof(uint32);
82}
83
84/*
85 * Append a [u]int64 to a StringInfo buffer, which already has enough space
86 * preallocated.
87 */
88static inline void
89pq_writeint64(StringInfoData *pg_restrict buf, uint64 i)
90{
91 uint64 ni = pg_hton64(i);
92
93 Assert(buf->len + (int) sizeof(uint64) <= buf->maxlen);
94 memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(uint64));
95 buf->len += sizeof(uint64);
96}
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 */
108static inline void
109pq_writestring(StringInfoData *pg_restrict buf, const char *pg_restrict str)
110{
111 int slen = strlen(str);
112 char *p;
113
114 p = pg_server_to_client(str, slen);
115 if (p != str) /* actual conversion has been done? */
116 slen = strlen(p);
117
118 Assert(buf->len + slen + 1 <= buf->maxlen);
119
120 memcpy(((char *pg_restrict) buf->data + buf->len), p, slen + 1);
121 buf->len += slen + 1;
122
123 if (p != str)
124 pfree(p);
125}
126
127/* append a binary [u]int8 to a StringInfo buffer */
128static inline void
129pq_sendint8(StringInfo buf, uint8 i)
130{
131 enlargeStringInfo(buf, sizeof(uint8));
132 pq_writeint8(buf, i);
133}
134
135/* append a binary [u]int16 to a StringInfo buffer */
136static inline void
137pq_sendint16(StringInfo buf, uint16 i)
138{
139 enlargeStringInfo(buf, sizeof(uint16));
140 pq_writeint16(buf, i);
141}
142
143/* append a binary [u]int32 to a StringInfo buffer */
144static inline void
145pq_sendint32(StringInfo buf, uint32 i)
146{
147 enlargeStringInfo(buf, sizeof(uint32));
148 pq_writeint32(buf, i);
149}
150
151/* append a binary [u]int64 to a StringInfo buffer */
152static inline void
153pq_sendint64(StringInfo buf, uint64 i)
154{
155 enlargeStringInfo(buf, sizeof(uint64));
156 pq_writeint64(buf, i);
157}
158
159/* append a binary byte to a StringInfo buffer */
160static inline void
161pq_sendbyte(StringInfo buf, uint8 byt)
162{
163 pq_sendint8(buf, byt);
164}
165
166/*
167 * Append a binary integer to a StringInfo buffer
168 *
169 * This function is deprecated; prefer use of the functions above.
170 */
171static inline void
172pq_sendint(StringInfo buf, uint32 i, int b)
173{
174 switch (b)
175 {
176 case 1:
177 pq_sendint8(buf, (uint8) i);
178 break;
179 case 2:
180 pq_sendint16(buf, (uint16) i);
181 break;
182 case 4:
183 pq_sendint32(buf, (uint32) i);
184 break;
185 default:
186 elog(ERROR, "unsupported integer size %d", b);
187 break;
188 }
189}
190
191
192extern void pq_begintypsend(StringInfo buf);
193extern bytea *pq_endtypsend(StringInfo buf);
194
195extern void pq_puttextmessage(char msgtype, const char *str);
196extern void pq_putemptymessage(char msgtype);
197
198extern int pq_getmsgbyte(StringInfo msg);
199extern unsigned int pq_getmsgint(StringInfo msg, int b);
200extern int64 pq_getmsgint64(StringInfo msg);
201extern float4 pq_getmsgfloat4(StringInfo msg);
202extern float8 pq_getmsgfloat8(StringInfo msg);
203extern const char *pq_getmsgbytes(StringInfo msg, int datalen);
204extern void pq_copymsgbytes(StringInfo msg, char *buf, int datalen);
205extern char *pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes);
206extern const char *pq_getmsgstring(StringInfo msg);
207extern const char *pq_getmsgrawstring(StringInfo msg);
208extern void pq_getmsgend(StringInfo msg);
209
210#endif /* PQFORMAT_H */
211