| /*------------------------------------------------------------------------- | |
| * | |
| * pqformat.h | |
| * Definitions for formatting and parsing frontend/backend messages | |
| * | |
| * Portions Copyright (c) 1996-2021, 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 char *data, int datalen); | |
| extern void pq_sendcountedtext(StringInfo buf, const char *str, int slen, | |
| bool countincludesself); | |
| 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((char *pg_restrict) (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((char *pg_restrict) (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((char *pg_restrict) (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((char *pg_restrict) (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(((char *pg_restrict) 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. | |
| */ | |
| #ifdef UNITTEST | |
| extern void | |
| pq_sendint(StringInfo buf, uint32 i, int b); | |
| #else | |
| 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; | |
| } | |
| } | |
| #endif | |
| 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, char *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 */ |