fu/c/pgtypes.c
Yorhel 8f94dd0921 pg: Initial support for receiving binary results
Just the initial framework stuff and a few types to test with.
2025-02-07 15:18:45 +01:00

72 lines
1.8 KiB
C

/* Send function, takes a Perl value and should write the binary encoded
* format into the given fustr. */
typedef void (*fupg_send_fn)(pTHX_ SV *, fustr *, void *);
/* Receive function, takes a binary string and should return a Perl value.
* libpq guarantees that the given buffer is aligned to MAXIMUM_ALIGNOF. */
typedef SV *(*fupg_recv_fn)(pTHX_ const char *, int, void *);
typedef struct {
Oid oid;
int len;
const char *name;
fupg_send_fn send;
fupg_recv_fn recv;
} fupg_type;
#define RECVFN(name) static SV *fupg_recv_##name(pTHX_ const char *buf, int buflen __attribute__((unused)), void *data __attribute__((unused)))
RECVFN(textfmt) {
return newSVpvn_utf8(buf, buflen, 1);
}
RECVFN(bool) {
return *buf ? &PL_sv_yes : &PL_sv_no;
}
RECVFN(int2) {
return newSViv((I16)__builtin_bswap16(*((U16 *)buf)));
}
RECVFN(int4) {
return newSViv((I32)__builtin_bswap32(*((U32 *)buf)));
}
RECVFN(int8) {
return newSViv((I64)__builtin_bswap64(*((U64 *)buf)));
}
#undef RECVFN
#define R(name) fupg_recv_##name
/* Sorted by oid to support binary search.
* (XXX: hash lookup might be faster, but requires codegen) */
static const fupg_type fupg_types[] = {
{ 0, 0, NULL, NULL, R(textfmt) }, /* Invalid Oid, abused for text format */
{ 16, 1, "bool", NULL, R(bool) },
{ 20, 8, "int8", NULL, R(int8) },
{ 21, 2, "int2", NULL, R(int2) },
{ 23, 4, "int4", NULL, R(int4) },
};
/* TODO: A LOT MORE TYPES */
#undef R
#define FUPG_TYPES (sizeof(fupg_types) / sizeof(fupg_type))
static const fupg_type *fupg_type_lookup(Oid oid) {
int i, b = 0, e = FUPG_TYPES-1;
while (b <= e) {
i = b + (e - b)/2;
if (fupg_types[i].oid == oid) return fupg_types+i;
if (fupg_types[i].oid < oid) b = i+1;
else e = i-1;
}
return NULL;
}