pg: Initial support for receiving binary results
Just the initial framework stuff and a few types to test with.
This commit is contained in:
parent
7c8473533d
commit
8f94dd0921
4 changed files with 164 additions and 34 deletions
72
c/pgtypes.c
Normal file
72
c/pgtypes.c
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/* 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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue