1 /*
2 Copyright (c) DataStax, Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 #ifndef DATASTAX_ENTERPRISE_INTERNAL_SERIALIZATION_HPP
18 #define DATASTAX_ENTERPRISE_INTERNAL_SERIALIZATION_HPP
19
20 #include "dse.h"
21
22 #include "macros.hpp"
23 #include "serialization.hpp"
24 #include "vector.hpp"
25
26 #include <assert.h>
27 #include <stdint.h>
28 #include <string.h>
29
30 #define DSE_POINT_TYPE "org.apache.cassandra.db.marshal.PointType"
31 #define DSE_LINE_STRING_TYPE "org.apache.cassandra.db.marshal.LineStringType"
32 #define DSE_POLYGON_TYPE "org.apache.cassandra.db.marshal.PolygonType"
33 #define DSE_DATE_RANGE_TYPE "org.apache.cassandra.db.marshal.DateRangeType"
34
35 #define WKB_HEADER_SIZE (sizeof(cass_uint8_t) + sizeof(cass_uint32_t)) // Endian + Type
36 #define WKB_POLYGON_HEADER_SIZE (WKB_HEADER_SIZE + sizeof(cass_uint32_t)) // Header + Num rings
37 #define WKB_LINE_STRING_HEADER_SIZE (WKB_HEADER_SIZE + sizeof(cass_uint32_t)) // Header + Num points
38
39 namespace datastax { namespace internal { namespace enterprise {
40
41 enum DateRangeBoundType {
42 DATE_RANGE_BOUND_TYPE_SINGLE_DATE = 0,
43 DATE_RANGE_BOUND_TYPE_CLOSED_RANGE = 1,
44 DATE_RANGE_BOUND_TYPE_OPEN_RANGE_HIGH = 2,
45 DATE_RANGE_BOUND_TYPE_OPEN_RANGE_LOW = 3,
46 DATE_RANGE_BOUND_TYPE_BOTH_OPEN_RANGE = 4,
47 DATE_RANGE_BOUND_TYPE_SINGLE_DATE_OPEN = 5
48 };
49
50 enum WkbGeometryType {
51 WKB_GEOMETRY_TYPE_POINT = 1,
52 WKB_GEOMETRY_TYPE_LINESTRING = 2,
53 WKB_GEOMETRY_TYPE_POLYGON = 3,
54 WKB_GEOMETRY_TYPE_MULTIPOINT = 4,
55 WKB_GEOMETRY_TYPE_MULTILINESTRING = 5,
56 WKB_GEOMETRY_TYPE_MULTIPOLYGON = 6,
57 WKB_GEOMETRY_TYPE_GEOMETRYCOLLECTION = 7
58 };
59
60 enum WkbByteOrder { WKB_BYTE_ORDER_BIG_ENDIAN = 0, WKB_BYTE_ORDER_LITTLE_ENDIAN = 1 };
61
62 #if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || \
63 defined(__x86_64__) || defined(__amd64__)
native_byte_order()64 inline WkbByteOrder native_byte_order() { return WKB_BYTE_ORDER_LITTLE_ENDIAN; }
65 #elif defined(__BYTE_ORDER__)
native_byte_order()66 inline WkbByteOrder native_byte_order() {
67 return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ? WKB_BYTE_ORDER_BIG_ENDIAN
68 : WKB_BYTE_ORDER_LITTLE_ENDIAN;
69 }
70 #else
native_byte_order()71 inline WkbByteOrder native_byte_order() {
72 const uint32_t native_byte_order = 0x01020304;
73 return reinterpret_cast<const cass_uint8_t*>(&NATIVE_ORDER)[0] == 0x01
74 ? WKB_BYTE_ORDER_BIG_ENDIAN
75 : WKB_BYTE_ORDER_LITTLE_ENDIAN;
76 }
77 #endif
78
79 typedef Vector<cass_byte_t> Bytes;
80
81 #if defined(HAVE_BUILTIN_BSWAP32) && defined(HAVE_BUILTIN_BSWAP64)
swap_uint32(cass_uint32_t value)82 inline cass_uint32_t swap_uint32(cass_uint32_t value) { return __builtin_bswap32(value); }
83
swap_uint64(cass_uint64_t value)84 inline cass_uint64_t swap_uint64(cass_uint64_t value) { return __builtin_bswap64(value); }
85 #elif defined(_MSC_VER)
swap_uint32(cass_uint32_t value)86 inline cass_uint32_t swap_uint32(cass_uint32_t value) {
87 STATIC_ASSERT(sizeof(cass_uint32_t) == sizeof(unsigned long));
88 return _byteswap_ulong(value);
89 }
90
swap_uint64(cass_uint64_t value)91 inline cass_uint64_t swap_uint64(cass_uint64_t value) { return _byteswap_uint64(value); }
92 #else
swap_uint32(cass_uint32_t value)93 inline cass_uint32_t swap_uint32(cass_uint32_t value) {
94 value = ((value << 8) & 0xFF00FF00) | ((value >> 8) & 0xFF00FF);
95 return (value << 16) | (value >> 16);
96 }
97
swap_uint64(cass_uint64_t value)98 inline cass_uint64_t swap_uint64(cass_uint64_t value) {
99 value = ((value << 8) & 0xFF00FF00FF00FF00ULL) | ((value >> 8) & 0x00FF00FF00FF00FFULL);
100 value = ((value << 16) & 0xFFFF0000FFFF0000ULL) | ((value >> 16) & 0x0000FFFF0000FFFFULL);
101 return (value << 32) | (value >> 32);
102 }
103 #endif
104
105 template <class T>
encode(T value,size_t index,Bytes & bytes)106 inline void encode(T value, size_t index, Bytes& bytes) {
107 assert(bytes.size() >= index + sizeof(T));
108 memcpy(&bytes[index], &value, sizeof(T));
109 }
110
111 template <class T>
encode_append(T value,Bytes & bytes)112 inline void encode_append(T value, Bytes& bytes) {
113 cass_uint8_t* data = reinterpret_cast<cass_uint8_t*>(&value);
114 for (size_t i = 0; i < sizeof(T); ++i) {
115 bytes.push_back(data[i]);
116 }
117 }
118
encode_header_append(WkbGeometryType type,Bytes & bytes)119 inline void encode_header_append(WkbGeometryType type, Bytes& bytes) {
120 bytes.push_back(native_byte_order());
121 encode_append(static_cast<cass_uint32_t>(type), bytes);
122 }
123
decode_double(const cass_byte_t * bytes,WkbByteOrder byte_order)124 inline cass_double_t decode_double(const cass_byte_t* bytes, WkbByteOrder byte_order) {
125 STATIC_ASSERT(sizeof(cass_double_t) == sizeof(cass_uint64_t));
126 cass_double_t value;
127 if (byte_order != native_byte_order()) {
128 cass_uint64_t temp;
129 memcpy(&temp, bytes, sizeof(cass_uint64_t));
130 swap_uint64(temp);
131 memcpy(&value, &temp, sizeof(cass_uint64_t));
132 } else {
133 memcpy(&value, bytes, sizeof(cass_uint64_t));
134 }
135 return value;
136 }
137
decode_uint32(const cass_byte_t * bytes,WkbByteOrder byte_order)138 inline cass_uint32_t decode_uint32(const cass_byte_t* bytes, WkbByteOrder byte_order) {
139 cass_uint32_t value;
140 memcpy(&value, bytes, sizeof(cass_uint32_t));
141 if (byte_order != native_byte_order()) {
142 swap_uint32(value);
143 }
144 return value;
145 }
146
decode_header(const cass_byte_t * bytes,WkbByteOrder * byte_order)147 inline WkbGeometryType decode_header(const cass_byte_t* bytes, WkbByteOrder* byte_order) {
148 *byte_order = static_cast<WkbByteOrder>(bytes[0]);
149 return static_cast<WkbGeometryType>(decode_uint32(bytes + 1, *byte_order));
150 }
151
152 }}} // namespace datastax::internal::enterprise
153
154 #endif
155