Statistics
| Branch: | Tag: | Revision:

root / host / lib / property_tree.cpp @ fac15db5

History | View | Annotate | Download (6.13 KB)

1 ba2a6b4b Josh Blum
//
2
// Copyright 2011 Ettus Research LLC
3
//
4
// This program is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
//
17
18
#include <uhd/property_tree.hpp>
19
#include <uhd/types/dict.hpp>
20
#include <boost/foreach.hpp>
21
#include <boost/thread/mutex.hpp>
22 aa6b340f Josh Blum
#include <boost/make_shared.hpp>
23 ba2a6b4b Josh Blum
#include <iostream>
24
25 da40a1ae Josh Blum
using namespace uhd;
26
27
/***********************************************************************
28
 * Helper function to iterate through paths
29
 **********************************************************************/
30
#include <boost/tokenizer.hpp>
31
#define path_tokenizer(path) \
32
    boost::tokenizer<boost::char_separator<char> > \
33
    (path, boost::char_separator<char>("/"))
34
35
/***********************************************************************
36
 * Property path implementation wrapper
37
 **********************************************************************/
38
fs_path::fs_path(void): std::string(){}
39
fs_path::fs_path(const char *p): std::string(p){}
40
fs_path::fs_path(const std::string &p): std::string(p){}
41
42
std::string fs_path::leaf(void) const{
43
    const size_t pos = this->rfind("/");
44
    if (pos == std::string::npos) return *this;
45
    return this->substr(pos+1);
46
}
47
48
fs_path fs_path::branch_path(void) const{
49
    const size_t pos = this->rfind("/");
50
    if (pos == std::string::npos) return *this;
51
    return fs_path(this->substr(0, pos));
52
}
53
54
fs_path uhd::operator/(const fs_path &lhs, const fs_path &rhs){
55
    //strip trailing slash on left-hand-side
56
    if (not lhs.empty() and *lhs.rbegin() == '/'){
57
        return fs_path(lhs.substr(0, lhs.size()-1)) / rhs;
58
    }
59
60
    //strip leading slash on right-hand-side
61
    if (not rhs.empty() and *rhs.begin() == '/'){
62
        return lhs / fs_path(rhs.substr(1));
63
    }
64
65
    return fs_path(lhs + "/" + rhs);
66
}
67
68
/***********************************************************************
69
 * Property tree implementation
70
 **********************************************************************/
