]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - libs/string/string.h
unvanquished filesystem
[xonotic/netradiant.git] / libs / string / string.h
index 9e0bcb03eeb699779c5d7f88e4885504c416ae4a..c9ef2c4dbb46fb0a404145585b0bbce75c39d518 100644 (file)
@@ -1,25 +1,25 @@
 /*
-Copyright (C) 2001-2006, William Joseph.
-All Rights Reserved.
+   Copyright (C) 2001-2006, William Joseph.
+   All Rights Reserved.
 
-This file is part of GtkRadiant.
+   This file is part of GtkRadiant.
 
-GtkRadiant is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-GtkRadiant is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
 
-#if !defined(INCLUDED_STRING_STRING_H)
+#if !defined( INCLUDED_STRING_STRING_H )
 #define INCLUDED_STRING_STRING_H
 
 /// \file
@@ -34,65 +34,57 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 /// \brief Returns true if \p string length is zero.
 /// O(1)
-inline bool string_empty(const char* string)
-{
-  return *string == '\0';
+inline bool string_empty( const char* string ){
+       return *string == '\0';
 }
 
 /// \brief Returns true if \p string length is not zero.
 /// O(1)
-inline bool string_not_empty(const char* string)
-{
-  return !string_empty(string);
+inline bool string_not_empty( const char* string ){
+       return !string_empty( string );
 }
 
 /// \brief Returns <0 if \p string is lexicographically less than \p other.
 /// Returns >0 if \p string is lexicographically greater than \p other.
 /// Returns 0 if \p string is lexicographically equal to \p other.
 /// O(n)
-inline int string_compare(const char* string, const char* other)
-{
-  return std::strcmp(string, other);
+inline int string_compare( const char* string, const char* other ){
+       return std::strcmp( string, other );
 }
 
 /// \brief Returns true if \p string is lexicographically equal to \p other.
 /// O(n)
-inline bool string_equal(const char* string, const char* other)
-{
-  return string_compare(string, other) == 0;
+inline bool string_equal( const char* string, const char* other ){
+       return string_compare( string, other ) == 0;
 }
 
 /// \brief Returns true if [\p string, \p string + \p n) is lexicographically equal to [\p other, \p other + \p n).
 /// O(n)
-inline bool string_equal_n(const char* string, const char* other, std::size_t n)
-{
-  return std::strncmp(string, other, n) == 0;
+inline bool string_equal_n( const char* string, const char* other, std::size_t n ){
+       return std::strncmp( string, other, n ) == 0;
 }
 
 /// \brief Returns true if \p string is lexicographically less than \p other.
 /// O(n)
-inline bool string_less(const char* string, const char* other)
-{
-  return string_compare(string, other) < 0;
+inline bool string_less( const char* string, const char* other ){
+       return string_compare( string, other ) < 0;
 }
 
 /// \brief Returns true if \p string is lexicographically greater than \p other.
 /// O(n)
-inline bool string_greater(const char* string, const char* other)
-{
-  return string_compare(string, other) > 0;
+inline bool string_greater( const char* string, const char* other ){
+       return string_compare( string, other ) > 0;
 }
 
 /// \brief Returns <0 if \p string is lexicographically less than \p other after converting both to lower-case.
 /// Returns >0 if \p string is lexicographically greater than \p other after converting both to lower-case.
 /// Returns 0 if \p string is lexicographically equal to \p other after converting both to lower-case.
 /// O(n)
-inline int string_compare_nocase(const char* string, const char* other)
-{
+inline int string_compare_nocase( const char* string, const char* other ){
 #ifdef WIN32
-  return _stricmp(string, other);
+       return _stricmp( string, other );
 #else
-  return strcasecmp(string, other);
+       return strcasecmp( string, other );
 #endif
 }
 
@@ -101,227 +93,214 @@ inline int string_compare_nocase(const char* string, const char* other)
 /// Returns 0 if [\p string, \p string + \p n) is lexicographically equal to [\p other, \p other + \p n).
 /// Treats all ascii characters as lower-case during comparisons.
 /// O(n)
-inline int string_compare_nocase_n(const char* string, const char* other, std::size_t n)
-{
+inline int string_compare_nocase_n( const char* string, const char* other, std::size_t n ){
 #ifdef WIN32
-  return _strnicmp(string, other, n);
+       return _strnicmp( string, other, n );
 #else
-  return strncasecmp(string, other, n);
+       return strncasecmp( string, other, n );
 #endif
 }
 
 /// \brief Returns true if \p string is lexicographically equal to \p other.
 /// Treats all ascii characters as lower-case during comparisons.
 /// O(n)
-inline bool string_equal_nocase(const char* string, const char* other)
-{
-  return string_compare_nocase(string, other) == 0;
+inline bool string_equal_nocase( const char* string, const char* other ){
+       return string_compare_nocase( string, other ) == 0;
 }
 
 /// \brief Returns true if [\p string, \p string + \p n) is lexicographically equal to [\p other, \p other + \p n).
 /// Treats all ascii characters as lower-case during comparisons.
 /// O(n)
-inline bool string_equal_nocase_n(const char* string, const char* other, std::size_t n)
-{
-  return string_compare_nocase_n(string, other, n) == 0;
+inline bool string_equal_nocase_n( const char* string, const char* other, std::size_t n ){
+       return string_compare_nocase_n( string, other, n ) == 0;
 }
 
 /// \brief Returns true if \p string is lexicographically less than \p other.
 /// Treats all ascii characters as lower-case during comparisons.
 /// O(n)
-inline bool string_less_nocase(const char* string, const char* other)
-{
-  return string_compare_nocase(string, other) < 0;
+inline bool string_less_nocase( const char* string, const char* other ){
+       return string_compare_nocase( string, other ) < 0;
 }
 
 /// \brief Returns true if \p string is lexicographically greater than \p other.
 /// Treats all ascii characters as lower-case during comparisons.
 /// O(n)
-inline bool string_greater_nocase(const char* string, const char* other)
-{
-  return string_compare_nocase(string, other) > 0;
+inline bool string_greater_nocase( const char* string, const char* other ){
+       return string_compare_nocase( string, other ) > 0;
 }
 
 /// \brief Returns the number of non-null characters in \p string.
 /// O(n)
-inline std::size_t string_length(const char* string)
-{
-  return std::strlen(string);
+inline std::size_t string_length( const char* string ){
+       return std::strlen( string );
 }
 
 /// \brief Returns true if the beginning of \p string is equal to \p prefix.
 /// O(n)
-inline bool string_equal_prefix(const char* string, const char* prefix)
-{
-  return string_equal_n(string, prefix, string_length(prefix));
+inline bool string_equal_prefix( const char* string, const char* prefix ){
+       return string_equal_n( string, prefix, string_length( prefix ) );
+}
+
+/// \brief Returns true if the ending of \p string is equal to \p suffix.
+/// O(n)
+inline bool string_equal_suffix( const char* string, const char* suffix){
+       const char *s = string + string_length( string ) - string_length( suffix );
+       return string_equal_n( s , suffix, string_length( suffix ) );
 }
 
 /// \brief Copies \p other into \p string and returns \p string.
 /// Assumes that the space allocated for \p string is at least string_length(other) + 1.
 /// O(n)
-inline char* string_copy(char* string, const char* other)
-{
-  return std::strcpy(string, other);
+inline char* string_copy( char* string, const char* other ){
+       return std::strcpy( string, other );
 }
 
 /// \brief Allocates a string buffer large enough to hold \p length characters, using \p allocator.
 /// The returned buffer must be released with \c string_release using a matching \p allocator.
 template<typename Allocator>
-inline char* string_new(std::size_t length, Allocator& allocator)
-{
-  return allocator.allocate(length + 1);
+inline char* string_new( std::size_t length, Allocator& allocator ){
+       return allocator.allocate( length + 1 );
 }
 
 /// \brief Deallocates the \p buffer large enough to hold \p length characters, using \p allocator.
 template<typename Allocator>
-inline void string_release(char* buffer, std::size_t length, Allocator& allocator)
-{
-  allocator.deallocate(buffer, length + 1);
+inline void string_release( char* buffer, std::size_t length, Allocator& allocator ){
+       allocator.deallocate( buffer, length + 1 );
 }
 
 /// \brief Returns a newly-allocated string which is a clone of \p other, using \p allocator.
 /// The returned buffer must be released with \c string_release using a matching \p allocator.
 template<typename Allocator>
-inline char* string_clone(const char* other, Allocator& allocator)
-{
-  char* copied = string_new(string_length(other), allocator);
-  std::strcpy(copied, other);
-  return copied;
+inline char* string_clone( const char* other, Allocator& allocator ){
+       char* copied = string_new( string_length( other ), allocator );
+       std::strcpy( copied, other );
+       return copied;
 }
 
 /// \brief Returns a newly-allocated string which is a clone of [\p first, \p last), using \p allocator.
 /// The returned buffer must be released with \c string_release using a matching \p allocator.
 template<typename Allocator>
-inline char* string_clone_range(StringRange range, Allocator& allocator)
-{
-  std::size_t length = range.last - range.first;
-  char* copied = strncpy(string_new(length, allocator), range.first, length);
-  copied[length] = '\0';
-  return copied;
+inline char* string_clone_range( StringRange range, Allocator& allocator ){
+       std::size_t length = range.last - range.first;
+       char* copied = strncpy( string_new( length, allocator ), range.first, length );
+       copied[length] = '\0';
+       return copied;
 }
 
 /// \brief Allocates a string buffer large enough to hold \p length characters.
 /// The returned buffer must be released with \c string_release.
-inline char* string_new(std::size_t length)
-{
-  DefaultAllocator<char> allocator;
-  return string_new(length, allocator);
+inline char* string_new( std::size_t length ){
+       DefaultAllocator<char> allocator;
+       return string_new( length, allocator );
+}
+
+/// \brief Allocates a new buffer large enough to hold two concatenated strings and fills it with strings.
+inline char* string_new_concat( const char* a, const char* b ){
+       char* str = string_new( string_length( a ) + string_length( b ) );
+       strcpy( str, a );
+       strcat( str, b );
+       return str;
 }
 
 /// \brief Deallocates the \p buffer large enough to hold \p length characters.
-inline void string_release(char* string, std::size_t length)
-{
-  DefaultAllocator<char> allocator;
-  string_release(string, length, allocator);
+inline void string_release( char* string, std::size_t length ){
+       DefaultAllocator<char> allocator;
+       string_release( string, length, allocator );
 }
 
 /// \brief Returns a newly-allocated string which is a clone of \p other.
 /// The returned buffer must be released with \c string_release.
-inline char* string_clone(const char* other)
-{
-  DefaultAllocator<char> allocator;
-  return string_clone(other, allocator);
+inline char* string_clone( const char* other ){
+       DefaultAllocator<char> allocator;
+       return string_clone( other, allocator );
 }
 
 /// \brief Returns a newly-allocated string which is a clone of [\p first, \p last).
 /// The returned buffer must be released with \c string_release.
-inline char* string_clone_range(StringRange range)
-{
-  DefaultAllocator<char> allocator;
-  return string_clone_range(range, allocator);
+inline char* string_clone_range( StringRange range ){
+       DefaultAllocator<char> allocator;
+       return string_clone_range( range, allocator );
 }
 
 typedef char* char_pointer;
 /// \brief Swaps the values of \p string and \p other.
-inline void string_swap(char_pointer& string, char_pointer& other)
-{
-  std::swap(string, other);
+inline void string_swap( char_pointer& string, char_pointer& other ){
+       std::swap( string, other );
 }
 
 typedef const char* char_const_pointer;
 /// \brief Swaps the values of \p string and \p other.
-inline void string_swap(char_const_pointer& string, char_const_pointer& other)
-{
-  std::swap(string, other);
+inline void string_swap( char_const_pointer& string, char_const_pointer& other ){
+       std::swap( string, other );
 }
 
 /// \brief Converts each character of \p string to lower-case and returns \p string.
 /// O(n)
-inline char* string_to_lowercase(char* string)
-{
-  for(char* p = string; *p != '\0'; ++p)
-  {
-    *p = std::tolower(*p);
-  }
-  return string;
+inline char* string_to_lowercase( char* string ){
+       for ( char* p = string; *p != '\0'; ++p )
+       {
+               *p = (char)std::tolower( *p );
+       }
+       return string;
 }
 
 /// \brief Converts each character of \p string to upper-case and returns \p string.
 /// O(n)
-inline char* string_to_uppercase(char* string)
-{
-  for(char* p = string; *p != '\0'; ++p)
-  {
-    *p = std::toupper(*p);
-  }
-  return string;
+inline char* string_to_uppercase( char* string ){
+       for ( char* p = string; *p != '\0'; ++p )
+       {
+               *p = (char)std::toupper( *p );
+       }
+       return string;
 }
 
 /// \brief A re-entrant string tokeniser similar to strchr.
 class StringTokeniser
 {
-  bool istoken(char c) const
-  {
-    if(strchr(m_delimiters, c) != 0)
-    {
-      return false;
-    }
-    return true;
-  }
-  const char* advance()
-  {
-    const char* token = m_pos;
-    bool intoken = true;
-    while(!string_empty(m_pos))
-    {
-      if(!istoken(*m_pos))
-      {
-        *m_pos = '\0';
-        intoken = false;
-      }
-      else if(!intoken)
-      {
-        return token;
-      }
-      ++m_pos;
-    }
-    return token;
-  }
-  std::size_t m_length;
-  char* m_string;
-  char* m_pos;
-  const char* m_delimiters;
+bool istoken( char c ) const {
+       if ( strchr( m_delimiters, c ) != 0 ) {
+               return false;
+       }
+       return true;
+}
+const char* advance(){
+       const char* token = m_pos;
+       bool intoken = true;
+       while ( !string_empty( m_pos ) )
+       {
+               if ( !istoken( *m_pos ) ) {
+                       *m_pos = '\0';
+                       intoken = false;
+               }
+               else if ( !intoken ) {
+                       return token;
+               }
+               ++m_pos;
+       }
+       return token;
+}
+std::size_t m_length;
+char* m_string;
+char* m_pos;
+const char* m_delimiters;
 public:
-  StringTokeniser(const char* string, const char* delimiters = " \n\r\t\v") :
-    m_length(string_length(string)),
-    m_string(string_copy(string_new(m_length), string)),
-    m_pos(m_string),
-    m_delimiters(delimiters)
-  {
-    while(!string_empty(m_pos) && !istoken(*m_pos))
-    {
-      ++m_pos;
-    }
-  }
-  ~StringTokeniser()
-  {
-    string_release(m_string, m_length);
-  }
-  /// \brief Returns the next token or "" if there are no more tokens available.
-  const char* getToken()
-  {
-    return advance();
-  }
+StringTokeniser( const char* string, const char* delimiters = " \n\r\t\v" ) :
+       m_length( string_length( string ) ),
+       m_string( string_copy( string_new( m_length ), string ) ),
+       m_pos( m_string ),
+       m_delimiters( delimiters ){
+       while ( !string_empty( m_pos ) && !istoken( *m_pos ) )
+       {
+               ++m_pos;
+       }
+}
+~StringTokeniser(){
+       string_release( m_string, m_length );
+}
+/// \brief Returns the next token or "" if there are no more tokens available.
+const char* getToken(){
+       return advance();
+}
 };
 
 /// \brief A non-mutable c-style string.
@@ -336,94 +315,79 @@ class String : public Buffer
 {
 public:
 
-  String()
-    : Buffer()
-  {
-  }
-  String(const char* string)
-    : Buffer(string)
-  {
-  }
-  String(StringRange range)
-    : Buffer(range)
-  {
-  }
-
-  String& operator=(const String& other)
-  {
-    String temp(other);
-    temp.swap(*this);
-    return *this;
-  }
-  String& operator=(const char* string)
-  {
-    String temp(string);
-    temp.swap(*this);
-    return *this;
-  }
-  String& operator=(StringRange range)
-  {
-    String temp(range);
-    temp.swap(*this);
-    return *this;
-  }
-
-  void swap(String& other)
-  {
-    Buffer::swap(other);
-  }
-
-  bool empty() const
-  {
-    return string_empty(Buffer::c_str());
-  }
+String()
+       : Buffer(){
+}
+String( const char* string )
+       : Buffer( string ){
+}
+String( StringRange range )
+       : Buffer( range ){
+}
+
+String& operator=( const String& other ){
+       String temp( other );
+       temp.swap( *this );
+       return *this;
+}
+String& operator=( const char* string ){
+       String temp( string );
+       temp.swap( *this );
+       return *this;
+}
+String& operator=( StringRange range ){
+       String temp( range );
+       temp.swap( *this );
+       return *this;
+}
+
+void swap( String& other ){
+       Buffer::swap( other );
+}
+
+bool empty() const {
+       return string_empty( Buffer::c_str() );
+}
 };
 
 template<typename Buffer>
-inline bool operator<(const String<Buffer>& self, const String<Buffer>& other)
-{
-  return string_less(self.c_str(), other.c_str());
+inline bool operator<( const String<Buffer>& self, const String<Buffer>& other ){
+       return string_less( self.c_str(), other.c_str() );
 }
 
 template<typename Buffer>
-inline bool operator>(const String<Buffer>& self, const String<Buffer>& other)
-{
-  return string_greater(self.c_str(), other.c_str());
+inline bool operator>( const String<Buffer>& self, const String<Buffer>& other ){
+       return string_greater( self.c_str(), other.c_str() );
 }
 
 template<typename Buffer>
-inline bool operator==(const String<Buffer>& self, const String<Buffer>& other)
-{
-  return string_equal(self.c_str(), other.c_str());
+inline bool operator==( const String<Buffer>& self, const String<Buffer>& other ){
+       return string_equal( self.c_str(), other.c_str() );
 }
 
 template<typename Buffer>
-inline bool operator!=(const String<Buffer>& self, const String<Buffer>& other)
-{
-  return !string_equal(self.c_str(), other.c_str());
+inline bool operator!=( const String<Buffer>& self, const String<Buffer>& other ){
+       return !string_equal( self.c_str(), other.c_str() );
 }
 
 template<typename Buffer>
-inline bool operator==(const String<Buffer>& self, const char* other)
-{
-  return string_equal(self.c_str(), other);
+inline bool operator==( const String<Buffer>& self, const char* other ){
+       return string_equal( self.c_str(), other );
 }
 
 template<typename Buffer>
-inline bool operator!=(const String<Buffer>& self, const char* other)
-{
-  return !string_equal(self.c_str(), other);
+inline bool operator!=( const String<Buffer>& self, const char* other ){
+       return !string_equal( self.c_str(), other );
 }
 
 namespace std
 {
-  /// \brief Swaps the values of \p self and \p other.
-  /// Overloads std::swap.
-  template<typename Buffer>
-  inline void swap(String<Buffer>& self, String<Buffer>& other)
-  {
-    self.swap(other);
-  }
+/// \brief Swaps the values of \p self and \p other.
+/// Overloads std::swap.
+template<typename Buffer>
+inline void swap( String<Buffer>& self, String<Buffer>& other ){
+       self.swap( other );
+}
 }
 
 
@@ -431,55 +395,44 @@ namespace std
 template<typename Allocator>
 class CopiedBuffer : private Allocator
 {
-  char* m_string;
-
-  char* copy_range(StringRange range)
-  {
-    return string_clone_range(range, static_cast<Allocator&>(*this));
-  }
-  char* copy(const char* other)
-  {
-    return string_clone(other, static_cast<Allocator&>(*this));
-  }
-  void destroy(char* string)
-  {
-    string_release(string, string_length(string), static_cast<Allocator&>(*this));
-  }
+char* m_string;
+
+char* copy_range( StringRange range ){
+       return string_clone_range( range, static_cast<Allocator&>( *this ) );
+}
+char* copy( const char* other ){
+       return string_clone( other, static_cast<Allocator&>( *this ) );
+}
+void destroy( char* string ){
+       string_release( string, string_length( string ), static_cast<Allocator&>( *this ) );
+}
 
 protected:
- ~CopiedBuffer()
-  {
-    destroy(m_string);
-  }
+~CopiedBuffer(){
+       destroy( m_string );
+}
 public:
-  CopiedBuffer()
-    : m_string(copy(""))
-  {
-  }
-  explicit CopiedBuffer(const Allocator& allocator)
-    : Allocator(allocator), m_string(copy(""))
-  {
-  }
-  CopiedBuffer(const CopiedBuffer& other)
-    : Allocator(other), m_string(copy(other.m_string))
-  {
-  }
-  CopiedBuffer(const char* string, const Allocator& allocator = Allocator())
-    : Allocator(allocator), m_string(copy(string))
-  {
-  }
-  CopiedBuffer(StringRange range, const Allocator& allocator = Allocator())
-    : Allocator(allocator), m_string(copy_range(range))
-  {
-  }
-  const char* c_str() const
-  {
-    return m_string;
-  }
-  void swap(CopiedBuffer& other)
-  {
-    string_swap(m_string, other.m_string);
-  }
+CopiedBuffer()
+       : m_string( copy( "" ) ){
+}
+explicit CopiedBuffer( const Allocator& allocator )
+       : Allocator( allocator ), m_string( copy( "" ) ){
+}
+CopiedBuffer( const CopiedBuffer& other )
+       : Allocator( other ), m_string( copy( other.m_string ) ){
+}
+CopiedBuffer( const char* string, const Allocator& allocator = Allocator() )
+       : Allocator( allocator ), m_string( copy( string ) ){
+}
+CopiedBuffer( StringRange range, const Allocator& allocator = Allocator() )
+       : Allocator( allocator ), m_string( copy_range( range ) ){
+}
+const char* c_str() const {
+       return m_string;
+}
+void swap( CopiedBuffer& other ){
+       string_swap( m_string, other.m_string );
+}
 };
 
 /// \brief A non-mutable string which uses copy-by-value for assignment.
@@ -490,77 +443,65 @@ typedef String< CopiedBuffer< DefaultAllocator<char> > > CopiedString;
 template<typename Allocator>
 class SmartBuffer : private Allocator
 {
-  char* m_buffer;
-
-  char* copy_range(StringRange range)
-  {
-    char* buffer = Allocator::allocate(sizeof(std::size_t) + (range.last - range.first) + 1);
-    strncpy(buffer + sizeof(std::size_t), range.first, range.last - range.first);
-    buffer[sizeof(std::size_t) + (range.last - range.first)] = '\0';
-    *reinterpret_cast<std::size_t*>(buffer) = 0;
-    return buffer;
-  }
-  char* copy(const char* string)
-  {
-    char* buffer = Allocator::allocate(sizeof(std::size_t) + string_length(string) + 1);
-    strcpy(buffer + sizeof(std::size_t), string);
-    *reinterpret_cast<std::size_t*>(buffer) = 0;
-    return buffer;
-  }
-  void destroy(char* buffer)
-  {
-    Allocator::deallocate(buffer, sizeof(std::size_t) + string_length(c_str()) + 1);
-  }
-
-  void incref(char* buffer)
-  {
-    ++(*reinterpret_cast<std::size_t*>(buffer));
-  }
-  void decref(char* buffer)
-  {
-    if(--(*reinterpret_cast<std::size_t*>(buffer)) == 0)
-      destroy(buffer);
-  }
+char* m_buffer;
+
+char* copy_range( StringRange range ){
+       char* buffer = Allocator::allocate( sizeof( std::size_t ) + ( range.last - range.first ) + 1 );
+       strncpy( buffer + sizeof( std::size_t ), range.first, range.last - range.first );
+       buffer[sizeof( std::size_t ) + ( range.last - range.first )] = '\0';
+       *reinterpret_cast<std::size_t*>( buffer ) = 0;
+       return buffer;
+}
+char* copy( const char* string ){
+       char* buffer = Allocator::allocate( sizeof( std::size_t ) + string_length( string ) + 1 );
+       strcpy( buffer + sizeof( std::size_t ), string );
+       *reinterpret_cast<std::size_t*>( buffer ) = 0;
+       return buffer;
+}
+void destroy( char* buffer ){
+       Allocator::deallocate( buffer, sizeof( std::size_t ) + string_length( c_str() ) + 1 );
+}
+
+void incref( char* buffer ){
+       ++( *reinterpret_cast<std::size_t*>( buffer ) );
+}
+void decref( char* buffer ){
+       if ( --( *reinterpret_cast<std::size_t*>( buffer ) ) == 0 ) {
+               destroy( buffer );
+       }
+}
 
 protected:
- ~SmartBuffer()
-  {
-    decref(m_buffer);
-  }
+~SmartBuffer(){
+       decref( m_buffer );
+}
 public:
-  SmartBuffer()
-    : m_buffer(copy(""))
-  {
-    incref(m_buffer);
-  }
-  explicit SmartBuffer(const Allocator& allocator)
-    : Allocator(allocator), m_buffer(copy(""))
-  {
-    incref(m_buffer);
-  }
-  SmartBuffer(const SmartBuffer& other)
-    : Allocator(other), m_buffer(other.m_buffer)
-  {
-    incref(m_buffer);
-  }
-  SmartBuffer(const char* string, const Allocator& allocator = Allocator())
-    : Allocator(allocator), m_buffer(copy(string))
-  {
-    incref(m_buffer);
-  }
-  SmartBuffer(StringRange range, const Allocator& allocator = Allocator())
-    : Allocator(allocator), m_buffer(copy_range(range))
-  {
-    incref(m_buffer);
-  }
-  const char* c_str() const
-  {
-    return m_buffer + sizeof(std::size_t);
-  }
-  void swap(SmartBuffer& other)
-  {
-    string_swap(m_buffer, other.m_buffer);
-  }
+SmartBuffer()
+       : m_buffer( copy( "" ) ){
+       incref( m_buffer );
+}
+explicit SmartBuffer( const Allocator& allocator )
+       : Allocator( allocator ), m_buffer( copy( "" ) ){
+       incref( m_buffer );
+}
+SmartBuffer( const SmartBuffer& other )
+       : Allocator( other ), m_buffer( other.m_buffer ){
+       incref( m_buffer );
+}
+SmartBuffer( const char* string, const Allocator& allocator = Allocator() )
+       : Allocator( allocator ), m_buffer( copy( string ) ){
+       incref( m_buffer );
+}
+SmartBuffer( StringRange range, const Allocator& allocator = Allocator() )
+       : Allocator( allocator ), m_buffer( copy_range( range ) ){
+       incref( m_buffer );
+}
+const char* c_str() const {
+       return m_buffer + sizeof( std::size_t );
+}
+void swap( SmartBuffer& other ){
+       string_swap( m_buffer, other.m_buffer );
+}
 };
 
 /// \brief A non-mutable string which uses copy-by-reference for assignment of SmartString.
@@ -569,42 +510,37 @@ typedef String< SmartBuffer< DefaultAllocator<char> > > SmartString;
 class StringEqualNoCase
 {
 public:
-  bool operator()(const CopiedString& key, const CopiedString& other) const
-  {
-    return string_equal_nocase(key.c_str(), other.c_str());
-  }
+bool operator()( const CopiedString& key, const CopiedString& other ) const {
+       return string_equal_nocase( key.c_str(), other.c_str() );
+}
 };
 
 struct StringLessNoCase
 {
-  bool operator()(const CopiedString& x, const CopiedString& y) const
-  {
-    return string_less_nocase(x.c_str(), y.c_str());
-  }
+       bool operator()( const CopiedString& x, const CopiedString& y ) const {
+               return string_less_nocase( x.c_str(), y.c_str() );
+       }
 };
 
 struct RawStringEqual
 {
-  bool operator()(const char* x, const char* y) const
-  {
-    return string_equal(x, y);
-  }
+       bool operator()( const char* x, const char* y ) const {
+               return string_equal( x, y );
+       }
 };
 
 struct RawStringLess
 {
-  bool operator()(const char* x, const char* y) const
-  {
-    return string_less(x, y);
-  }
+       bool operator()( const char* x, const char* y ) const {
+               return string_less( x, y );
+       }
 };
 
 struct RawStringLessNoCase
 {
-  bool operator()(const char* x, const char* y) const
-  {
-    return string_less_nocase(x, y);
-  }
+       bool operator()( const char* x, const char* y ) const {
+               return string_less_nocase( x, y );
+       }
 };
 
 #endif