blob: dde836ab5da32f95d06d02d2669c1be302e8e8e6 [file] [log] [blame]
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "dse.h"
#include "macros.hpp"
#include "string_ref.hpp"
#include "dse_serialization.hpp"
#include "dse_validate.hpp"
using namespace datastax::internal;
using namespace datastax::internal::enterprise;
extern "C" {
CassError cass_value_get_dse_point(const CassValue* value, cass_double_t* x, cass_double_t* y) {
const cass_byte_t* pos;
size_t size;
CassError rc = validate_data_type(value, DSE_POINT_TYPE);
if (rc != CASS_OK) return rc;
rc = cass_value_get_bytes(value, &pos, &size);
if (rc != CASS_OK) return rc;
if (size < WKB_HEADER_SIZE + 2 * sizeof(cass_double_t)) {
return CASS_ERROR_LIB_NOT_ENOUGH_DATA;
}
WkbByteOrder byte_order;
if (decode_header(pos, &byte_order) != WKB_GEOMETRY_TYPE_POINT) {
return CASS_ERROR_LIB_INVALID_DATA;
}
pos += WKB_HEADER_SIZE;
*x = decode_double(pos, byte_order);
pos += sizeof(cass_double_t);
*y = decode_double(pos, byte_order);
return CASS_OK;
}
CassError cass_value_get_dse_date_range(const CassValue* value, DseDateRange* range) {
size_t size = 0;
size_t expected_size = 0;
const char* pos = NULL;
const char* end = NULL;
DateRangeBoundType range_type;
DseDateRangeBound* first_bound = NULL;
int8_t decoded_byte = 0;
CassError rc = validate_data_type(value, DSE_DATE_RANGE_TYPE);
if (rc != CASS_OK) return rc;
rc = cass_value_get_string(value, &pos, &size);
if (rc != CASS_OK) return rc;
if (size == 0) {
return CASS_ERROR_LIB_NOT_ENOUGH_DATA;
}
end = pos + size;
// The format of the data is <type int8>[<from_time int64><from_precision int8>[<to_time
// int64><to_precision int8>]] Depending on the type of range, we may have a subset of the
// remaining fields. This translates to having 0, 1, or 2 bounds. If we have one bound, it may be
// an upper or lower bound.
range_type = static_cast<DateRangeBoundType>(*pos++);
range->is_single_date =
static_cast<cass_bool_t>(range_type == DATE_RANGE_BOUND_TYPE_SINGLE_DATE ||
range_type == DATE_RANGE_BOUND_TYPE_SINGLE_DATE_OPEN);
range->lower_bound = dse_date_range_bound_unbounded();
range->upper_bound = dse_date_range_bound_unbounded();
switch (range_type) {
case DATE_RANGE_BOUND_TYPE_BOTH_OPEN_RANGE:
case DATE_RANGE_BOUND_TYPE_SINGLE_DATE_OPEN:
expected_size = sizeof(int8_t);
break;
case DATE_RANGE_BOUND_TYPE_SINGLE_DATE:
case DATE_RANGE_BOUND_TYPE_OPEN_RANGE_HIGH:
case DATE_RANGE_BOUND_TYPE_OPEN_RANGE_LOW:
// type, from_time, from_precision
expected_size = sizeof(int8_t) + sizeof(int64_t) + sizeof(int8_t);
first_bound = (range_type == DATE_RANGE_BOUND_TYPE_OPEN_RANGE_LOW) ? &(range->upper_bound)
: &(range->lower_bound);
break;
case DATE_RANGE_BOUND_TYPE_CLOSED_RANGE:
// type, from_time, from_precision, to_time, to_precision
expected_size =
sizeof(int8_t) + sizeof(int64_t) + sizeof(int8_t) + sizeof(int64_t) + sizeof(int8_t);
first_bound = &(range->lower_bound);
break;
default:
return CASS_ERROR_LIB_INVALID_DATA;
}
if (size < expected_size) {
return CASS_ERROR_LIB_NOT_ENOUGH_DATA;
}
if (pos == end) {
return CASS_OK;
}
// We have at least one bound; write to the attribute that was chosen earlier.
pos = decode_int64(const_cast<char*>(pos), first_bound->time_ms);
pos = decode_int8(const_cast<char*>(pos), decoded_byte);
first_bound->precision = static_cast<DseDateRangePrecision>(decoded_byte);
if (pos == end) {
return CASS_OK;
}
// This is the second bound; must be upper.
pos = decode_int64(const_cast<char*>(pos), range->upper_bound.time_ms);
decode_int8(const_cast<char*>(pos), decoded_byte);
range->upper_bound.precision = static_cast<DseDateRangePrecision>(decoded_byte);
return CASS_OK;
}
} // extern "C"