summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-serialize-reflection.cpp
blob: 60ab31e17756c39d2ebdef52f6c41e712906b438 (plain)
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
// slang-serialize-reflection.cpp
#include "slang-serialize-reflection.h"

#include "slang-serialize.h"

namespace Slang
{

bool ReflectClassInfo::isSubClassOfSlow(const ThisType& super) const
{
    ReflectClassInfo const* info = this;
    while (info)
    {
        if (info == &super)
            return true;
        info = info->m_superClass;
    }
    return false;
}

#if 0

// #if'd out because produces a warning->error if not used.
static bool _checkSubClassRange(ReflectClassInfo*const* typeInfos, Index typeInfosCount)
{   
    for (Index i = 0; i < typeInfosCount; ++i)
    {
        for (Index j = 0; j < typeInfosCount; ++j)
        {
            auto a = typeInfos[i];
            auto b = typeInfos[j];
            if (a->isSubClassOf(*b) != a->isSubClassOfSlow(*b))
            {
                return false;
            }
        }
    }

    return true;
}

#endif

static uint32_t _calcRangeRec(
    ReflectClassInfo* classInfo,
    const Dictionary<const ReflectClassInfo*, List<ReflectClassInfo*>>& childMap,
    uint32_t index)
{
    classInfo->m_classId = index++;
    // Do the calc range for all the children
    auto list = childMap.tryGetValue(classInfo);

    if (list)
    {
        for (auto child : *list)
        {
            index = _calcRangeRec(child, childMap, index);
        }
    }

    classInfo->m_lastClassId = index;
    return index;
}

static ReflectClassInfo* _calcRoot(ReflectClassInfo* classInfo)
{
    while (classInfo->m_superClass)
    {
        classInfo = const_cast<ReflectClassInfo*>(classInfo->m_superClass);
    }
    return classInfo;
}


/* static */ void ReflectClassInfo::calcClassIdHierachy(
    uint32_t baseIndex,
    ReflectClassInfo* const* typeInfos,
    Index typeInfosCount)
{
    SLANG_ASSERT(typeInfosCount > 0);

    // TODO(JS):
    // Note that the calculating of the ranges could be done more efficiently by adding to an array
    // of struct { super, class }, sorting, by super classs and using a dictionary to map from class
    // it's first in list of super class use. This works for now though.

    // The root cannot be shared with another hierarchy - as doing so will mean that the range will
    // be incorrect (it would need to span both trees)
    ReflectClassInfo* root = _calcRoot(typeInfos[0]);

    // We want to produce a map from a node that holds all of it's children
    Dictionary<const ThisType*, List<ThisType*>> childMap;

    const List<ThisType*> emptyList;
    {
        for (Index i = 0; i < typeInfosCount; ++i)
        {
            auto typeInfo = typeInfos[i];
            if (typeInfo->m_superClass)
            {
                // Add to that item
                List<ThisType*>* list =
                    childMap.tryGetValueOrAdd(typeInfo->m_superClass, emptyList);
                if (!list)
                {
                    list = childMap.tryGetValue(typeInfo->m_superClass);
                }
                SLANG_ASSERT(list);
                list->add(typeInfo);
            }

            // The root should be the same for all types
            SLANG_ASSERT(_calcRoot(typeInfo) == root);
        }
    }

    // We want to recursively work out a range
    _calcRangeRec(root, childMap, baseIndex);

    // SLANG_ASSERT(_checkSubClassRange(typeInfos, typeInfoCount));
}

} // namespace Slang