File indexing completed on 2025-07-12 08:28:43
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_PROPERTY_TREE_STRING_PATH_HPP_INCLUDED
0012 #define BOOST_PROPERTY_TREE_STRING_PATH_HPP_INCLUDED
0013
0014 #include <boost/property_tree/ptree_fwd.hpp>
0015 #include <boost/property_tree/id_translator.hpp>
0016 #include <boost/property_tree/exceptions.hpp>
0017 #include <boost/property_tree/detail/ptree_utils.hpp>
0018
0019 #include <boost/static_assert.hpp>
0020 #include <boost/assert.hpp>
0021 #include <boost/type_traits/is_same.hpp>
0022 #include <boost/optional/optional.hpp>
0023 #include <boost/throw_exception.hpp>
0024 #include <algorithm>
0025 #include <string>
0026 #include <iterator>
0027
0028 namespace boost { namespace property_tree
0029 {
0030 namespace detail
0031 {
0032 template <typename Sequence, typename Iterator>
0033 void append_and_preserve_iter(Sequence &s, const Sequence &r,
0034 Iterator &, std::forward_iterator_tag)
0035 {
0036
0037
0038 s.insert(s.end(), r.begin(), r.end());
0039 }
0040 template <typename Sequence, typename Iterator>
0041 void append_and_preserve_iter(Sequence &s, const Sequence &r,
0042 Iterator &it,
0043 std::random_access_iterator_tag)
0044 {
0045
0046 typename std::iterator_traits<Iterator>::difference_type idx =
0047 it - s.begin();
0048 s.insert(s.end(), r.begin(), r.end());
0049 it = s.begin() + idx;
0050 }
0051
0052 template <typename Sequence>
0053 inline std::string dump_sequence(const Sequence &)
0054 {
0055 return "<undumpable sequence>";
0056 }
0057 inline std::string dump_sequence(const std::string &s)
0058 {
0059 return s;
0060 }
0061 #ifndef BOOST_NO_STD_WSTRING
0062 inline std::string dump_sequence(const std::wstring &s)
0063 {
0064 return narrow<std::string>(s.c_str());
0065 }
0066 #endif
0067 }
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 template <typename String, typename Translator>
0082 class string_path
0083 {
0084 BOOST_STATIC_ASSERT((is_same<String,
0085 typename Translator::internal_type>::value));
0086 public:
0087 typedef typename Translator::external_type key_type;
0088 typedef typename String::value_type char_type;
0089
0090
0091 explicit string_path(char_type separator = char_type('.'));
0092
0093
0094
0095
0096
0097
0098 string_path(const String &value, char_type separator = char_type('.'),
0099 Translator tr = Translator());
0100
0101
0102
0103
0104
0105
0106
0107
0108 string_path(const char_type *value,
0109 char_type separator = char_type('.'),
0110 Translator tr = Translator());
0111
0112
0113 string_path(const string_path &o);
0114 string_path& operator =(const string_path &o);
0115
0116
0117 key_type reduce();
0118
0119
0120 bool empty() const;
0121
0122
0123 bool single() const;
0124
0125
0126 char_type separator() const { return m_separator; }
0127
0128 std::string dump() const {
0129 return detail::dump_sequence(m_value);
0130 }
0131
0132
0133 friend string_path operator /(string_path p1, const string_path &p2)
0134 {
0135 p1 /= p2;
0136 return p1;
0137 }
0138
0139
0140
0141 string_path& operator /=(const string_path &o) {
0142
0143
0144
0145 BOOST_ASSERT((m_separator == o.m_separator
0146 || o.empty()
0147 || o.single())
0148 && "Incompatible paths.");
0149 if(!o.empty()) {
0150 String sub;
0151 if(!this->empty()) {
0152 sub.push_back(m_separator);
0153 }
0154 sub.insert(sub.end(), o.cstart(), o.m_value.end());
0155 detail::append_and_preserve_iter(m_value, sub, m_start,
0156 typename std::iterator_traits<s_iter>::iterator_category());
0157 }
0158 return *this;
0159 }
0160
0161 private:
0162 typedef typename String::iterator s_iter;
0163 typedef typename String::const_iterator s_c_iter;
0164 String m_value;
0165 char_type m_separator;
0166 Translator m_tr;
0167 s_iter m_start;
0168 s_c_iter cstart() const { return m_start; }
0169 };
0170
0171 template <typename String, typename Translator> inline
0172 string_path<String, Translator>::string_path(char_type separator)
0173 : m_separator(separator), m_start(m_value.begin())
0174 {}
0175
0176 template <typename String, typename Translator> inline
0177 string_path<String, Translator>::string_path(const String &value,
0178 char_type separator,
0179 Translator tr)
0180 : m_value(value), m_separator(separator),
0181 m_tr(tr), m_start(m_value.begin())
0182 {}
0183
0184 template <typename String, typename Translator> inline
0185 string_path<String, Translator>::string_path(const char_type *value,
0186 char_type separator,
0187 Translator tr)
0188 : m_value(value), m_separator(separator),
0189 m_tr(tr), m_start(m_value.begin())
0190 {}
0191
0192 template <typename String, typename Translator> inline
0193 string_path<String, Translator>::string_path(const string_path &o)
0194 : m_value(o.m_value), m_separator(o.m_separator),
0195 m_tr(o.m_tr), m_start(m_value.begin())
0196 {
0197 std::advance(m_start, std::distance(o.m_value.begin(), o.cstart()));
0198 }
0199
0200 template <typename String, typename Translator> inline
0201 string_path<String, Translator>&
0202 string_path<String, Translator>::operator =(const string_path &o)
0203 {
0204 m_value = o.m_value;
0205 m_separator = o.m_separator;
0206 m_tr = o.m_tr;
0207 m_start = m_value.begin();
0208 std::advance(m_start, std::distance(o.m_value.begin(), o.cstart()));
0209 return *this;
0210 }
0211
0212 template <typename String, typename Translator>
0213 typename Translator::external_type string_path<String, Translator>::reduce()
0214 {
0215 BOOST_ASSERT(!empty() && "Reducing empty path");
0216
0217 s_iter next_sep = std::find(m_start, m_value.end(), m_separator);
0218 String part(m_start, next_sep);
0219 m_start = next_sep;
0220 if(!empty()) {
0221
0222 ++m_start;
0223 }
0224
0225 if(optional<key_type> key = m_tr.get_value(part)) {
0226 return *key;
0227 }
0228 BOOST_PROPERTY_TREE_THROW(ptree_bad_path("Path syntax error", *this));
0229 }
0230
0231 template <typename String, typename Translator> inline
0232 bool string_path<String, Translator>::empty() const
0233 {
0234 return m_start == m_value.end();
0235 }
0236
0237 template <typename String, typename Translator> inline
0238 bool string_path<String, Translator>::single() const
0239 {
0240 return std::find(static_cast<s_c_iter>(m_start),
0241 m_value.end(), m_separator)
0242 == m_value.end();
0243 }
0244
0245
0246
0247 template <typename Ch, typename Traits, typename Alloc>
0248 struct path_of< std::basic_string<Ch, Traits, Alloc> >
0249 {
0250 typedef std::basic_string<Ch, Traits, Alloc> _string;
0251 typedef string_path< _string, id_translator<_string> > type;
0252 };
0253 }}
0254
0255 #endif