Skip to content

Commit bc9874c

Browse files
authored
Reduce std::string copies (jbeder#924)
- Don't eagerly convert key to std::string - Make const char* keys streamable when exception is thrown - Don't create a temporary string when comparing a const char* key
1 parent 06b99f5 commit bc9874c

File tree

4 files changed

+30
-55
lines changed

4 files changed

+30
-55
lines changed

include/yaml-cpp/exceptions.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) {
100100
return stream.str();
101101
}
102102

103+
inline const std::string KEY_NOT_FOUND_WITH_KEY(const char* key) {
104+
std::stringstream stream;
105+
stream << KEY_NOT_FOUND << ": " << key;
106+
return stream.str();
107+
}
108+
103109
template <typename T>
104110
inline const std::string KEY_NOT_FOUND_WITH_KEY(
105111
const T& key, typename enable_if<is_numeric<T>>::type* = 0) {
@@ -120,6 +126,12 @@ inline const std::string BAD_SUBSCRIPT_WITH_KEY(const std::string& key) {
120126
return stream.str();
121127
}
122128

129+
inline const std::string BAD_SUBSCRIPT_WITH_KEY(const char* key) {
130+
std::stringstream stream;
131+
stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")";
132+
return stream.str();
133+
}
134+
123135
template <typename T>
124136
inline const std::string BAD_SUBSCRIPT_WITH_KEY(
125137
const T& key, typename enable_if<is_numeric<T>>::type* = nullptr) {

include/yaml-cpp/node/convert.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,17 @@ struct convert<std::string> {
7474
// C-strings can only be encoded
7575
template <>
7676
struct convert<const char*> {
77-
static Node encode(const char*& rhs) { return Node(rhs); }
77+
static Node encode(const char* rhs) { return Node(rhs); }
78+
};
79+
80+
template <>
81+
struct convert<char*> {
82+
static Node encode(const char* rhs) { return Node(rhs); }
7883
};
7984

8085
template <std::size_t N>
81-
struct convert<const char[N]> {
82-
static Node encode(const char(&rhs)[N]) { return Node(rhs); }
86+
struct convert<char[N]> {
87+
static Node encode(const char* rhs) { return Node(rhs); }
8388
};
8489

8590
template <>

include/yaml-cpp/node/detail/impl.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,11 @@ inline bool node::equals(const T& rhs, shared_memory_holder pMemory) {
106106
}
107107

108108
inline bool node::equals(const char* rhs, shared_memory_holder pMemory) {
109-
return equals<std::string>(rhs, pMemory);
109+
std::string lhs;
110+
if (convert<std::string>::decode(Node(*this, std::move(pMemory)), lhs)) {
111+
return lhs == rhs;
112+
}
113+
return false;
110114
}
111115

112116
// indexing

include/yaml-cpp/node/impl.h

Lines changed: 5 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -315,51 +315,6 @@ inline void Node::push_back(const Node& rhs) {
315315
m_pMemory->merge(*rhs.m_pMemory);
316316
}
317317

318-
// helpers for indexing
319-
namespace detail {
320-
template <typename T>
321-
struct to_value_t {
322-
explicit to_value_t(const T& t_) : t(t_) {}
323-
const T& t;
324-
using return_type = const T &;
325-
326-
const T& operator()() const { return t; }
327-
};
328-
329-
template <>
330-
struct to_value_t<const char*> {
331-
explicit to_value_t(const char* t_) : t(t_) {}
332-
const char* t;
333-
using return_type = std::string;
334-
335-
const std::string operator()() const { return t; }
336-
};
337-
338-
template <>
339-
struct to_value_t<char*> {
340-
explicit to_value_t(char* t_) : t(t_) {}
341-
const char* t;
342-
using return_type = std::string;
343-
344-
const std::string operator()() const { return t; }
345-
};
346-
347-
template <std::size_t N>
348-
struct to_value_t<char[N]> {
349-
explicit to_value_t(const char* t_) : t(t_) {}
350-
const char* t;
351-
using return_type = std::string;
352-
353-
const std::string operator()() const { return t; }
354-
};
355-
356-
// converts C-strings to std::strings so they can be copied
357-
template <typename T>
358-
inline typename to_value_t<T>::return_type to_value(const T& t) {
359-
return to_value_t<T>(t)();
360-
}
361-
} // namespace detail
362-
363318
template<typename Key>
364319
std::string key_to_string(const Key& key) {
365320
return streamable_to_string<Key, is_streamable<std::stringstream, Key>::value>().impl(key);
@@ -369,8 +324,8 @@ std::string key_to_string(const Key& key) {
369324
template <typename Key>
370325
inline const Node Node::operator[](const Key& key) const {
371326
EnsureNodeExists();
372-
detail::node* value = static_cast<const detail::node&>(*m_pNode).get(
373-
detail::to_value(key), m_pMemory);
327+
detail::node* value =
328+
static_cast<const detail::node&>(*m_pNode).get(key, m_pMemory);
374329
if (!value) {
375330
return Node(ZombieNode, key_to_string(key));
376331
}
@@ -380,14 +335,14 @@ inline const Node Node::operator[](const Key& key) const {
380335
template <typename Key>
381336
inline Node Node::operator[](const Key& key) {
382337
EnsureNodeExists();
383-
detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory);
338+
detail::node& value = m_pNode->get(key, m_pMemory);
384339
return Node(value, m_pMemory);
385340
}
386341

387342
template <typename Key>
388343
inline bool Node::remove(const Key& key) {
389344
EnsureNodeExists();
390-
return m_pNode->remove(detail::to_value(key), m_pMemory);
345+
return m_pNode->remove(key, m_pMemory);
391346
}
392347

393348
inline const Node Node::operator[](const Node& key) const {
@@ -420,8 +375,7 @@ inline bool Node::remove(const Node& key) {
420375
template <typename Key, typename Value>
421376
inline void Node::force_insert(const Key& key, const Value& value) {
422377
EnsureNodeExists();
423-
m_pNode->force_insert(detail::to_value(key), detail::to_value(value),
424-
m_pMemory);
378+
m_pNode->force_insert(key, value, m_pMemory);
425379
}
426380

427381
// free functions

0 commit comments

Comments
 (0)