aboutsummaryrefslogtreecommitdiff
path: root/paludis/repositories/e/e_slot_key.cc
blob: b286f7833e96bb4b57c06533e24318b5b786807c (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
124
125
126
127
128
129
/* vim: set sw=4 sts=4 et foldmethod=syntax : */

/*
 * Copyright (c) 2010, 2011 Ciaran McCreesh
 *
 * This file is part of the Paludis package manager. Paludis is free software;
 * you can redistribute it and/or modify it under the terms of the GNU General
 * Public License version 2, as published by the Free Software Foundation.
 *
 * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <paludis/repositories/e/e_slot_key.hh>
#include <paludis/repositories/e/eapi.hh>

#include <paludis/util/singleton-impl.hh>
#include <paludis/util/hashes.hh>
#include <paludis/util/singleton-impl.hh>
#include <paludis/util/pimp-impl.hh>
#include <paludis/util/make_named_values.hh>

#include <paludis/name.hh>
#include <paludis/slot.hh>

#include <tuple>
#include <unordered_map>

using namespace paludis;
using namespace paludis::erepository;

namespace
{
    struct ESlotKey :
        MetadataValueKey<Slot>
    {
        const Slot slot_value;
        const std::shared_ptr<const EAPIMetadataVariable> variable;
        const MetadataKeyType key_type;

        ESlotKey(const Slot & v, const std::shared_ptr<const EAPIMetadataVariable> & m, const MetadataKeyType t) :
            slot_value(v),
            variable(m),
            key_type(t)
        {
        }

        ~ESlotKey()
        {
        }

        virtual const Slot parse_value() const
        {
            return slot_value;
        }

        virtual const std::string raw_name() const
        {
            return variable->name();
        }

        virtual const std::string human_name() const
        {
            return variable->description();
        }

        virtual MetadataKeyType type() const
        {
            return key_type;
        }
    };

    typedef std::tuple<std::shared_ptr<const EAPIMetadataVariable>, std::string, MetadataKeyType> ESlotKeyStoreIndex;

    struct ESlotKeyStoreHash
    {
        std::size_t operator() (const ESlotKeyStoreIndex & p) const
        {
            return
                Hash<std::string>()(std::get<0>(p)->description()) ^
                std::get<0>(p)->flat_list_index() ^
                Hash<std::string>()(std::get<0>(p)->name()) ^
                Hash<std::string>()(std::get<1>(p)) ^
                static_cast<int>(std::get<2>(p));
        }
    };
}

namespace paludis
{
    template <>
    struct Imp<ESlotKeyStore>
    {
        mutable Mutex mutex;
        mutable std::unordered_map<ESlotKeyStoreIndex, std::shared_ptr<const ESlotKey>, ESlotKeyStoreHash> store;
    };
}

ESlotKeyStore::ESlotKeyStore() :
    _imp()
{
}

ESlotKeyStore::~ESlotKeyStore() = default;

const std::shared_ptr<const MetadataValueKey<Slot> >
ESlotKeyStore::fetch(
        const std::shared_ptr<const EAPIMetadataVariable> & v,
        const std::string & s,
        const MetadataKeyType t) const
{
    Lock lock(_imp->mutex);

    ESlotKeyStoreIndex x(v, s, t);
    auto i(_imp->store.find(x));
    if (i == _imp->store.end())
        i = _imp->store.insert(std::make_pair(x, std::make_shared<const ESlotKey>(make_named_values<Slot>(
                            n::match_values() = std::make_pair(s, s),
                            n::parallel_value() = s,
                            n::raw_value() = s), v, t))).first;
    return i->second;
}