File: esmdata.cpp

package info (click to toggle)
openmw 0.50.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 37,076 kB
  • sloc: cpp: 380,958; xml: 2,192; sh: 1,449; python: 911; makefile: 26; javascript: 5
file content (81 lines) | stat: -rw-r--r-- 2,665 bytes parent folder | download
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
#include "esmdata.hpp"
#include "lessbyid.hpp"
#include "record.hpp"

#include <components/esm/defs.hpp>
#include <components/esm3/loadacti.hpp>
#include <components/esm3/loadcont.hpp>
#include <components/esm3/loaddoor.hpp>
#include <components/esm3/loadgmst.hpp>
#include <components/esm3/loadland.hpp>
#include <components/esm3/loadstat.hpp>
#include <components/esm3/variant.hpp>
#include <components/misc/strings/lower.hpp>

#include <algorithm>
#include <stdexcept>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include <vector>

namespace EsmLoader
{
    namespace
    {
        template <class F>
        auto returnAs(F&& f)
        {
            using Result = decltype(std::forward<F>(f)(ESM::Static{}));
            if constexpr (!std::is_same_v<Result, void>)
                return Result{};
        }

        template <class T, class F>
        auto withStatic(const ESM::RefId& refId, const std::vector<T>& values, F&& f)
        {
            const auto it = std::lower_bound(values.begin(), values.end(), refId, LessById{});

            if (it == values.end() || it->mId != refId)
                return returnAs(std::forward<F>(f));

            return std::forward<F>(f)(*it);
        }

        template <class F>
        auto withStatic(const ESM::RefId& refId, ESM::RecNameInts type, const EsmData& content, F&& f)
        {
            switch (type)
            {
                case ESM::REC_ACTI:
                    return withStatic(refId, content.mActivators, std::forward<F>(f));
                case ESM::REC_CONT:
                    return withStatic(refId, content.mContainers, std::forward<F>(f));
                case ESM::REC_DOOR:
                    return withStatic(refId, content.mDoors, std::forward<F>(f));
                case ESM::REC_STAT:
                    return withStatic(refId, content.mStatics, std::forward<F>(f));
                default:
                    break;
            }

            return returnAs(std::forward<F>(f));
        }
    }

    EsmData::~EsmData() {}

    std::string_view getModel(const EsmData& content, const ESM::RefId& refId, ESM::RecNameInts type)
    {
        return withStatic(refId, type, content, [](const auto& v) { return std::string_view(v.mModel); });
    }

    ESM::Variant getGameSetting(const std::vector<ESM::GameSetting>& records, std::string_view id)
    {
        auto it = std::lower_bound(records.begin(), records.end(), id, LessById{});
        if (it == records.end() || it->mId != id)
            throw std::runtime_error("Game settings \"" + std::string(id) + "\" is not found");
        return it->mValue;
    }
}