71 ba2a6b4b Josh Blum
class property_tree_impl : public uhd::property_tree{
72
public:
73
74 da40a1ae Josh Blum
    property_tree_impl(const fs_path &root = fs_path()):
75 aa6b340f Josh Blum
        _root(root)
76
    {
77
        _guts = boost::make_shared<tree_guts_type>();
78
    }
79
80 da40a1ae Josh Blum
    sptr subtree(const fs_path &path_) const{
81
        const fs_path path = _root / path_;
82 aa6b340f Josh Blum
        boost::mutex::scoped_lock lock(_guts->mutex);
83
84
        property_tree_impl *subtree = new property_tree_impl(path);
85
        subtree->_guts = this->_guts; //copy the guts sptr
86
        return sptr(subtree);
87
    }
88
89 da40a1ae Josh Blum
    void remove(const fs_path &path_){
90
        const fs_path path = _root / path_;
91 aa6b340f Josh Blum
        boost::mutex::scoped_lock lock(_guts->mutex);
92 ba2a6b4b Josh Blum
93
        node_type *parent = NULL;
94 aa6b340f Josh Blum
        node_type *node = &_guts->root;
95 da40a1ae Josh Blum
        BOOST_FOREACH(const std::string &name, path_tokenizer(path)){
96 22319dfc Josh Blum
            if (not node->has_key(name)) throw_path_not_found(path);
97 ba2a6b4b Josh Blum
            parent = node;
98 22319dfc Josh Blum
            node = &(*node)[name];
99 ba2a6b4b Josh Blum
        }
100
        if (parent == NULL) throw uhd::runtime_error("Cannot uproot");
101 da40a1ae Josh Blum
        parent->pop(fs_path(path.leaf()));
102 ba2a6b4b Josh Blum
    }
103
104 da40a1ae Josh Blum
    bool exists(const fs_path &path_) const{
105
        const fs_path path = _root / path_;
106 aa6b340f Josh Blum
        boost::mutex::scoped_lock lock(_guts->mutex);
107 ba2a6b4b Josh Blum
108 aa6b340f Josh Blum
        node_type *node = &_guts->root;
109 da40a1ae Josh Blum
        BOOST_FOREACH(const std::string &name, path_tokenizer(path)){
110 22319dfc Josh Blum
            if (not node->has_key(name)) return false;
111
            node = &(*node)[name];
112 ba2a6b4b Josh Blum
        }
113
        return true;
114
    }
115
116 da40a1ae Josh Blum
    std::vector<std::string> list(const fs_path &path_) const{
117
        const fs_path path = _root / path_;
118 aa6b340f Josh Blum
        boost::mutex::scoped_lock lock(_guts->mutex);
119 ba2a6b4b Josh Blum
120 aa6b340f Josh Blum
        node_type *node = &_guts->root;
121 da40a1ae Josh Blum
        BOOST_FOREACH(const std::string &name, path_tokenizer(path)){
122 22319dfc Josh Blum
            if (not node->has_key(name)) throw_path_not_found(path);
123
            node = &(*node)[name];
124 ba2a6b4b Josh Blum
        }
125
126 3a618751 Josh Blum
        return node->keys();
127 ba2a6b4b Josh Blum
    }
128
129 da40a1ae Josh Blum
    void _create(const fs_path &path_, const boost::shared_ptr<void> &prop){
130
        const fs_path path = _root / path_;
131 aa6b340f Josh Blum
        boost::mutex::scoped_lock lock(_guts->mutex);
132 ba2a6b4b Josh Blum
133 aa6b340f Josh Blum
        node_type *node = &_guts->root;
134 da40a1ae Josh Blum
        BOOST_FOREACH(const std::string &name, path_tokenizer(path)){
135 22319dfc Josh Blum
            if (not node->has_key(name)) (*node)[name] = node_type();
136
            node = &(*node)[name];
137 ba2a6b4b Josh Blum
        }
138 da40a1ae Josh Blum
        if (node->prop.get() != NULL) throw uhd::runtime_error("Cannot create! Property already exists at: " + path);
139 ba2a6b4b Josh Blum
        node->prop = prop;
140
    }
141
142 da40a1ae Josh Blum
    boost::shared_ptr<void> &_access(const fs_path &path_) const{
143
        const fs_path path = _root / path_;
144 aa6b340f Josh Blum
        boost::mutex::scoped_lock lock(_guts->mutex);
145 ba2a6b4b Josh Blum
146 aa6b340f Josh Blum
        node_type *node = &_guts->root;
147 da40a1ae Josh Blum
        BOOST_FOREACH(const std::string &name, path_tokenizer(path)){
148 22319dfc Josh Blum
            if (not node->has_key(name)) throw_path_not_found(path);
149
            node = &(*node)[name];
150 ba2a6b4b Josh Blum
        }
151 da40a1ae Josh Blum
        if (node->prop.get() == NULL) throw uhd::runtime_error("Cannot access! Property uninitialized at: " + path);
152 ba2a6b4b Josh Blum
        return node->prop;
153
    }
154
155
private:
156 da40a1ae Josh Blum
    void throw_path_not_found(const fs_path &path) const{
157
        throw uhd::lookup_error("Path not found in tree: " + path);
158 ba2a6b4b Josh Blum
    }
159
160 aa6b340f Josh Blum
    //basic structural node element
161 ba2a6b4b Josh Blum
    struct node_type : uhd::dict<std::string, node_type>{
162 d2f79c07 Josh Blum
        boost::shared_ptr<void> prop;
163 aa6b340f Josh Blum
    };
164
165
    //tree guts which may be referenced in a subtree
166
    struct tree_guts_type{
167
        node_type root;
168
        boost::mutex mutex;
169
    };
170 ba2a6b4b Josh Blum
171 aa6b340f Josh Blum
    //members, the tree and root prefix
172
    boost::shared_ptr<tree_guts_type> _guts;
173 da40a1ae Josh Blum
    const fs_path _root;
174 ba2a6b4b Josh Blum
};
175
176 da40a1ae Josh Blum
/***********************************************************************
177
 * Property tree factory
178
 **********************************************************************/
179 ba2a6b4b Josh Blum
uhd::property_tree::sptr uhd::property_tree::make(void){
180
    return sptr(new property_tree_impl());
181
}