GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/** |
||
2 |
* This file is part of the CernVM File System. |
||
3 |
* |
||
4 |
* Implements a string class that stores short strings on the stack and |
||
5 |
* malloc's a std::string on the heap on overflow. Used for file names and |
||
6 |
* path names that are usually small. |
||
7 |
*/ |
||
8 |
|||
9 |
#ifndef CVMFS_SHORTSTRING_H_ |
||
10 |
#define CVMFS_SHORTSTRING_H_ |
||
11 |
|||
12 |
#include <algorithm> |
||
13 |
#include <cstring> |
||
14 |
#include <string> |
||
15 |
|||
16 |
#include "atomic.h" |
||
17 |
|||
18 |
#ifdef CVMFS_NAMESPACE_GUARD |
||
19 |
namespace CVMFS_NAMESPACE_GUARD { |
||
20 |
#endif |
||
21 |
|||
22 |
const unsigned char kDefaultMaxName = 25; |
||
23 |
const unsigned char kDefaultMaxLink = 25; |
||
24 |
const unsigned char kDefaultMaxPath = 200; |
||
25 |
|||
26 |
template<unsigned char StackSize, char Type> |
||
27 |
class ShortString { |
||
28 |
public: |
||
29 |
4681567 |
ShortString() : long_string_(NULL), length_(0) { |
|
30 |
4681567 |
atomic_inc64(&num_instances_); |
|
31 |
4681567 |
} |
|
32 |
27833 |
ShortString(const ShortString &other) : long_string_(NULL) { |
|
33 |
27833 |
atomic_inc64(&num_instances_); |
|
34 |
27833 |
Assign(other); |
|
35 |
27833 |
} |
|
36 |
24296 |
ShortString(const char *chars, const unsigned length) : long_string_(NULL) { |
|
37 |
24296 |
atomic_inc64(&num_instances_); |
|
38 |
24296 |
Assign(chars, length); |
|
39 |
24296 |
} |
|
40 |
5572235 |
explicit ShortString(const std::string &std_string) : long_string_(NULL) { |
|
41 |
5572235 |
atomic_inc64(&num_instances_); |
|
42 |
5579255 |
Assign(std_string.data(), std_string.length()); |
|
43 |
5570450 |
} |
|
44 |
|||
45 |
5578954 |
ShortString & operator= (const ShortString & other) { |
|
46 |
✓✗✓✗ ✓✗ |
5578954 |
if (this != &other) |
47 |
5579059 |
Assign(other); |
|
48 |
5568919 |
return *this; |
|
49 |
} |
||
50 |
|||
51 |
✗✓✗✓ ✗✓ |
10309936 |
~ShortString() { delete long_string_; } |
52 |
|||
53 |
11164078 |
void Assign(const char *chars, const unsigned length) { |
|
54 |
✗✓✗✓ ✗✓ |
11164078 |
delete long_string_; |
55 |
11154808 |
long_string_ = NULL; |
|
56 |
✗✓✗✓ ✗✓ |
11154808 |
if (length > StackSize) { |
57 |
atomic_inc64(&num_overflows_); |
||
58 |
long_string_ = new std::string(chars, length); |
||
59 |
} else { |
||
60 |
✓✗✓✓ ✓✓ |
11154808 |
if (length) |
61 |
11158807 |
memcpy(stack_, chars, length); |
|
62 |
11154808 |
this->length_ = length; |
|
63 |
} |
||
64 |
11154808 |
} |
|
65 |
|||
66 |
5606956 |
void Assign(const ShortString &other) { |
|
67 |
5606956 |
Assign(other.GetChars(), other.GetLength()); |
|
68 |
5596756 |
} |
|
69 |
|||
70 |
1627 |
void Append(const char *chars, const unsigned length) { |
|
71 |
✗✓ | 1627 |
if (long_string_) { |
72 |
long_string_->append(chars, length); |
||
73 |
return; |
||
74 |
} |
||
75 |
|||
76 |
1627 |
const unsigned new_length = this->length_ + length; |
|
77 |
✗✓ | 1627 |
if (new_length > StackSize) { |
78 |
atomic_inc64(&num_overflows_); |
||
79 |
long_string_ = new std::string(); |
||
80 |
long_string_->reserve(new_length); |
||
81 |
long_string_->assign(stack_, length_); |
||
82 |
long_string_->append(chars, length); |
||
83 |
return; |
||
84 |
} |
||
85 |
✓✓ | 1627 |
if (length > 0) |
86 |
1604 |
memcpy(&stack_[this->length_], chars, length); |
|
87 |
1627 |
this->length_ = new_length; |
|
88 |
} |
||
89 |
|||
90 |
void Clear() { |
||
91 |
delete long_string_; |
||
92 |
long_string_ = NULL; |
||
93 |
length_ = 0; |
||
94 |
} |
||
95 |
|||
96 |
11209480 |
const char *GetChars() const { |
|
97 |
✗✓✗✓ ✗✓ |
11209480 |
if (long_string_) |
98 |
return long_string_->data(); |
||
99 |
else |
||
100 |
11209480 |
return stack_; |
|
101 |
} |
||
102 |
|||
103 |
11217251 |
unsigned GetLength() const { |
|
104 |
✗✓✗✓ ✗✓ |
11217251 |
if (long_string_) |
105 |
return long_string_->length(); |
||
106 |
11217251 |
return length_; |
|
107 |
} |
||
108 |
|||
109 |
1119 |
bool IsEmpty() const { |
|
110 |
1119 |
return GetLength() == 0; |
|
111 |
} |
||
112 |
|||
113 |
5601129 |
std::string ToString() const { |
|
114 |
5601129 |
return std::string(this->GetChars(), this->GetLength()); |
|
115 |
} |
||
116 |
|||
117 |
541 |
const char *c_str() const { |
|
118 |
✗✓✗✗ ✗✓ |
541 |
if (long_string_) |
119 |
return long_string_->c_str(); |
||
120 |
|||
121 |
541 |
char *c = const_cast<char *>(stack_) + length_; |
|
122 |
541 |
*c = '\0'; |
|
123 |
541 |
return stack_; |
|
124 |
} |
||
125 |
|||
126 |
513 |
bool operator ==(const ShortString &other) const { |
|
127 |
513 |
const unsigned this_length = this->GetLength(); |
|
128 |
513 |
const unsigned other_length = other.GetLength(); |
|
129 |
✓✓✓✓ |
513 |
if (this_length != other_length) |
130 |
288 |
return false; |
|
131 |
✓✓✓✓ |
225 |
if (this_length == 0) |
132 |
144 |
return true; |
|
133 |
|||
134 |
81 |
return memcmp(this->GetChars(), other.GetChars(), this_length) == 0; |
|
135 |
} |
||
136 |
|||
137 |
293 |
bool operator !=(const ShortString &other) const { |
|
138 |
293 |
return !(*this == other); |
|
139 |
} |
||
140 |
|||
141 |
582 |
bool operator <(const ShortString &other) const { |
|
142 |
582 |
const unsigned this_length = this->GetLength(); |
|
143 |
582 |
const unsigned other_length = other.GetLength(); |
|
144 |
|||
145 |
✓✓ | 582 |
if (this_length < other_length) |
146 |
143 |
return true; |
|
147 |
✓✓ | 439 |
if (this_length > other_length) |
148 |
57 |
return false; |
|
149 |
|||
150 |
382 |
const char *this_chars = this->GetChars(); |
|
151 |
382 |
const char *other_chars = other.GetChars(); |
|
152 |
✓✓ | 2348 |
for (unsigned i = 0; i < this_length; ++i) { |
153 |
✓✓ | 1972 |
if (this_chars[i] < other_chars[i]) |
154 |
5 |
return true; |
|
155 |
✓✓ | 1967 |
if (this_chars[i] > other_chars[i]) |
156 |
1 |
return false; |
|
157 |
} |
||
158 |
376 |
return false; |
|
159 |
} |
||
160 |
|||
161 |
389 |
bool StartsWith(const ShortString &other) const { |
|
162 |
389 |
const unsigned this_length = this->GetLength(); |
|
163 |
389 |
const unsigned other_length = other.GetLength(); |
|
164 |
✓✓ | 389 |
if (this_length < other_length) |
165 |
20 |
return false; |
|
166 |
|||
167 |
369 |
return memcmp(this->GetChars(), other.GetChars(), other_length) == 0; |
|
168 |
} |
||
169 |
|||
170 |
142 |
ShortString Suffix(const unsigned start_at) const { |
|
171 |
142 |
const unsigned length = this->GetLength(); |
|
172 |
✓✓ | 142 |
if (start_at >= length) |
173 |
4 |
return ShortString("", 0); |
|
174 |
|||
175 |
138 |
return ShortString(this->GetChars() + start_at, length-start_at); |
|
176 |
} |
||
177 |
|||
178 |
static uint64_t num_instances() { return atomic_read64(&num_instances_); } |
||
179 |
static uint64_t num_overflows() { return atomic_read64(&num_overflows_); } |
||
180 |
|||
181 |
private: |
||
182 |
std::string *long_string_; |
||
183 |
char stack_[StackSize+1]; // +1 to add a final '\0' if necessary |
||
184 |
unsigned char length_; |
||
185 |
static atomic_int64 num_overflows_; |
||
186 |
static atomic_int64 num_instances_; |
||
187 |
}; // class ShortString |
||
188 |
|||
189 |
typedef ShortString<kDefaultMaxPath, 0> PathString; |
||
190 |
typedef ShortString<kDefaultMaxName, 1> NameString; |
||
191 |
typedef ShortString<kDefaultMaxLink, 2> LinkString; |
||
192 |
|||
193 |
template<unsigned char StackSize, char Type> |
||
194 |
atomic_int64 ShortString<StackSize, Type>::num_overflows_ = 0; |
||
195 |
template<unsigned char StackSize, char Type> |
||
196 |
atomic_int64 ShortString<StackSize, Type>::num_instances_ = 0; |
||
197 |
|||
198 |
#ifdef CVMFS_NAMESPACE_GUARD |
||
199 |
} // namespace CVMFS_NAMESPACE_GUARD |
||
200 |
#endif |
||
201 |
|||
202 |
#endif // CVMFS_SHORTSTRING_H_ |
Generated by: GCOVR (Version 4.1) |