See More

/////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) // // See accompanying file COPYING.TXT file for licensing details. // /////////////////////////////////////////////////////////////////////////////// #ifndef CPPCMS_STRING_KEY_H #define CPPCMS_STRING_KEY_H #include #include #include #include #include namespace cppcms { /// /// \brief This is a special object that may hold an std::string or /// alternatively reference to external (unowned) chunk of text /// /// It is designed to be used for efficiency and reduce amount of /// memory allocations and copies. /// /// It has interface that is roughly similar to the interface of std::string, /// but it does not provide a members that can mutate it or provide a NUL terminated /// string c_str(). /// class string_key { public: /// /// Iterator type /// typedef char const *const_iterator; /// /// The last position of the character in the string /// static const size_t npos = -1; /// /// Default constructor - empty key /// string_key() : begin_(0), end_(0) { } /// /// Create a new string copying the \a key /// string_key(char const *key) : begin_(0), end_(0), key_(key) { } /// /// Create a new string copying the \a key /// string_key(std::string const &key) : begin_(0), end_(0), key_(key) { } /// /// String size in bytes /// size_t size() const { return end() - begin(); } /// /// Same as size() /// size_t length() const { return size(); } /// /// Clear the string /// void clear() { begin_ = end_ = 0; key_.clear(); } /// /// Check if the string is empty /// bool empty() const { return end() == begin(); } /// /// Find first occurrence of a character \c in the string starting from /// position \a pos. Returns npos if not character found. /// size_t find(char c,size_t pos = 0) const { size_t s = size(); if(pos >= s) return npos; char const *p=begin() + pos; while(pos <= s && *p!=c) { pos++; p++; } if(pos >= s) return npos; return pos; } /// /// Create a substring from this string starting from character \a pos of size at most \a n /// string_key substr(size_t pos = 0,size_t n=npos) const { string_key tmp = unowned_substr(pos,n); return string_key(std::string(tmp.begin(),tmp.end())); } /// /// Create a substring from this string starting from character \a pos of size at most \a n /// such that the memory is not copied but only reference by the created substring /// string_key unowned_substr(size_t pos = 0,size_t n=npos) const { if(pos >= size()) { return string_key(); } char const *p=begin() + pos; char const *e=end(); if(n > size_t(e-p)) { return string_key(p,e); } else { return string_key(p,p+n); } } /// /// Get a character at position \a n /// char const &operator[](size_t n) const { return *(begin() + n); } /// /// Get a character at position \a n, if \a n is not valid position, throws std::out_of_range exception /// char const &at(size_t n) const { if(n > size()) throw std::out_of_range("cppcms::string_key::at() range error"); return *(begin() + n); } /// /// Create a string from \a v without copying the memory. \a v should remain valid /// as long as this object is used /// static string_key unowned(std::string const &v) { return string_key(v.c_str(),v.c_str()+v.size()); } /// /// Create a string from \a str without copying the memory. \a str should remain valid /// as long as this object is used /// static string_key unowned(char const *str) { char const *end = str; while(*end) end++; return string_key(str,end); } /// /// Create a string from \a characters at rang [begin,end) without copying the memory. /// The range should remain valid as long as this object is used /// static string_key unowned(char const *begin,char const *end) { return string_key(begin,end); } /// /// Get a pointer to the first character in the string /// char const *begin() const { if(begin_) return begin_; return key_.c_str(); } /// /// Get a pointer to the one past last character in the string /// char const *end() const { if(begin_) return end_; return key_.c_str() + key_.size(); } /// /// Compare two strings /// bool operator<(string_key const &other) const { return std::lexicographical_compare( begin(),end(), other.begin(),other.end(), std::char_traits::lt); } /// /// Compare two strings /// bool operator>(string_key const &other) const { return other < *this; } /// /// Compare two strings /// bool operator>=(string_key const &other) const { return !(*this < other); } /// /// Compare two strings /// bool operator<=(string_key const &other) const { return !(*this > other); } /// /// Compare two strings /// bool operator==(string_key const &other) const { return (end() - begin() == other.end() - other.begin()) && memcmp(begin(),other.begin(),end()-begin()) == 0; } /// /// Compare two strings /// bool operator!=(string_key const &other) const { return !(*this==other); } /// /// Get the pointer to the first character in the string. Note it should not be NUL terminated /// char const *data() const { return begin(); } /// /// Create std::string from the key /// std::string str() const { if(begin_) return std::string(begin_,end_-begin_); else return key_; } /// /// Convert the key to the std::string /// operator std::string() const { return str(); } private: string_key(char const *b,char const *e) : begin_(b), end_(e) { } char const *begin_; char const *end_; std::string key_; }; /// /// Write the string to the stream /// inline std::ostream &operator<<(std::ostream &out,string_key const &s) { out.write(s.data(),s.size()); return out; } /// /// Compare two strings /// inline bool operator==(string_key const &l,char const *r) { return l==string_key::unowned(r); } /// /// Compare two strings /// inline bool operator==(char const *l,string_key const &r) { return string_key::unowned(l) == r; } /// /// Compare two strings /// inline bool operator==(string_key const &l,std::string const &r) { return l==string_key::unowned(r); } /// /// Compare two strings /// inline bool operator==(std::string const &l,string_key const &r) { return string_key::unowned(l) == r; } /// /// Compare two strings /// inline bool operator!=(string_key const &l,char const *r) { return l!=string_key::unowned(r); } /// /// Compare two strings /// inline bool operator!=(char const *l,string_key const &r) { return string_key::unowned(l) != r; } /// /// Compare two strings /// inline bool operator!=(string_key const &l,std::string const &r) { return l!=string_key::unowned(r); } /// /// Compare two strings /// inline bool operator!=(std::string const &l,string_key const &r) { return string_key::unowned(l) != r; } /// /// Compare two strings /// inline bool operator<=(string_key const &l,char const *r) { return l<=string_key::unowned(r); } /// /// Compare two strings /// inline bool operator<=(char const *l,string_key const &r) { return string_key::unowned(l) <= r; } /// /// Compare two strings /// inline bool operator<=(string_key const &l,std::string const &r) { return l<=string_key::unowned(r); } /// /// Compare two strings /// inline bool operator<=(std::string const &l,string_key const &r) { return string_key::unowned(l) <= r; } /// /// Compare two strings /// inline bool operator>=(string_key const &l,char const *r) { return l>=string_key::unowned(r); } /// /// Compare two strings /// inline bool operator>=(char const *l,string_key const &r) { return string_key::unowned(l) >= r; } /// /// Compare two strings /// inline bool operator>=(string_key const &l,std::string const &r) { return l>=string_key::unowned(r); } /// /// Compare two strings /// inline bool operator>=(std::string const &l,string_key const &r) { return string_key::unowned(l) >= r; } /// /// Compare two strings /// inline bool operator<(string_key const &l,char const *r) { return l<:unowned compare two strings inline bool operator const return string_key::unowned r l>(string_key const &l,char const *r) { return l>string_key::unowned(r); } /// /// Compare two strings /// inline bool operator>(char const *l,string_key const &r) { return string_key::unowned(l) > r; } /// /// Compare two strings /// inline bool operator>(string_key const &l,std::string const &r) { return l>string_key::unowned(r); } /// /// Compare two strings /// inline bool operator>(std::string const &l,string_key const &r) { return string_key::unowned(l) > r; } } #endif