graph_properties.cc 6.82 KB
Newer Older
Tiago Peixoto's avatar
Tiago Peixoto committed
1
2
// graph-tool -- a general graph modification and manipulation thingy
//
Tiago Peixoto's avatar
Tiago Peixoto committed
3
// Copyright (C) 2007  Tiago de Paula Peixoto <tiago@forked.de>
Tiago Peixoto's avatar
Tiago Peixoto committed
4
5
6
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
Tiago Peixoto's avatar
Tiago Peixoto committed
7
// as published by the Free Software Foundation; either version 3
Tiago Peixoto's avatar
Tiago Peixoto committed
8
9
10
11
12
13
14
15
// of the License, or (at your option) any later version.
//
// This program 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
16
17
// along with this program. If not, see <http://www.gnu.org/licenses/>.

Tiago Peixoto's avatar
Tiago Peixoto committed
18
#include "graph_properties.hh"
19
20
#include "graph_util.hh"
#include "graph.hh"
Tiago Peixoto's avatar
Tiago Peixoto committed
21

22
#include <boost/lambda/bind.hpp>
23
24
#include <boost/mpl/for_each.hpp>

25
26
27
28
29
using namespace std;
using namespace boost;
using namespace boost::lambda;
using namespace graph_tool;

30
31
namespace graph_tool
{
32

33
// global property types
34
const char* type_names[] =
35
36
37
    {"bool", "int32_t", "int64_t", "double", "long double",
     "string", "vector<bool>","vector<int32_t>", "vector<int64_t>",
     "vector<double>", "vector<long double>"};
38

39
40
// this function gets the dynamic property map inside dp which matches the given
// name and key type
41
dynamic_property_map&
42
find_property_map(const dynamic_properties& dp, string name,
43
                              const type_info& key_type)
Tiago Peixoto's avatar
Tiago Peixoto committed
44
45
{
    for(typeof(dp.begin()) iter = dp.begin(); iter != dp.end(); ++iter)
46
47
        if (iter->first == name && iter->second->key() == key_type)
            return *iter->second;
Tiago Peixoto's avatar
Tiago Peixoto committed
48

49
50
51
52
53
54
55
56
    throw property_not_found(name);
}

void GraphInterface::RemoveVertexProperty(string property)
{
    dynamic_properties_copy dp;
    try
    {
57
        dynamic_property_map& prop_map =
58
            find_property_map(_properties, property, typeid(vertex_t));
59
        for (typeof(_properties.begin()) iter = _properties.begin();
60
             iter != _properties.end(); ++iter)
61
62
        {
            if (iter->second != &prop_map)
63
                dp.insert(iter->first,
64
                          auto_ptr<dynamic_property_map>(iter->second));
65
        }
66
67
68
    }
    catch (property_not_found)
    {
69
        throw GraphException("property '" + property + "' not found");
70
71
72
73
74
75
76
77
78
    }
    _properties = dp;
}

void GraphInterface::RemoveEdgeProperty(string property)
{
    dynamic_properties_copy dp;
    try
    {
79
        dynamic_property_map& prop_map =
80
            find_property_map(_properties, property, typeid(edge_t));
81
        for (typeof(_properties.begin()) iter = _properties.begin();
82
             iter != _properties.end(); ++iter)
83
84
        {
            if (iter->second != &prop_map)
85
                dp.insert(iter->first,
86
                          auto_ptr<dynamic_property_map>(iter->second));
87
        }
88
89
90
    }
    catch (property_not_found)
    {
91
        throw GraphException("property '" + property + "' not found");
92
93
94
95
    }
    _properties = dp;
}

Tiago Peixoto's avatar
Tiago Peixoto committed
96
97
98
99
100
void GraphInterface::RemoveGraphProperty(string property)
{
    dynamic_properties_copy dp;
    try
    {
101
102
        dynamic_property_map& prop_map =
            find_property_map(_properties, property,
103
                              typeid(graph_property_tag));
104
        for (typeof(_properties.begin()) iter = _properties.begin();
105
             iter != _properties.end(); ++iter)
Tiago Peixoto's avatar
Tiago Peixoto committed
106
107
        {
            if (iter->second != &prop_map)
108
                dp.insert(iter->first,
109
                          auto_ptr<dynamic_property_map>(iter->second));
Tiago Peixoto's avatar
Tiago Peixoto committed
110
111
112
113
114
115
116
117
118
119
        }
    }
    catch (property_not_found)
    {
        throw GraphException("property '" + property + "' not found");
    }
    _properties = dp;
}


120
struct add_property_map
121
{
122
123
124
125
    template <class ValueType, class IndexMap>
    void operator()(ValueType, const string& type_name, IndexMap index,
                    const string& property_name, dynamic_properties& dp,
                    bool& found) const
126
    {
127
128
        size_t i = mpl::find<value_types,ValueType>::type::pos::value;
        if (type_name == type_names[i])
129
        {
130
131
132
            vector_property_map<ValueType, IndexMap> prop(index);
            dp.property(property_name, prop);
            found = true;
133
        }
134
    }
135
136
};

137
void GraphInterface::AddVertexProperty(string property, string type)
138
{
139
    try
Tiago Peixoto's avatar
Tiago Peixoto committed
140
    {
141
142
143
        find_property_map(_properties, property, typeid(vertex_t));
    }
    catch (property_not_found)
144
    {
145
146
        throw GraphException("A vertex property named " + property +
                             " already exists");
147
    }
148
149
150
151
152
153
154
155
156
    bool found = false;
    mpl::for_each<value_types>(lambda::bind<void>(add_property_map(),
                                                  lambda::_1, lambda::var(type),
                                                  _vertex_index,
                                                  lambda::var(property),
                                                  lambda::var(_properties), 
                                                  lambda::var(found)));
    if (!found)
        throw GraphException("Invalid property type " + type);
157
158
}

159
void GraphInterface::AddEdgeProperty(string property, string type)
160
{
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
    try
    {
        find_property_map(_properties, property, typeid(edge_t));
    }
    catch (property_not_found)
    {
        throw GraphException("An edge property named " + property +
                             " already exists");
    }
    bool found = false;
    mpl::for_each<value_types>(lambda::bind<void>(add_property_map(), 
                                                  lambda::_1, lambda::var(type),
                                                  _edge_index, 
                                                  lambda::var(property),
                                                  lambda::var(_properties),
                                                  lambda::var(found)));
    if (!found)
        throw GraphException("Invalid property type " + type);
179
180
}

181
void GraphInterface::AddGraphProperty(string property, string type)
Tiago Peixoto's avatar
Tiago Peixoto committed
182
183
{
    ConstantPropertyMap<size_t,graph_property_tag> graph_index(0);
184
    try
185
    {
186
        find_property_map(_properties, property, typeid(graph_property_tag));
187
    }
188
189
190
191
192
193
194
195
196
197
198
199
200
201
    catch (property_not_found)
    {
        throw GraphException("A graph property named " + property +
                             " already exists");
    }
    bool found = false;
    mpl::for_each<value_types>(lambda::bind<void>(add_property_map(), 
                                                  lambda::_1, lambda::var(type),
                                                  graph_index, 
                                                  lambda::var(property),
                                                  lambda::var(_properties),
                                                  lambda::var(found)));
    if (!found)
        throw GraphException("Invalid property type " + type);
Tiago Peixoto's avatar
Tiago Peixoto committed
202
203
}

204

205
} // graph_tool namespace
206