aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/microbdb/extinfo.h
blob: c8389e783cd066698365645a49fe3c0191d77a2a (plain) (blame)
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);
    }
};