- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List

# StaticString.h

    00001 /*
    00002  *  Phusion Passenger - http://www.modrails.com/
    00003  *  Copyright (c) 2010 Phusion
    00004  *
    00005  *  "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
    00006  *
    00007  *  Permission is hereby granted, free of charge, to any person obtaining a copy
    00008  *  of this software and associated documentation files (the "Software"), to deal
    00009  *  in the Software without restriction, including without limitation the rights
    00010  *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    00011  *  copies of the Software, and to permit persons to whom the Software is
    00012  *  furnished to do so, subject to the following conditions:
    00013  *
    00014  *  The above copyright notice and this permission notice shall be included in
    00015  *  all copies or substantial portions of the Software.
    00016  *
    00017  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    00018  *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    00019  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    00020  *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    00021  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    00022  *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    00023  *  THE SOFTWARE.
    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  * An immutable, static byte buffer. This class will never copy data:
    00040  * it just holds a pointer to the data. So a StaticString will become unusable
    00041  * once the data it refers to has been freed.
    00042  *
    00043  * StaticString will never modify the data.
    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         /** A hash function object for StaticString. */
    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 } // namespace Passenger
    00297
    00298 #endif /* _PASSENGER_STATIC_STRING_H_ */