File: node.hpp

package info (click to toggle)
ares 126-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 32,600 kB
  • sloc: cpp: 356,508; ansic: 20,394; makefile: 16; sh: 2
file content (147 lines) | stat: -rw-r--r-- 5,755 bytes parent folder | download
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#pragma once

namespace nall::Markup {

struct Node;
struct ManagedNode;
using SharedNode = shared_pointer<ManagedNode>;

struct ManagedNode {
  ManagedNode() = default;
  ManagedNode(const string& name) : _name(name) {}
  ManagedNode(const string& name, const string& value) : _name(name), _value(value) {}

  auto clone() const -> SharedNode {
    SharedNode clone{new ManagedNode(_name, _value)};
    for(auto& child : _children) {
      clone->_children.append(child->clone());
    }
    return clone;
  }

  auto copy(SharedNode source) -> void {
    _name = source->_name;
    _value = source->_value;
    _metadata = source->_metadata;
    _children.reset();
    for(auto child : source->_children) {
      _children.append(child->clone());
    }
  }

protected:
  string _name;
  string _value;
  uintptr _metadata = 0;
  vector<SharedNode> _children;

  auto _evaluate(string query) const -> bool;
  auto _find(const string& query) const -> vector<Node>;
  auto _lookup(const string& path) const -> Node;
  auto _create(const string& path) -> Node;

  friend class Node;
};

struct Node {
  Node() : shared(new ManagedNode) {}
  Node(const SharedNode& source) : shared(source ? source : new ManagedNode) {}
  Node(const nall::string& name) : shared(new ManagedNode(name)) {}
  Node(const nall::string& name, const nall::string& value) : shared(new ManagedNode(name, value)) {}

  auto unique() const -> bool { return shared.unique(); }
  auto clone() const -> Node { return shared->clone(); }
  auto copy(Node source) -> void { return shared->copy(source.shared); }

  explicit operator bool() const { return shared->_name || shared->_children; }
  auto name() const -> nall::string { return shared->_name; }
  auto value() const -> nall::string { return shared->_value; }

  auto value(nall::string& target) const -> bool { if(shared) target = string(); return (bool)shared; }
  auto value(bool& target) const -> bool { if(shared) target = boolean(); return (bool)shared; }
  auto value(s32& target) const -> bool { if(shared) target = integer(); return (bool)shared; }
  auto value(u32& target) const -> bool { if(shared) target = natural(); return (bool)shared; }
  auto value(f64& target) const -> bool { if(shared) target = real(); return (bool)shared; }

  auto text() const -> nall::string { return value().strip(); }
  auto string() const -> nall::string { return value().strip(); }
  auto boolean() const -> bool { return text() == "true"; }
  auto integer() const -> s64 { return text().integer(); }
  auto natural() const -> u64 { return text().natural(); }
  auto real() const -> f64 { return text().real(); }

  auto text(const nall::string& fallback) const -> nall::string { return bool(*this) ? text() : fallback; }
  auto string(const nall::string& fallback) const -> nall::string { return bool(*this) ? string() : fallback; }
  auto boolean(bool fallback) const -> bool { return bool(*this) ? boolean() : fallback; }
  auto integer(s64 fallback) const -> s64 { return bool(*this) ? integer() : fallback; }
  auto natural(u64 fallback) const -> u64 { return bool(*this) ? natural() : fallback; }
  auto real(f64 fallback) const -> f64 { return bool(*this) ? real() : fallback; }

  auto setName(const nall::string& name = "") -> Node& { shared->_name = name; return *this; }
  auto setValue(const nall::string& value = "") -> Node& { shared->_value = value; return *this; }

  auto reset() -> void { shared->_children.reset(); }
  auto size() const -> u32 { return shared->_children.size(); }

  auto prepend(const Node& node) -> void { shared->_children.prepend(node.shared); }
  auto append(const Node& node) -> void { shared->_children.append(node.shared); }
  auto remove(const Node& node) -> bool {
    for(auto n : range(size())) {
      if(node.shared == shared->_children[n]) {
        return shared->_children.remove(n), true;
      }
    }
    return false;
  }

  auto insert(u32 position, const Node& node) -> bool {
    if(position > size()) return false;  //used > instead of >= to allow indexed-equivalent of append()
    return shared->_children.insert(position, node.shared), true;
  }

  auto remove(u32 position) -> bool {
    if(position >= size()) return false;
    return shared->_children.remove(position), true;
  }

  auto swap(u32 x, u32 y) -> bool {
    if(x >= size() || y >= size()) return false;
    return std::swap(shared->_children[x], shared->_children[y]), true;
  }

  auto sort(function<bool (Node, Node)> comparator = [](auto x, auto y) {
    return nall::string::compare(x.shared->_name, y.shared->_name) < 0;
  }) -> void {
    nall::sort(shared->_children.data(), shared->_children.size(), [&](auto x, auto y) {
      return comparator(x, y);  //this call converts SharedNode objects to Node objects
    });
  }

  auto operator[](s32 position) -> Node {
    if(position >= size()) return {};
    return shared->_children[position];
  }

  auto operator[](const nall::string& path) const -> Node { return shared->_lookup(path); }
  auto operator()(const nall::string& path) -> Node { return shared->_create(path); }
  auto find(const nall::string& query) const -> vector<Node> { return shared->_find(query); }

  struct iterator {
    auto operator*() -> Node { return {source.shared->_children[position]}; }
    auto operator!=(const iterator& source) const -> bool { return position != source.position; }
    auto operator++() -> iterator& { return position++, *this; }
    iterator(const Node& source, u32 position) : source(source), position(position) {}

  private:
    const Node& source;
    u32 position;
  };

  auto begin() const -> iterator { return iterator(*this, 0); }
  auto end() const -> iterator { return iterator(*this, size()); }

protected:
  SharedNode shared;
};

}