mirror of
https://github.com/postgres/postgres.git
synced 2026-01-26 09:41:40 +03:00
This reverts commit f0f2c0c1ae.
The original problem that led to the use of pg_restrict was that MSVC
couldn't handle plain restrict, and defining it to something else
would conflict with its __declspec(restrict) that is used in system
header files. In C11 mode, this is no longer a problem, as MSVC
handles plain restrict. This led to the commit to replace pg_restrict
with restrict. But this did not take C++ into account. Standard C++
does not have restrict, so we defined it as something else (for
example, MSVC supports __restrict). But this then again conflicts
with __declspec(restrict) in system header files. So we have to
revert this attempt. The comments are updated to clarify that the
reason for this is now C++ only.
Reported-by: Jelte Fennema-Nio <postgres@jeltef.nl>
Reviewed-by: Andres Freund <andres@anarazel.de>
Discussion: https://www.postgresql.org/message-id/CAGECzQRoD7chJP1-dneSrhxUJv%2BBRcigoGOO4UwGzaShLot2Yw%40mail.gmail.com
210 lines
5.7 KiB
C
210 lines
5.7 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* pqformat.h
|
|
* Definitions for formatting and parsing frontend/backend messages
|
|
*
|
|
* Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* src/include/libpq/pqformat.h
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#ifndef PQFORMAT_H
|
|
#define PQFORMAT_H
|
|
|
|
#include "lib/stringinfo.h"
|
|
#include "mb/pg_wchar.h"
|
|
#include "port/pg_bswap.h"
|
|
|
|
extern void pq_beginmessage(StringInfo buf, char msgtype);
|
|
extern void pq_beginmessage_reuse(StringInfo buf, char msgtype);
|
|
extern void pq_endmessage(StringInfo buf);
|
|
extern void pq_endmessage_reuse(StringInfo buf);
|
|
|
|
extern void pq_sendbytes(StringInfo buf, const void *data, int datalen);
|
|
extern void pq_sendcountedtext(StringInfo buf, const char *str, int slen);
|
|
extern void pq_sendtext(StringInfo buf, const char *str, int slen);
|
|
extern void pq_sendstring(StringInfo buf, const char *str);
|
|
extern void pq_send_ascii_string(StringInfo buf, const char *str);
|
|
extern void pq_sendfloat4(StringInfo buf, float4 f);
|
|
extern void pq_sendfloat8(StringInfo buf, float8 f);
|
|
|
|
/*
|
|
* Append a [u]int8 to a StringInfo buffer, which already has enough space
|
|
* preallocated.
|
|
*
|
|
* The use of pg_restrict allows the compiler to optimize the code based on
|
|
* the assumption that buf, buf->len, buf->data and *buf->data don't
|
|
* overlap. Without the annotation buf->len etc cannot be kept in a register
|
|
* over subsequent pq_writeintN calls.
|
|
*
|
|
* The use of StringInfoData * rather than StringInfo is due to MSVC being
|
|
* overly picky and demanding a * before a restrict.
|
|
*/
|
|
static inline void
|
|
pq_writeint8(StringInfoData *pg_restrict buf, uint8 i)
|
|
{
|
|
uint8 ni = i;
|
|
|
|
Assert(buf->len + (int) sizeof(uint8) <= buf->maxlen);
|
|
memcpy(buf->data + buf->len, &ni, sizeof(uint8));
|
|
buf->len += sizeof(uint8);
|
|
}
|
|
|
|
/*
|
|
* Append a [u]int16 to a StringInfo buffer, which already has enough space
|
|
* preallocated.
|
|
*/
|
|
static inline void
|
|
pq_writeint16(StringInfoData *pg_restrict buf, uint16 i)
|
|
{
|
|
uint16 ni = pg_hton16(i);
|
|
|
|
Assert(buf->len + (int) sizeof(uint16) <= buf->maxlen);
|
|
memcpy(buf->data + buf->len, &ni, sizeof(uint16));
|
|
buf->len += sizeof(uint16);
|
|
}
|
|
|
|
/*
|
|
* Append a [u]int32 to a StringInfo buffer, which already has enough space
|
|
* preallocated.
|
|
*/
|
|
static inline void
|
|
pq_writeint32(StringInfoData *pg_restrict buf, uint32 i)
|
|
{
|
|
uint32 ni = pg_hton32(i);
|
|
|
|
Assert(buf->len + (int) sizeof(uint32) <= buf->maxlen);
|
|
memcpy(buf->data + buf->len, &ni, sizeof(uint32));
|
|
buf->len += sizeof(uint32);
|
|
}
|
|
|
|
/*
|
|
* Append a [u]int64 to a StringInfo buffer, which already has enough space
|
|
* preallocated.
|
|
*/
|
|
static inline void
|
|
pq_writeint64(StringInfoData *pg_restrict buf, uint64 i)
|
|
{
|
|
uint64 ni = pg_hton64(i);
|
|
|
|
Assert(buf->len + (int) sizeof(uint64) <= buf->maxlen);
|
|
memcpy(buf->data + buf->len, &ni, sizeof(uint64));
|
|
buf->len += sizeof(uint64);
|
|
}
|
|
|
|
/*
|
|
* Append a null-terminated text string (with conversion) to a buffer with
|
|
* preallocated space.
|
|
*
|
|
* NB: The pre-allocated space needs to be sufficient for the string after
|
|
* converting to client encoding.
|
|
*
|
|
* NB: passed text string must be null-terminated, and so is the data
|
|
* sent to the frontend.
|
|
*/
|
|
static inline void
|
|
pq_writestring(StringInfoData *pg_restrict buf, const char *pg_restrict str)
|
|
{
|
|
int slen = strlen(str);
|
|
char *p;
|
|
|
|
p = pg_server_to_client(str, slen);
|
|
if (p != str) /* actual conversion has been done? */
|
|
slen = strlen(p);
|
|
|
|
Assert(buf->len + slen + 1 <= buf->maxlen);
|
|
|
|
memcpy(buf->data + buf->len, p, slen + 1);
|
|
buf->len += slen + 1;
|
|
|
|
if (p != str)
|
|
pfree(p);
|
|
}
|
|
|
|
/* append a binary [u]int8 to a StringInfo buffer */
|
|
static inline void
|
|
pq_sendint8(StringInfo buf, uint8 i)
|
|
{
|
|
enlargeStringInfo(buf, sizeof(uint8));
|
|
pq_writeint8(buf, i);
|
|
}
|
|
|
|
/* append a binary [u]int16 to a StringInfo buffer */
|
|
static inline void
|
|
pq_sendint16(StringInfo buf, uint16 i)
|
|
{
|
|
enlargeStringInfo(buf, sizeof(uint16));
|
|
pq_writeint16(buf, i);
|
|
}
|
|
|
|
/* append a binary [u]int32 to a StringInfo buffer */
|
|
static inline void
|
|
pq_sendint32(StringInfo buf, uint32 i)
|
|
{
|
|
enlargeStringInfo(buf, sizeof(uint32));
|
|
pq_writeint32(buf, i);
|
|
}
|
|
|
|
/* append a binary [u]int64 to a StringInfo buffer */
|
|
static inline void
|
|
pq_sendint64(StringInfo buf, uint64 i)
|
|
{
|
|
enlargeStringInfo(buf, sizeof(uint64));
|
|
pq_writeint64(buf, i);
|
|
}
|
|
|
|
/* append a binary byte to a StringInfo buffer */
|
|
static inline void
|
|
pq_sendbyte(StringInfo buf, uint8 byt)
|
|
{
|
|
pq_sendint8(buf, byt);
|
|
}
|
|
|
|
/*
|
|
* Append a binary integer to a StringInfo buffer
|
|
*
|
|
* This function is deprecated; prefer use of the functions above.
|
|
*/
|
|
static inline void
|
|
pq_sendint(StringInfo buf, uint32 i, int b)
|
|
{
|
|
switch (b)
|
|
{
|
|
case 1:
|
|
pq_sendint8(buf, (uint8) i);
|
|
break;
|
|
case 2:
|
|
pq_sendint16(buf, (uint16) i);
|
|
break;
|
|
case 4:
|
|
pq_sendint32(buf, (uint32) i);
|
|
break;
|
|
default:
|
|
elog(ERROR, "unsupported integer size %d", b);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
extern void pq_begintypsend(StringInfo buf);
|
|
extern bytea *pq_endtypsend(StringInfo buf);
|
|
|
|
extern void pq_puttextmessage(char msgtype, const char *str);
|
|
extern void pq_putemptymessage(char msgtype);
|
|
|
|
extern int pq_getmsgbyte(StringInfo msg);
|
|
extern unsigned int pq_getmsgint(StringInfo msg, int b);
|
|
extern int64 pq_getmsgint64(StringInfo msg);
|
|
extern float4 pq_getmsgfloat4(StringInfo msg);
|
|
extern float8 pq_getmsgfloat8(StringInfo msg);
|
|
extern const char *pq_getmsgbytes(StringInfo msg, int datalen);
|
|
extern void pq_copymsgbytes(StringInfo msg, void *buf, int datalen);
|
|
extern char *pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes);
|
|
extern const char *pq_getmsgstring(StringInfo msg);
|
|
extern const char *pq_getmsgrawstring(StringInfo msg);
|
|
extern void pq_getmsgend(StringInfo msg);
|
|
|
|
#endif /* PQFORMAT_H */
|