|
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
- //
- // See accompanying file COPYING.TXT file for licensing details.
- //
- ///////////////////////////////////////////////////////////////////////////////
- #ifndef CPPCMS_STRING_KEY_H
- #define CPPCMS_STRING_KEY_H
-
- #include <string>
- #include <string.h>
- #include <algorithm>
- #include <stdexcept>
- #include <ostream>
-
- 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<char>::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<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;
- }
-
- }
-
- #endif
|