// -*- C++ -*- // Copyright (C) 2015 Red Hat Inc. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. #ifndef STRINGTABLE_H #define STRINGTABLE_H #include #include #if defined(HAVE_BOOST_UTILITY_STRING_REF_HPP) #include #include //header with string_ref // XXX: experimental tunables #define INTERNED_STRING_FIND_MEMMEM 1 /* perf stat indicates a very slight benefit */ #define INTERNED_STRING_CUSTOM_HASH 1 /* maybe an abbreviated hash function for long strings? */ #define INTERNED_STRING_INSTRUMENT 0 /* write out hash logs ... super super slow */ struct interned_string: public boost::string_ref { // all these construction operations intern the incoming string interned_string(): boost::string_ref() {} interned_string(const char* value): boost::string_ref(intern(value)) {} interned_string(const std::string& value): boost::string_ref(intern(value)) {} interned_string& operator = (const std::string& value) { return *this = intern(value); } interned_string& operator = (const char* value) { return *this = intern(value); } #if BOOST_VERSION < 105400 std::string to_string () const { return std::string(this->data(), this->size()); } // some comparison operators that aren't available in boost 1.53 bool operator == (const char* y) { return compare(boost::string_ref(y)) == 0; } bool operator == (const std::string& y) { return compare(boost::string_ref(y)) == 0; } friend bool operator == (interned_string x, interned_string y) { return x.compare(y) == 0; } friend bool operator == (const char * x, interned_string y) { return y.compare(boost::string_ref(x)) == 0; } friend bool operator == (const std::string& x, interned_string y) { return y.compare(boost::string_ref(x)) == 0; } bool operator != (const char* y) { return compare(boost::string_ref(y)) != 0; } bool operator != (const std::string& y) { return compare(boost::string_ref(y)) != 0; } friend bool operator != (interned_string x, interned_string y) { return x.compare(y) != 0; } friend bool operator != (const char * x, interned_string y) { return y.compare(boost::string_ref(x)) != 0; } friend bool operator != (const std::string& x, interned_string y) { return y.compare(boost::string_ref(x)) != 0; } #endif // easy out-conversion operators operator std::string () const { return this->to_string(); } // return an efficient substring reference interned_string substr(size_t pos = 0, size_t len = npos) const { return boost::string_ref::substr(pos, len); } // boost oversights template size_t find (const F& f, size_t start_pos) { size_t x = this->substr(start_pos).find(f); if (x == boost::string_ref::npos) return x; else return x + start_pos; } template size_t find (const F& f) const { return boost::string_ref::find(f); } #if INTERNED_STRING_FIND_MEMMEM size_t find (const boost::string_ref& f) const; size_t find (const std::string& f) const; size_t find (const char *f) const; #endif private: static interned_string intern(const std::string& value); static interned_string intern(const char* value); static interned_string intern(char value); // This is private so we can be sure of ownership, from our interned string table. interned_string(const boost::string_ref& value): boost::string_ref(value) {} }; #else /* !defined(HAVE_BOOST_UTILITY_STRING_REF_HPP) */ struct interned_string : public std::string { interned_string(): std::string() {} interned_string(const char* value): std::string (value ? :"") {} interned_string(const std::string& value): std::string(value) {} std::string to_string() const {return (std::string) *this; } void remove_prefix (size_t n) {*this = this->substr(n);} interned_string substr(size_t pos = 0, size_t len = npos) const { return (interned_string)std::string::substr(pos, len); } bool starts_with(const char* value) const { return (this->compare(0, std::strlen(value), value) == 0); } bool starts_with(const std::string& value) const { return (this->compare(0, value.length(), value) == 0); } private: // c_str is not allowed on boost::string_ref, so add a private unimplemented // declaration here to prevent the use of string::c_str accidentally. const char* c_str() const; }; #endif /* defined(HAVE_BOOST_UTILITY_STRING_REF_HPP) */ #endif // STRINGTABLE_H /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */