1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
#pragma once
#include "header.h"
#include <library/cpp/packedtypes/longs.h>
#include <util/generic/typetraits.h>
#include <library/cpp/microbdb/noextinfo.pb.h>
inline bool operator<(const TNoExtInfo&, const TNoExtInfo&) {
return false;
}
namespace NMicroBDB {
Y_HAS_MEMBER(TExtInfo);
template <class, bool>
struct TSelectExtInfo;
template <class T>
struct TSelectExtInfo<T, false> {
typedef TNoExtInfo TExtInfo;
};
template <class T>
struct TSelectExtInfo<T, true> {
typedef typename T::TExtInfo TExtInfo;
};
template <class T>
class TExtInfoType {
public:
static const bool Exists = THasTExtInfo<T>::value;
typedef typename TSelectExtInfo<T, Exists>::TExtInfo TResult;
};
Y_HAS_MEMBER(MakeExtKey);
template <class, class, bool>
struct TSelectMakeExtKey;
template <class TVal, class TKey>
struct TSelectMakeExtKey<TVal, TKey, false> {
static inline void Make(TKey* to, typename TExtInfoType<TKey>::TResult*, const TVal* from, const typename TExtInfoType<TVal>::TResult*) {
*to = *from;
}
};
template <class TVal, class TKey>
struct TSelectMakeExtKey<TVal, TKey, true> {
static inline void Make(TKey* to, typename TExtInfoType<TKey>::TResult* toExt, const TVal* from, const typename TExtInfoType<TVal>::TResult* fromExt) {
TVal::MakeExtKey(to, toExt, from, fromExt);
}
};
template <typename T>
inline size_t SizeOfExt(const T* rec, size_t* /*out*/ extLenSize = nullptr, size_t* /*out*/ extSize = nullptr) {
if (!TExtInfoType<T>::Exists) {
if (extLenSize)
*extLenSize = 0;
if (extSize)
*extSize = 0;
return SizeOf(rec);
} else {
size_t sz = SizeOf(rec);
i64 l;
int els = in_long(l, (const char*)rec + sz);
if (extLenSize)
*extLenSize = static_cast<size_t>(els);
if (extSize)
*extSize = static_cast<size_t>(l);
return sz;
}
}
template <class T>
bool GetExtInfo(const T* rec, typename TExtInfoType<T>::TResult* extInfo) {
Y_VERIFY(TExtInfoType<T>::Exists, "GetExtInfo should only be used with extended records");
if (!rec)
return false;
size_t els;
size_t es;
size_t s = SizeOfExt(rec, &els, &es);
const ui8* raw = (const ui8*)rec + s + els;
return extInfo->ParseFromArray(raw, es);
}
template <class T>
const ui8* GetExtInfoRaw(const T* rec, size_t* len) {
Y_VERIFY(TExtInfoType<T>::Exists, "GetExtInfo should only be used with extended records");
if (!rec) {
*len = 0;
return nullptr;
}
size_t els;
size_t es;
size_t s = SizeOfExt(rec, &els, &es);
*len = els + es;
return (const ui8*)rec + s;
}
// Compares serialized extInfo (e.g. for stable sort)
template <class T>
int CompareExtInfo(const T* a, const T* b) {
Y_VERIFY(TExtInfoType<T>::Exists, "CompareExtInfo should only be used with extended records");
size_t elsA, esA;
size_t elsB, esB;
SizeOfExt(a, &elsA, &esA);
SizeOfExt(a, &elsB, &esB);
if (esA != esB)
return esA - esB;
else
return memcmp((const ui8*)a + elsA, (const ui8*)b + elsB, esA);
}
}
using NMicroBDB::TExtInfoType;
template <class TVal, class TKey>
struct TMakeExtKey {
static const bool Exists = NMicroBDB::THasMakeExtKey<TVal>::value;
static inline void Make(TKey* to, typename TExtInfoType<TKey>::TResult* toExt, const TVal* from, const typename TExtInfoType<TVal>::TResult* fromExt) {
NMicroBDB::TSelectMakeExtKey<TVal, TKey, Exists>::Make(to, toExt, from, fromExt);
}
};
|