Skip to content

Commit

Permalink
use c++11 heterogeneous map lookups in config if possible.
Browse files Browse the repository at this point in the history
this means that codes like cfg.child("abcd") or cfg["abcd"] won't create
a temporary std::string anymore. At least when cfg is const.
  • Loading branch information
gfgtdf committed Apr 1, 2016
1 parent 9c442eb commit b6282d8
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 3 deletions.
60 changes: 59 additions & 1 deletion src/config.cpp
Expand Up @@ -42,6 +42,24 @@ static lg::log_domain log_config("config");
#define ERR_CF LOG_STREAM(err, log_config)
#define DBG_CF LOG_STREAM(debug, log_config)


#ifdef USE_HETEROGENOUS_LOOKUPS
struct config_simple_key
{
const char* str;
int len;

friend bool operator<(const config_simple_key& l, const std::string& r)
{
return r.compare(0, r.size(), l.str, l.len) > 0;
}
friend bool operator<(const std::string& l, const config_simple_key& r)
{
return l.compare(0, l.size(), r.str, r.len) < 0;
}
};
#endif

struct tconfig_implementation
{
/**
Expand Down Expand Up @@ -653,14 +671,42 @@ config &config::child(const std::string& key, int n)
if (n < 0) n = i->second.size() + n;
if(size_t(n) < i->second.size()) {
return *i->second[n];
} else {
}
else {
DBG_CF << "The config object has only »" << i->second.size()
<< "« children named »" << key
<< "«; request for the index »" << n << "« cannot be honored.\n";

return invalid;
}
}

#ifdef USE_HETEROGENOUS_LOOKUPS
config &config::child_impl(const char* key, int len, int n)
{
check_valid();

const child_map::const_iterator i = children.find(config_simple_key{ key, len });
if (i == children.end()) {
DBG_CF << "The config object has no child named »"
<< key << "«.\n";

return invalid;
}

if (n < 0) n = i->second.size() + n;
if (size_t(n) < i->second.size()) {
return *i->second[n];
}
else {
DBG_CF << "The config object has only »" << i->second.size()
<< "« children named »" << key
<< "«; request for the index »" << n << "« cannot be honored.\n";

return invalid;
}
}
#endif

config& config::child(const std::string& key, const std::string& parent)
{
Expand Down Expand Up @@ -877,6 +923,18 @@ const config::attribute_value &config::operator[](const std::string &key) const
return empty_attribute;
}

#ifdef USE_HETEROGENOUS_LOOKUPS
const config::attribute_value& config::get_attribute(const char* key, int len) const
{
check_valid();

const attribute_map::const_iterator i = values.find(config_simple_key { key, len });
if (i != values.end()) return i->second;
static const attribute_value empty_attribute;
return empty_attribute;
}

#endif
const config::attribute_value *config::get(const std::string &key) const
{
check_valid();
Expand Down
45 changes: 43 additions & 2 deletions src/config.hpp
Expand Up @@ -50,6 +50,11 @@
#include "exceptions.hpp"
#include "tstring.hpp"

//TODO: enable for gcc 5.0 and clang 3.4
#if defined(_MSC_VER) && _MSC_VER >= 1900
# define USE_HETEROGENOUS_LOOKUPS
#endif

class config;
class enum_tag;

Expand Down Expand Up @@ -99,7 +104,11 @@ class config
{ return this != &invalid; }

typedef std::vector<config*> child_list;
typedef std::map<std::string,child_list> child_map;
typedef std::map<std::string, child_list
#ifdef USE_HETEROGENOUS_LOOKUPS
, std::less<>
#endif
> child_map;

struct const_child_iterator;

Expand Down Expand Up @@ -357,7 +366,13 @@ class config
static const std::string s_true, s_false;
};

typedef std::map<std::string, attribute_value> attribute_map;
typedef std::map<
std::string
, attribute_value
#ifdef USE_HETEROGENOUS_LOOKUPS
, std::less<>
#endif
> attribute_map;
typedef attribute_map::value_type attribute;

struct const_attribute_iterator
Expand Down Expand Up @@ -415,6 +430,12 @@ class config
*/
config &child(const std::string& key, int n = 0);

#ifdef USE_HETEROGENOUS_LOOKUPS
template<int N>
config &child(const char(&key)[N], int n = 0)
{ return child_impl(key, N - 1, n); }
config &child_impl(const char* key, int len, int n = 0);
#endif
/**
* Returns the nth child with the given @a key, or
* a reference to an invalid config if there is none.
Expand All @@ -424,6 +445,11 @@ class config
const config &child(const std::string& key, int n = 0) const
{ return const_cast<config *>(this)->child(key, n); }

#ifdef USE_HETEROGENOUS_LOOKUPS
template<int N>
const config &child(const char(&key)[N], int n = 0) const
{ return const_cast<config *>(this)->child_impl(key, N- 1, n); }
#endif
/**
* Returns a mandatory child node.
*
Expand Down Expand Up @@ -478,6 +504,18 @@ class config
*/
const attribute_value &operator[](const std::string &key) const;

#ifdef USE_HETEROGENOUS_LOOKUPS
/**
* Returns a reference to the attribute with the given @a key
* or to a dummy empty attribute if it does not exist.
*/
template<int N>
inline const attribute_value &operator[](const char (&key)[N]) const
{
//-1 for the terminating null character.
return get_attribute(key, N - 1);
}
#endif
/**
* Returns a pointer to the attribute with the given @a key
* or nullptr if it does not exist.
Expand Down Expand Up @@ -683,6 +721,9 @@ class config
void swap(config& cfg);

private:
#ifdef USE_HETEROGENOUS_LOOKUPS
const attribute_value& get_attribute(const char* key, int len) const;
#endif
/**
* Removes the child at position @a pos of @a l.
*/
Expand Down

0 comments on commit b6282d8

Please sign in to comment.