00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
00048 inline size_t cstrlen(char const* s) { return std::strlen(s); }
00049
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
00057
00058
00059
00060
00061 template<typename Char>
00062 struct basic_gc_string
00063 {
00064 typedef Char char_type;
00065 typedef std::size_t size_type;
00066
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
00072 basic_gc_string()
00073 : m_size(0),
00074 m_storage(0),
00075 m_ptr(empty_c_str<Char>()) {}
00076
00077
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
00087
00088
00089
00090
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
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
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
00113 char_type
00114 operator[](size_type i) const
00115 {
00116 return m_ptr[i];
00117 }
00118
00119
00120
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
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
00264
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
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