summaryrefslogtreecommitdiff
path: root/src/nw4r/g3d/res/g3d_resdict.cpp
blob: 023c23fcb84cdfe986c293462148d1e7dd37c787 (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
#include "nw4r/g3d.h" // IWYU pragma: export

#include <cstring>

namespace nw4r {
namespace g3d {

ResDicNodeData *ResDic::Get(const ResName name) const {
    u32 len = name.GetLength();
    const char *pName = name.GetName();
    const ResDicData &r = ref();

    const ResDicNodeData *c = &r.data[0];
    const ResDicNodeData *x = &r.data[c->idxLeft];

    while (c->ref > x->ref) {
        c = x;

        u32 wd = x->ref >> 3;
        u32 pos = x->ref & 7;

        if (wd < len && (pName[wd] >> pos) & 1) {
            x = &r.data[x->idxRight];
        } else {
            x = &r.data[x->idxLeft];
        }
    }

    if (name == NW4R_G3D_OFS_TO_RESNAME(&r, x->ofsString)) {
        return const_cast<ResDicNodeData *>(x);
    }

    return NULL;
}

ResDicNodeData *ResDic::Get(const char *pName, u32 len) const {
    const ResDicData &r = ref();

    const ResDicNodeData *c = &r.data[0];
    const ResDicNodeData *x = &r.data[c->idxLeft];

    while (c->ref > x->ref) {
        c = x;

        u32 wd = x->ref >> 3;
        u32 pos = x->ref & 7;

        if (wd < len && (pName[wd] >> pos) & 1) {
            x = &r.data[x->idxRight];
        } else {
            x = &r.data[x->idxLeft];
        }
    }

    if (x->ofsString != 0 && std::strcmp(pName, ofs_to_ptr<char>(x->ofsString)) == 0) {
        return const_cast<ResDicNodeData *>(x);
    }

    return NULL;
}

void *ResDic::operator[](const char *pName) const {
    if (IsValid() && pName != NULL) {
        ResDicNodeData *pNode = Get(pName, std::strlen(pName));

        if (pNode != NULL) {
            return const_cast<void *>(ofs_to_ptr_raw<void>(pNode->ofsData));
        }
    }

    return NULL;
}

void *ResDic::operator[](const ResName name) const {
    if (IsValid() && name.IsValid()) {
        ResDicNodeData *pNode = Get(name);

        if (pNode != NULL) {
            return const_cast<void *>(ofs_to_ptr_raw<void>(pNode->ofsData));
        }
    }

    return NULL;
}

s32 ResDic::GetIndex(const ResName name) const {
    if (IsValid() && name.IsValid()) {
        ResDicNodeData *pNode = Get(name);

        if (pNode != NULL) {
            return pNode - (ref().data + 1);
        }
    }

    return NOT_FOUND;
}

} // namespace g3d
} // namespace nw4r