1 #include <internal/nodes/config_node_root.hpp>
2 #include <hocon/config_exception.hpp>
3 #include <internal/nodes/config_node_array.hpp>
4 #include <internal/nodes/config_node_object.hpp>
5 #include <internal/path_parser.hpp>
6 #include <leatherman/locale/locale.hpp>
7 
8 // Mark string for translation (alias for leatherman::locale::format)
9 using leatherman::locale::_;
10 
11 using namespace std;
12 
13 namespace hocon {
14 
config_node_root(shared_node_list children,shared_origin origin)15     config_node_root::config_node_root(shared_node_list children, shared_origin origin) :
16             config_node_complex_value(move(children)), _origin(move(origin)) { }
17 
new_node(shared_node_list nodes) const18     shared_ptr<const config_node_complex_value> config_node_root::new_node(shared_node_list nodes) const {
19         throw config_exception(_("Tried to indent a root node"));
20     }
21 
value() const22     shared_ptr<const config_node_complex_value> config_node_root::value() const {
23         for (auto&& node : children()) {
24             if (auto complex = dynamic_pointer_cast<const config_node_complex_value>(node)) {
25                 return complex;
26             }
27         }
28         throw config_exception(_("Root node did not contain a value"));
29     }
30 
set_value(std::string desired_path,shared_node_value value,config_syntax flavor) const31     shared_ptr<const config_node_root> config_node_root::set_value(std::string desired_path,
32                                                                    shared_node_value value,
33                                                                    config_syntax flavor) const
34     {
35         shared_node_list children_copy = children();
36         for (size_t i = 0; i < children_copy.size(); i++) {
37             auto node = children_copy[i];
38             if (dynamic_pointer_cast<const config_node_complex_value>(node)) {
39                 if (dynamic_pointer_cast<const config_node_array>(node)) {
40                     throw config_exception(_("The config document had an array at the root level, and values cannot be modified inside an array"));
41                 } else if (auto object = dynamic_pointer_cast<const config_node_object>(node)) {
42                     if (value == nullptr) {
43                         children_copy[i] = object->remove_value_on_path(desired_path, flavor);
44                     } else {
45                         children_copy[i] = object->set_value_on_path(desired_path, value, flavor);
46                     }
47                     return make_shared<config_node_root>(children_copy, _origin);
48                 }
49             }
50         }
51         throw config_exception(_("Root node did not contain a value"));
52     }
53 
has_value(string desired_path) const54     bool config_node_root::has_value(string desired_path) const {
55         path raw_path = path_parser::parse_path(desired_path);
56         shared_node_list children_copy = children();
57         for (size_t i = 0; i < children_copy.size(); i++) {
58             auto node = children_copy[i];
59             if (dynamic_pointer_cast<const config_node_complex_value>(node)) {
60                 if (dynamic_pointer_cast<const config_node_array>(node)) {
61                     throw config_exception(_("The config document had an array at the root level, and values cannot be modified inside an array"));
62                 } else if (auto object = dynamic_pointer_cast<const config_node_object>(node)) {
63                     return object->has_value(raw_path);
64                 }
65             }
66         }
67         throw config_exception(_("Root node did not contain a value"));
68     }
69 
70 }  // namespace hocon
71