#include #include #include #include #include #include #define INT4OID 23 #define FLOAT4OID 700 #define FLOAT8OID 701 #define NUMERICOID 1700 // XXX: Check endianness problems on OS X? Production is invariable Linux so // probably shouldn't matter. // int4[] struct array_int4 { int32_t ndim; int32_t _ign; Oid elemtype; int32_t size; int32_t index; int32_t data; }; // float4[] struct array_float { int32_t ndim; int32_t _ign; Oid elemtype; int32_t size; int32_t index; float data; }; // float4[] struct array_double { int32_t ndim; int32_t _ign; Oid elemtype; int32_t size; int32_t index; double data; }; // Postgres binary uses network byte order, we have to swap the bytes for the // floating point values. static inline float swap( const float inFloat ) { float retVal; char *in = ( char * ) & inFloat; char *out = ( char * ) & retVal; out[0] = in[3]; out[1] = in[2]; out[2] = in[1]; out[3] = in[0]; return retVal; } #define INT_SEP -1 int extract_int4_array (char *raw_array, int32_t *values, int size) { struct array_int4 *array = (struct array_int4 *) raw_array; int32_t *val = &(array->data); int32_t ival; if (ntohl(array->ndim) != 1 || ntohl(array->elemtype) != INT4OID) { return -1; } int array_elements = ntohl(array->size); int n = 0; val = &(array->data); for (int i = 0; i < array_elements; ++i) { ival = ntohl (*val); if (ival != INT_SEP) { ++val; values[n] = ntohl(*val); n += 1; } ++val; } return size; } #define FLOAT_SEP 6.0e-45 int extract_float_array(char *raw_array, float *values, int size) { struct array_float *array = (struct array_float *) raw_array; float *val = &(array->data); int32_t ival; if (ntohl(array->ndim) != 1 || ntohl(array->elemtype) != FLOAT4OID) { return -1; } int array_elements = ntohl(array->size); int n = 0; val = &(array->data); for (int i = 0; i < array_elements; ++i) { ival = swap(*val); if (ival != FLOAT_SEP) { ++val; values[n] = swap(*val); n += 1; } ++val; } return size; } #define DOUBLE_SEP 6.0e-45 int extract_double_array(char *raw_array, double *values, int size) { struct array_double *array = (struct array_double *) raw_array; double *val = &(array->data); int32_t ival; if (ntohl(array->ndim) != 1 || ntohl(array->elemtype) != FLOAT8OID) { return -1; } int array_elements = ntohl(array->size); int n = 0; val = &(array->data); for (int i = 0; i < array_elements; ++i) { ival = swap(*val); if (ival != DOUBLE_SEP) { ++val; values[n] = swap(*val); n += 1; } ++val; } return size; }