Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

more/gen/gc_string.h

Go to the documentation of this file.
00001 //  Copyright (C) 2001--2002  Petter Urkedal
00002 //
00003 //  This file is free software; you can redistribute it and/or modify
00004 //  it under the terms of the GNU General Public License as published by
00005 //  the Free Software Foundation; either version 2 of the License, or
00006 //  (at your option) any later version.
00007 //
00008 //  This file is distributed in the hope that it will be useful,
00009 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 //  GNU General Public License for more details.
00012 //
00013 //  You should have received a copy of the GNU General Public License
00014 //  along with this program; if not, write to the Free Software
00015 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00016 //
00017 //  As a special exception, you may use this file as part of a free
00018 //  software library without restriction.  Specifically, if other files
00019 //  instantiate templates or use macros or inline functions from this
00020 //  file, or you compile this file and link it with other files to
00021 //  produce an executable, this file does not by itself cause the
00022 //  resulting executable to be covered by the GNU General Public
00023 //  License.  This exception does not however invalidate any other
00024 //  reasons why the executable file might be covered by the GNU General
00025 //  Public License.
00026 //
00027 //  $Id: gc_string.h,v 1.2 2002/08/24 13:57:50 petter_urkedal Exp $
00028 
00029 
00030 #ifndef MORE_GEN_GC_STRING_H
00031 #define MORE_GEN_GC_STRING_H
00032 
00033 #include <more/bits/config.h>
00034 
00035 #include <bdwgc/gc.h>
00036 #include <cwchar>
00037 #include <cstdlib>
00038 #include <string>
00039 #include <algorithm>
00040 #include <iostream>
00041 #include <limits>
00042 
00043 
00044 namespace more {
00045 namespace gen {
00046 
00047   /** \internal */
00048   inline size_t cstrlen(char const* s) { return std::strlen(s); }
00049   /** \internal */
00050   inline size_t cstrlen(wchar_t const* s) { return std::wcslen(s); }
00051 
00052   template<typename Ch> inline      Ch* empty_c_str();
00053   template<>            inline    char* empty_c_str<char>()    { return ""; }
00054   template<>            inline wchar_t* empty_c_str<wchar_t>() { return L""; }
00055 
00056   /** \class basic_gc_string gc_string.h more/gen/gc_string.h
00057       A shallow copied garbage collected string to use for string
00058       literals.  With a limited set of operations, the string behaves
00059       as if deep copied.  (Actually, the operations which would break
00060       the deep-copy semantics, are excluded, at least for now.)  */
00061   template<typename Char>
00062     struct basic_gc_string
00063     {
00064         typedef Char char_type;
00065         typedef std::size_t size_type;
00066 //      typedef char_type* iterator;
00067         typedef char_type const* iterator;
00068         typedef char_type const* const_iterator;
00069         static const size_type npos = std::numeric_limits<size_type>::max();
00070 
00071         /** Construct an empty string. */
00072         basic_gc_string()
00073             : m_size(0),
00074               m_storage(0),
00075               m_ptr(empty_c_str<Char>()) {}
00076 
00077         /** Construct as a copy of c_str. */
00078         basic_gc_string(char_type const* c_str)
00079             : m_size(cstrlen(c_str)),
00080               m_storage(m_size+1),
00081               m_ptr(alloc(m_storage))
00082         {
00083             std::copy(c_str, c_str + m_size, m_ptr);
00084         }
00085 
00086         /** Construct from persistent constant storage.  The lifetime
00087             of c_str must be longer than that of the constructed
00088             string.  c_str is not explicitely allocated, so it may
00089             point to static or collected memory. c_str must be at
00090             least \a n characters. */
00091         basic_gc_string(char_type const* c_str, size_type n)
00092             : m_size(n),
00093               m_storage(0),
00094               m_ptr(const_cast<char_type*>(c_str)) {}
00095 
00096         /** Construct a shallow copy of x. */
00097         basic_gc_string(basic_gc_string const& x)
00098             : m_size(x.m_size),
00099               m_storage(0),
00100               m_ptr(x.m_ptr) {}
00101 
00102         /** Assign a shallow copy of x. */
00103         basic_gc_string&
00104         operator=(basic_gc_string const& x)
00105         {
00106             m_ptr = x.m_ptr;
00107             m_size = x.m_size;
00108             m_storage = 0;
00109             return *this;
00110         }
00111 
00112         /** Return the character an \a i. */
00113         char_type
00114         operator[](size_type i) const
00115         {
00116             return m_ptr[i];
00117         }
00118 
00119 //      iterator        begin() { return m_ptr; }
00120 //      iterator        end()   { return m_ptr + m_size; }
00121         const_iterator  begin() const { return m_ptr; }
00122         const_iterator  end()   const { return m_ptr + m_size; }
00123         size_type       size()  const { return m_size; }
00124         size_type       length() const { return m_size; }
00125         bool            empty() const { return m_size == 0; }
00126 
00127         basic_gc_string&
00128         append(char_type const* s, size_type n)
00129         {
00130             if (m_storage < m_size + n)
00131                 grow(m_size + n);
00132             std::copy(s, s + n, m_ptr + m_size);
00133             m_size += n;
00134             return *this;
00135         }
00136 
00137         basic_gc_string&
00138         append(char_type const* s)
00139         {
00140             return append(s, std::strlen(s));
00141         }
00142 
00143         basic_gc_string&
00144         append(basic_gc_string const& str, size_type pos, size_type n)
00145         {
00146             if (n > str.size() - pos)
00147                 n = str.size() - pos;
00148             return append(str.c_str() + pos, n);
00149         }
00150 
00151         basic_gc_string&
00152         append(basic_gc_string const& str)
00153         {
00154             return append(str.c_str(), str.size());
00155         }
00156 
00157         basic_gc_string&
00158         append(size_type n, char_type ch)
00159         {
00160             if (m_storage < m_size + n)
00161                 grow(m_size + n);
00162             std::fill(m_ptr + m_size, m_ptr + m_size + n, ch);
00163             m_size += n;
00164             return *this;
00165         }
00166 
00167         basic_gc_string&
00168         operator+=(char_type wc)
00169         {
00170             if (m_storage <= m_size)
00171                 grow(m_size + 1);
00172             m_ptr[m_size++] = wc;
00173             return *this;
00174         }
00175 
00176         basic_gc_string&
00177         operator+=(basic_gc_string const& rhs)
00178         {
00179             return append(rhs);
00180         }
00181 
00182         basic_gc_string&
00183         operator+=(Char const* rhs)
00184         {
00185             return append(rhs);
00186         }
00187 
00188         char_type const*
00189         c_str() const
00190         {
00191             if (m_storage <= m_size)
00192                 grow(m_size + 1);
00193             if (m_ptr[m_size] != 0)
00194                 m_ptr[m_size] = 0;
00195             return m_ptr;
00196         }
00197 
00198         friend void
00199         swap(basic_gc_string& x, basic_gc_string& y)
00200         {
00201             std::swap(x.m_ptr, y.m_ptr);
00202             std::swap(x.m_size, y.m_size);
00203             std::swap(x.m_storage, y.m_storage);
00204         }
00205 
00206         basic_gc_string
00207         substr(size_type i, size_type n = npos) const
00208         {
00209             if (i + n > m_size)
00210                 n = m_size - i;
00211             return basic_gc_string(m_ptr + i, n);
00212         }
00213 
00214       private:
00215         static Char*
00216         alloc(size_type size)
00217         {
00218             Char* ptr = static_cast<Char*>(GC_malloc(size*sizeof(Char)));
00219             if (!ptr) {
00220                 std::cerr << "Out of memory." << std::endl;
00221                 abort();
00222             }
00223             return ptr;
00224         }
00225 
00226         void
00227         grow(size_type minsize) const
00228         {
00229             char_type* old = m_ptr;
00230             m_storage = m_size*2;
00231             if (m_storage < minsize)
00232                 m_storage = minsize;
00233             m_ptr = alloc(m_storage);
00234             std::copy(old, old + m_size, m_ptr);
00235         }
00236 
00237         size_type m_size;
00238         mutable size_type m_storage;
00239         mutable char_type* m_ptr;
00240     };
00241 
00242   /** True if the strings are equal. */
00243   template<typename Char>
00244     inline bool
00245     operator==(basic_gc_string<Char> const& x, basic_gc_string<Char> const& y)
00246     {
00247         return x.size() == y.size()
00248             && std::equal(x.begin(), x.end(), y.begin());
00249     }
00250   template<typename Char>
00251     inline bool
00252     operator==(basic_gc_string<Char> const& x, Char const* y)
00253     {
00254         return x == basic_gc_string<Char>(y, cstrlen(y));
00255     }
00256   template<typename Char>
00257     inline bool
00258     operator==(Char const* x, basic_gc_string<Char> const& y)
00259     {
00260         return basic_gc_string<Char>(x, cstrlen(x)) == y;
00261     }
00262 
00263   /** An arbitrary full ordering of strings. Use locale specific versions
00264       for dictionary ordering. */
00265   template<typename Char>
00266     inline bool
00267     operator<(basic_gc_string<Char> const& x, basic_gc_string<Char> const& y)
00268     {
00269         return std::lexicographical_compare(x.begin(), x.end(),
00270                                             y.begin(), y.end());
00271     }
00272   template<typename Char>
00273     inline bool
00274     operator<(basic_gc_string<Char> const& x, Char const* y)
00275     {
00276         return x < basic_gc_string<Char>(y, cstrlen(y));
00277     }
00278   template<typename Char>
00279     inline bool
00280     operator<(Char const* x, basic_gc_string<Char> const& y)
00281     {
00282         return basic_gc_string<Char>(x, cstrlen(x)) < y;
00283     }
00284 
00285   /** Concatenation of two strings. */
00286   template<typename Char>
00287     inline basic_gc_string<Char>
00288     operator+(basic_gc_string<Char> const& x, basic_gc_string<Char> const& y)
00289     {
00290         typename basic_gc_string<Char>::size_type n = x.size();
00291         typename basic_gc_string<Char>::size_type k = n + y.size();
00292         Char* s = static_cast<Char*>(GC_malloc((k + 1)*sizeof(Char)));
00293         std::copy(x.begin(), x.end(), s);
00294         std::copy(y.begin(), y.end(), s + n);
00295         return basic_gc_string<Char>(s, k);
00296     }
00297 
00298   template<typename Char>
00299     inline basic_gc_string<Char>
00300     operator+(Char const* x, basic_gc_string<Char> y)
00301     {
00302         return basic_gc_string<Char>(x, cstrlen(x)) + y;
00303     }
00304 
00305   template<typename Char>
00306     inline basic_gc_string<Char>
00307     operator+(basic_gc_string<Char> x, Char const* y)
00308     {
00309         return x + basic_gc_string<Char>(y, cstrlen(y));
00310     }
00311 
00312   typedef basic_gc_string<char> gc_string;
00313   typedef basic_gc_string<wchar_t> gc_wstring;
00314 
00315   inline std::ostream&
00316   operator<<(std::ostream& os, gc_string const& str)
00317   {
00318       os.write(str.begin(), str.size());
00319       return os;
00320   }
00321 
00322 }}
00323 
00324 #endif

Generated on Sat Sep 7 19:11:12 2002 for more with Doxygen 1.2.13.1. Doxygen 1.2.13.1 is written and copyright 1997-2002 by Dimitri van Heesch.