]> sourceware.org Git - systemtap.git/blame - stringtable.h
PR23879, PR24875: fix task-finder-vma on f29+
[systemtap.git] / stringtable.h
CommitLineData
aa389a19
FCE
1// -*- C++ -*-
2// Copyright (C) 2015 Red Hat Inc.
3//
4// This file is part of systemtap, and is free software. You can
5// redistribute it and/or modify it under the terms of the GNU General
6// Public License (GPL); either version 2, or (at your option) any
7// later version.
8
9
10#ifndef STRINGTABLE_H
11#define STRINGTABLE_H
12
5d46f7cb 13#include <functional>
aa389a19 14#include <string>
3dd76f53
AJ
15#include <cstring>
16
421a5349
JS
17// TODO use C++17's std::string_view when possible. It even hashes natively.
18// (some compilers already have std::experimental::string_view)
ea63d6ad 19
3dd76f53 20#if defined(HAVE_BOOST_UTILITY_STRING_REF_HPP)
91f252b7 21#include <boost/version.hpp>
aa389a19
FCE
22#include <boost/utility/string_ref.hpp> //header with string_ref
23
7eae03f8
FCE
24// XXX: experimental tunables
25#define INTERNED_STRING_FIND_MEMMEM 1 /* perf stat indicates a very slight benefit */
26#define INTERNED_STRING_CUSTOM_HASH 1 /* maybe an abbreviated hash function for long strings? */
924f8d22 27#define INTERNED_STRING_INSTRUMENT 0 /* write out hash logs ... super super slow */
47d349b1
FCE
28
29struct interned_string: public boost::string_ref
30{
31 // all these construction operations intern the incoming string
3e4547ad 32 interned_string(): boost::string_ref() {}
531de7b4
JS
33 interned_string(const char* value):
34 boost::string_ref(intern(value)) {}
35 interned_string(const std::string& value):
36 boost::string_ref(intern(value)) {}
37 interned_string& operator = (const std::string& value)
38 { return *this = intern(value); }
39 interned_string& operator = (const char* value)
40 { return *this = intern(value); }
91f252b7
AJ
41
42#if BOOST_VERSION < 105400
43 std::string to_string () const { return std::string(this->data(), this->size()); }
44
45 // some comparison operators that aren't available in boost 1.53
46 bool operator == (const char* y) { return compare(boost::string_ref(y)) == 0; }
47 bool operator == (const std::string& y) { return compare(boost::string_ref(y)) == 0; }
48 friend bool operator == (interned_string x, interned_string y) { return x.compare(y) == 0; }
49 friend bool operator == (const char * x, interned_string y)
50 {
51 return y.compare(boost::string_ref(x)) == 0;
52 }
53 friend bool operator == (const std::string& x, interned_string y)
54 {
55 return y.compare(boost::string_ref(x)) == 0;
56 }
57
58 bool operator != (const char* y) { return compare(boost::string_ref(y)) != 0; }
59 bool operator != (const std::string& y) { return compare(boost::string_ref(y)) != 0; }
60 friend bool operator != (interned_string x, interned_string y) { return x.compare(y) != 0; }
61 friend bool operator != (const char * x, interned_string y)
62 {
63 return y.compare(boost::string_ref(x)) != 0;
64 }
65 friend bool operator != (const std::string& x, interned_string y)
66 {
67 return y.compare(boost::string_ref(x)) != 0;
68 }
69#endif
70
47d349b1 71 // easy out-conversion operators
45a63356 72 operator std::string () const { return this->to_string(); }
3e4547ad 73
7371cd19 74 // return an efficient substring reference
07ebb812
FCE
75 interned_string substr(size_t pos = 0, size_t len = npos) const
76 {
7371cd19 77 return boost::string_ref::substr(pos, len);
07ebb812 78 }
45a63356
FCE
79
80 // boost oversights
81 template <typename F>
7eae03f8 82 size_t find (const F& f, size_t start_pos)
45a63356 83 {
7371cd19 84 size_t x = this->substr(start_pos).find(f);
45a63356
FCE
85 if (x == boost::string_ref::npos)
86 return x;
87 else
88 return x + start_pos;
89 }
90
91 template <typename F>
7eae03f8 92 size_t find (const F& f) const
45a63356
FCE
93 {
94 return boost::string_ref::find(f);
95 }
7eae03f8
FCE
96
97#if INTERNED_STRING_FIND_MEMMEM
98 size_t find (const boost::string_ref& f) const;
99 size_t find (const std::string& f) const;
100 size_t find (const char *f) const;
101#endif
cccf2f58
JS
102
103 size_t find (const interned_string& f) const
104 {
105 return find (static_cast<const boost::string_ref&> (f));
106 }
45a63356 107
47d349b1 108private:
07ebb812 109 static interned_string intern(const std::string& value);
7cde9f59 110 static interned_string intern(const char* value);
2f119072 111 static interned_string intern(char value);
7371cd19
JS
112
113 // This is private so we can be sure of ownership, from our interned string table.
114 interned_string(const boost::string_ref& value): boost::string_ref(value) {}
47d349b1 115};
421a5349
JS
116
117namespace std {
118 template<> struct hash<interned_string> {
119 size_t operator() (interned_string s) const
120 {
121 // NB: we'd love to be able to hook up to a blob hashing
122 // function in std::hash, but there isn't one. We don't want
123 // to copy the interned_string into a temporary string just to
124 // hash the thing.
125 //
126 // This code is based on the g++ _Fnv_hash_base ptr/length case.
127 size_t hash = 0;
128 const char* x = s.data();
129 for (size_t i=s.length(); i>0; i--)
130 hash = (hash * 131) + *x++;
131 return hash;
132 }
133 };
134}
135
3dd76f53 136#else /* !defined(HAVE_BOOST_UTILITY_STRING_REF_HPP) */
47d349b1 137
3dd76f53
AJ
138struct interned_string : public std::string {
139 interned_string(): std::string() {}
140 interned_string(const char* value): std::string (value ? :"") {}
141 interned_string(const std::string& value): std::string(value) {}
142 std::string to_string() const {return (std::string) *this; }
143 void remove_prefix (size_t n) {*this = this->substr(n);}
144 interned_string substr(size_t pos = 0, size_t len = npos) const
145 {
146 return (interned_string)std::string::substr(pos, len);
147 }
148 bool starts_with(const char* value) const
149 {
150 return (this->compare(0, std::strlen(value), value) == 0);
151 }
152
153 bool starts_with(const std::string& value) const
154 {
155 return (this->compare(0, value.length(), value) == 0);
156 }
7371cd19
JS
157
158private:
159 // c_str is not allowed on boost::string_ref, so add a private unimplemented
160 // declaration here to prevent the use of string::c_str accidentally.
161 const char* c_str() const;
3dd76f53 162};
47d349b1 163
5d46f7cb
JS
164namespace std {
165 template<> struct hash<interned_string> {
421a5349 166 size_t operator() (interned_string const& s) const
5d46f7cb 167 {
421a5349
JS
168 // strings are directly hashable
169 return hash<string>()(s);
5d46f7cb
JS
170 }
171 };
172}
aa389a19 173
421a5349
JS
174#endif /* defined(HAVE_BOOST_UTILITY_STRING_REF_HPP) */
175
aa389a19
FCE
176#endif // STRINGTABLE_H
177
178/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.087152 seconds and 5 git commands to generate.