summaryrefslogtreecommitdiffstats
path: root/host/lib/property_tree.cpp
blob: 469d59e0de1f02d0ba14b4475f88afbf58df1818 (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
130
131
132
//
// Copyright 2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 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
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

#include <uhd/property_tree.hpp>
#include <uhd/types/dict.hpp>
#include <boost/foreach.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/make_shared.hpp>
#include <iostream>

class property_tree_impl : public uhd::property_tree{
public:

    property_tree_impl(const path_type &root = path_type()):
        _root(root)
    {
        _guts = boost::make_shared<tree_guts_type>();
    }

    sptr subtree(const path_type &path_) const{
        const path_type path = _root / path_;
        boost::mutex::scoped_lock lock(_guts->mutex);

        property_tree_impl *subtree = new property_tree_impl(path);
        subtree->_guts = this->_guts; //copy the guts sptr
        return sptr(subtree);
    }

    void remove(const path_type &path_){
        const path_type path = _root / path_;
        boost::mutex::scoped_lock lock(_guts->mutex);

        node_type *parent = NULL;
        node_type *node = &_guts->root;
        BOOST_FOREACH(const std::string &branch, path){
            if (not node->has_key(branch)) throw_path_not_found(path);
            parent = node;
            node = &(*node)[branch];
        }
        if (parent == NULL) throw uhd::runtime_error("Cannot uproot");
        parent->pop(path.leaf());
    }

    bool exists(const path_type &path_) const{
        const path_type path = _root / path_;
        boost::mutex::scoped_lock lock(_guts->mutex);

        node_type *node = &_guts->root;
        BOOST_FOREACH(const std::string &branch, path){
            if (not node->has_key(branch)) return false;
            node = &(*node)[branch];
        }
        return true;
    }

    std::vector<std::string> list(const path_type &path_) const{
        const path_type path = _root / path_;
        boost::mutex::scoped_lock lock(_guts->mutex);

        node_type *node = &_guts->root;
        BOOST_FOREACH(const std::string &branch, path){
            if (not node->has_key(branch)) throw_path_not_found(path);
            node = &(*node)[branch];
        }

        return node->keys();
    }

    void _create(const path_type &path_, const boost::shared_ptr<void> &prop){
        const path_type path = _root / path_;
        boost::mutex::scoped_lock lock(_guts->mutex);

        node_type *node = &_guts->root;
        BOOST_FOREACH(const std::string &branch, path){
            if (not node->has_key(branch)) (*node)[branch] = node_type();
            node = &(*node)[branch];
        }
        if (node->prop.get() != NULL) throw uhd::runtime_error("Cannot create! Property already exists at: " + path.string());
        node->prop = prop;
    }

    boost::shared_ptr<void> &_access(const path_type &path_) const{
        const path_type path = _root / path_;
        boost::mutex::scoped_lock lock(_guts->mutex);

        node_type *node = &_guts->root;
        BOOST_FOREACH(const std::string &branch, path){
            if (not node->has_key(branch)) throw_path_not_found(path);
            node = &(*node)[branch];
        }
        if (node->prop.get() == NULL) throw uhd::runtime_error("Cannot access! Property uninitialized at: " + path.string());
        return node->prop;
    }

private:
    void throw_path_not_found(const path_type &path) const{
        throw uhd::lookup_error("Path not found in tree: " + path.string());
    }

    //basic structural node element
    struct node_type : uhd::dict<std::string, node_type>{
        boost::shared_ptr<void> prop;
    };

    //tree guts which may be referenced in a subtree
    struct tree_guts_type{
        node_type root;
        boost::mutex mutex;
    };

    //members, the tree and root prefix
    boost::shared_ptr<tree_guts_type> _guts;
    const path_type _root;
};

uhd::property_tree::sptr uhd::property_tree::make(void){
    return sptr(new property_tree_impl());
}