00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef _PASSENGER_STATIC_STRING_H_
00026 #define _PASSENGER_STATIC_STRING_H_
00027
00028 #include <string>
00029 #include <cstring>
00030 #include <cstddef>
00031 #include <ostream>
00032 #include <stdexcept>
00033
00034 namespace Passenger {
00035
00036 using namespace std;
00037
00038
00039
00040
00041
00042
00043
00044
00045 class StaticString {
00046 private:
00047 const char *content;
00048 string::size_type len;
00049
00050 static const char *memmem(const char *haystack, string::size_type haystack_len,
00051 const char *needle, string::size_type needle_len)
00052 {
00053 if (needle_len == 0) {
00054 return haystack;
00055 }
00056
00057 const char *last_possible = haystack + haystack_len - needle_len;
00058 do {
00059 const char *result = (const char *) memchr(haystack, needle[0], haystack_len);
00060 if (result != NULL) {
00061 if (result > last_possible) {
00062 return NULL;
00063 } else if (memcmp(result, needle, needle_len) == 0) {
00064 return result;
00065 } else {
00066 ssize_t new_len = ssize_t(haystack_len) - (result - haystack) - 1;
00067 if (new_len <= 0) {
00068 return NULL;
00069 } else {
00070 haystack = result + 1;
00071 haystack_len = new_len;
00072 }
00073 }
00074 } else {
00075 return NULL;
00076 }
00077 } while (true);
00078 }
00079
00080 public:
00081
00082 struct Hash {
00083 size_t operator()(const StaticString &str) const {
00084 size_t result = 0;
00085 const char *data = str.content;
00086 const char *end = data + str.len;
00087 while (data != end) {
00088 result = result * 33 + *data;
00089 data++;
00090 }
00091 return result;
00092 }
00093 };
00094
00095 StaticString() {
00096 content = "";
00097 len = 0;
00098 }
00099
00100 StaticString(const StaticString &b) {
00101 content = b.content;
00102 len = b.len;
00103 }
00104
00105 StaticString(const string &s) {
00106 content = s.data();
00107 len = s.size();
00108 }
00109
00110 StaticString(const char *data) {
00111 content = data;
00112 len = strlen(data);
00113 }
00114
00115 StaticString(const char *data, string::size_type len) {
00116 content = data;
00117 this->len = len;
00118 }
00119
00120 bool empty() const {
00121 return len == 0;
00122 }
00123
00124 string::size_type size() const {
00125 return len;
00126 }
00127
00128 char operator[](string::size_type i) const {
00129 return content[i];
00130 }
00131
00132 char at(string::size_type i) const {
00133 return content[i];
00134 }
00135
00136 const char *c_str() const {
00137 return content;
00138 }
00139
00140 const char *data() const {
00141 return content;
00142 }
00143
00144 string toString() const {
00145 return string(content, len);
00146 }
00147
00148 bool equals(const StaticString &other) const {
00149 return len == other.len && memcmp(content, other.content, len) == 0;
00150 }
00151
00152 bool equals(const string &other) const {
00153 return len == other.size() && memcmp(content, other.data(), len) == 0;
00154 }
00155
00156 string::size_type find(char c, string::size_type pos = 0) const {
00157 if (pos < len) {
00158 const char *result = (const char *) memchr(content + pos, c, len - pos);
00159 if (result == NULL) {
00160 return string::npos;
00161 } else {
00162 return result - content;
00163 }
00164 } else {
00165 return string::npos;
00166 }
00167 }
00168
00169 string::size_type find(const StaticString &s, string::size_type pos = 0) const {
00170 if (s.empty()) {
00171 return 0;
00172 } else if (pos < len) {
00173 const char *result = memmem(content + pos, len - pos, s.c_str(), s.size());
00174 if (result == NULL) {
00175 return string::npos;
00176 } else {
00177 return result - content;
00178 }
00179 } else {
00180 return string::npos;
00181 }
00182 }
00183
00184 string::size_type find(const char *s, string::size_type pos, string::size_type n) const {
00185 return find(StaticString(s, n), pos);
00186 }
00187
00188 StaticString substr(string::size_type pos = 0, string::size_type n = string::npos) const {
00189 if (pos > len) {
00190 throw out_of_range("Argument 'pos' out of range");
00191 } else {
00192 if (n > len - pos) {
00193 n = len - pos;
00194 }
00195 return StaticString(content + pos, n);
00196 }
00197 }
00198
00199 bool operator==(const StaticString &other) const {
00200 return len == other.len && memcmp(content, other.content, len) == 0;
00201 }
00202
00203 bool operator==(const string &other) const {
00204 return len == other.size() && memcmp(content, other.data(), len) == 0;
00205 }
00206
00207 bool operator==(const char *other) const {
00208 size_t other_len = strlen(other);
00209 return len == other_len && memcmp(content, other, other_len) == 0;
00210 }
00211
00212 bool operator!=(const StaticString &other) const {
00213 return len != other.len || memcmp(content, other.content, len) != 0;
00214 }
00215
00216 bool operator!=(const string &other) const {
00217 return len != other.size() || memcmp(content, other.data(), len) != 0;
00218 }
00219
00220 bool operator!=(const char *other) const {
00221 size_t other_len = strlen(other);
00222 return len != other_len || memcmp(content, other, other_len) != 0;
00223 }
00224
00225 bool operator<(const StaticString &other) const {
00226 size_t size = (len < other.size()) ? len : other.size();
00227 int result = memcmp(content, other.data(), size);
00228 if (result == 0) {
00229 return len < other.size();
00230 } else {
00231 return result < 0;
00232 }
00233 }
00234
00235 bool operator<(const char *other) const {
00236 return *this < StaticString(other);
00237 }
00238
00239 string operator+(const char *other) const {
00240 return string(content, len) + other;
00241 }
00242
00243 string operator+(const string &other) const {
00244 return string(content, len) + other;
00245 }
00246
00247 string operator+(const StaticString &other) const {
00248 string result(content, len);
00249 result.append(other.data(), other.size());
00250 return result;
00251 }
00252
00253 operator string() const {
00254 return string(content, len);
00255 }
00256 };
00257
00258 inline string
00259 operator+(const char *lhs, const StaticString &rhs) {
00260 return StaticString(lhs) + rhs;
00261 }
00262
00263 inline string
00264 operator+(const string &lhs, const StaticString &rhs) {
00265 string result = lhs;
00266 result.append(rhs.data(), rhs.size());
00267 return result;
00268 }
00269
00270 inline ostream &
00271 operator<<(ostream &os, const StaticString &str) {
00272 os.write(str.data(), str.size());
00273 return os;
00274 }
00275
00276 inline bool
00277 operator==(const string &other, const StaticString &str) {
00278 return str == other;
00279 }
00280
00281 inline bool
00282 operator==(const char *other, const StaticString &str) {
00283 return str == other;
00284 }
00285
00286 inline bool
00287 operator!=(const string &other, const StaticString &str) {
00288 return str != other;
00289 }
00290
00291 inline bool
00292 operator!=(const char *other, const StaticString &str) {
00293 return str != other;
00294 }
00295
00296 }
00297
00298 #endif