Cassandra-Client
view release on metacpan or search on metacpan
} else {
column->keyspace = unpack_string_sv(aTHX_ ptr, size, &pos);
column->table = unpack_string_sv(aTHX_ ptr, size, &pos);
}
column->name = unpack_string_sv_hash(aTHX_ ptr, size, &pos, &column->name_hash);
unpack_type(aTHX_ ptr, size, &pos, &column->type);
if (!hv_exists_ent(name_hash, column->name, column->name_hash)) {
uniq_column_count++;
hv_store_ent(name_hash, column->name, &PL_sv_undef, column->name_hash);
}
}
row_meta->uniq_column_count = uniq_column_count;
}
sv_chop(data, (char*)ptr+pos);
XSRETURN(2);
MODULE = Cassandra::Client PACKAGE = Cassandra::Client::RowMetaPtr
AV*
decode(self, data, use_hashes)
Cassandra::Client::RowMeta *self
SV *data
int use_hashes
CODE:
STRLEN size, pos;
unsigned char *ptr;
int32_t row_count;
int i, j, col_count;
struct cc_column *columns;
RETVAL = newAV();
sv_2mortal((SV*)RETVAL); /* work around a bug in perl */
ptr = (unsigned char*)SvPV(data, size);
pos = 0;
if (UNLIKELY(!ptr))
croak("Invalid input to decode()");
col_count = self->column_count;
columns = self->columns;
row_count = unpack_int(aTHX_ ptr, size, &pos);
/* This came up while fuzzing: when we have 1000000 rows but no columns, we
* just flood the memory with empty arrays/hashes. Let's just reject this
* corner case. If you need this, please contact the author! */
if (UNLIKELY(row_count > 1000 && !col_count))
croak("Refusing to decode %d rows without known column information", row_count);
for (i = 0; i < row_count; i++) {
if (use_hashes) {
HV *this_row = newHV();
av_push(RETVAL, newRV_noinc((SV*)this_row));
for (j = 0; j < col_count; j++) {
SV *decoded = newSV(0);
hv_store_ent(this_row, columns[j].name, decoded, columns[j].name_hash);
decode_cell(aTHX_ ptr, size, &pos, &columns[j].type, decoded);
}
} else {
AV *this_row = newAV();
av_push(RETVAL, newRV_noinc((SV*)this_row));
for (j = 0; j < col_count; j++) {
SV *decoded = newSV(0);
av_push(this_row, decoded);
decode_cell(aTHX_ ptr, size, &pos, &columns[j].type, decoded);
}
}
}
OUTPUT:
RETVAL
SV*
encode(self, row)
Cassandra::Client::RowMeta *self
SV* row
CODE:
int column_count, i, use_hash;
STRLEN size_estimate;
AV *row_a;
HV *row_h;
if (UNLIKELY(row == NULL))
croak("row must be passed");
if (UNLIKELY(!SvROK(row)))
croak("encode: argument must be a reference");
column_count = self->column_count;
if (SvTYPE(SvRV(row)) == SVt_PVAV) {
row_a = (AV*)SvRV(row);
use_hash = 0;
if (UNLIKELY((av_len(row_a)+1) != column_count))
croak("row encoder expected %d column(s), but got %d", column_count, ((int)av_len(row_a))+1);
} else if (SvTYPE(SvRV(row)) == SVt_PVHV) {
row_h = (HV*)SvRV(row);
use_hash = 1;
if (UNLIKELY(HvUSEDKEYS(row_h) != self->uniq_column_count))
croak("row encoder expected %d column(s), but got %d", self->uniq_column_count, (int)HvUSEDKEYS(row_h));
} else {
croak("encode: argument must be an ARRAY or HASH reference");
}
/* Rough estimate. We only use it to predict Sv size, we don't rely on it being accurate.
If we overshoot, we waste some memory, and if we undershoot we copy a bit too often. */
size_estimate = 2 + (column_count * 12);
if (size_estimate <= 0) /* overflows aren't impossible, I guess */
size_estimate = 0; /* wing it */
RETVAL = newSV(size_estimate);
sv_setpvn(RETVAL, "", 0);
pack_short(aTHX_ RETVAL, column_count);
if (!use_hash) {
for (i = 0; i < column_count; i++) {
SV **maybe_cell = av_fetch(row_a, i, 0);
if (UNLIKELY(maybe_cell == NULL))
croak("row encoder error. bailing out");
encode_cell(aTHX_ RETVAL, *maybe_cell, &self->columns[i].type);
}
} else {
for (i = 0; i < column_count; i++) {
( run in 1.139 second using v1.01-cache-2.11-cpan-2398b32b56e )