100 lines
2.0 KiB
C++
100 lines
2.0 KiB
C++
|
|
// Value handling functions
|
|
|
|
#define INT(ptr) (*((long long *) ptr))
|
|
#define REAL(ptr) (*((double *) ptr))
|
|
#define min(a,b) (a < b ? a : b)
|
|
|
|
typedef union {
|
|
long long i;
|
|
double d;
|
|
char * s;
|
|
} Val;
|
|
|
|
typedef struct {
|
|
Val val;
|
|
int is_null;
|
|
Item_result type;
|
|
unsigned long len;
|
|
int free;
|
|
} Value;
|
|
|
|
#define value_ptr(value) (value->is_null ? NULL : (char *) &value->val)
|
|
|
|
void value_init(Value * value) {
|
|
value->is_null = 1;
|
|
value->free = 0;
|
|
}
|
|
|
|
void value_free_val(Value *value) {
|
|
if (value->free) {
|
|
free(value->val.s);
|
|
value->free = 0;
|
|
}
|
|
}
|
|
|
|
void value_set_null(Value *value) {
|
|
value_free_val(value);
|
|
value->is_null = 1;
|
|
}
|
|
|
|
void value_set(Value * value, UDF_ARGS *args, int arg_index, int copy) {
|
|
char * arg = args->args[arg_index];
|
|
|
|
if (arg != NULL) {
|
|
value->is_null = 0;
|
|
value->type = args->arg_type[arg_index];
|
|
|
|
switch (value->type) {
|
|
case INT_RESULT:
|
|
value->val.i = INT(arg);
|
|
break;
|
|
case REAL_RESULT:
|
|
value->val.d = REAL(arg);
|
|
break;
|
|
default:
|
|
value->len = args->lengths[arg_index];
|
|
if (copy) {
|
|
value->free = 1;
|
|
value->val.s = (char *) malloc(value->len);
|
|
memcpy(value->val.s, arg, value->len);
|
|
} else
|
|
value->val.s = arg;
|
|
}
|
|
} else
|
|
value->is_null = 1;
|
|
}
|
|
|
|
void value_from_arg(Value * value, UDF_ARGS *args, int arg_index) {
|
|
value->free = 0;
|
|
value_set(value, args, arg_index, 0);
|
|
}
|
|
|
|
void value_copy_arg(Value * value, UDF_ARGS *args, int arg_index) {
|
|
value_free_val(value);
|
|
value_set(value, args, arg_index, 1);
|
|
}
|
|
|
|
int value_compare(Value *a, Value *b) {
|
|
int cmp;
|
|
double real_cmp;
|
|
|
|
if (!a->is_null && !b->is_null && a->type == b->type) {
|
|
switch (a->type) {
|
|
case INT_RESULT:
|
|
cmp = a->val.i - b->val.i;
|
|
break;
|
|
case REAL_RESULT:
|
|
real_cmp = a->val.d - b->val.d;
|
|
cmp = real_cmp == 0.0 ? 0 : (real_cmp > 0.0 ? 1 : -1);
|
|
break;
|
|
default: // STRING_RESULT & DECIMAL_RESULT
|
|
cmp = strncmp(a->val.s, b->val.s, min(a->len, b->len));
|
|
if (cmp == 0) cmp = a->len - b->len;
|
|
}
|
|
} else
|
|
cmp = b->is_null;
|
|
|
|
return cmp;
|
|
}
|