comparison packages/language/cxx/ustl/current/src/ustring.cpp @ 2904:88af52c64ce4

* ecos.db: Add uSTL library package record. * language/cxx/ustl/*: Initial check-in of the port of uSTL 1.3 to eCos contributed by Uwe Kindler.
author jld
date Thu, 20 Aug 2009 17:00:30 +0000
parents
children 4885e0722884
comparison
equal deleted inserted replaced
2903:4fc5c84f2234 2904:88af52c64ce4
1 // This file is part of the uSTL library, an STL implementation.
2 //
3 // Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net>
4 // This file is free software, distributed under the MIT License.
5
6 #include "ustring.h"
7 #include "mistream.h"
8 #include "mostream.h"
9 #include "ualgo.h"
10 #include <stdio.h> // for vsnprintf (in string::format)
11
12 namespace ustl {
13
14 //----------------------------------------------------------------------
15
16 const uoff_t string::npos;
17
18 //----------------------------------------------------------------------
19
20 /// Assigns itself the value of string \p s
21 string::string (const string& s)
22 : memblock ((s.size()+1) & (s.is_linked()-1)) // Allocate with terminator if not linked (can't call virtuals from base ctor)
23 {
24 if (s.is_linked())
25 relink (s.c_str(), s.size());
26 else {
27 copy_n (s.begin(), size(), begin());
28 relink (begin(), size()-1); // --m_Size
29 }
30 }
31
32 /// Links to \p s
33 string::string (const_pointer s)
34 : memblock ()
35 {
36 if (!s) s = "";
37 relink (s, strlen(s));
38 }
39
40 /// Creates a string of length \p n filled with character \p c.
41 string::string (size_type n, value_type c)
42 : memblock (n+1) // because base ctor can't call virtuals of this class
43 {
44 relink (begin(), size()-1); // --m_Size
45 fill_n (begin(), n, c);
46 at(n) = 0;
47 }
48
49 /// Resize the string to \p n characters. New space contents is undefined.
50 void string::resize (size_type n)
51 {
52 if (!(n | memblock::capacity()))
53 return (relink ("",0));
54 memblock::resize (n);
55 at(n) = 0;
56 }
57
58 /// Assigns itself the value of string \p s
59 void string::assign (const_pointer s)
60 {
61 if (!s) s = "";
62 assign (s, strlen (s));
63 }
64
65 /// Assigns itself the value of string \p s of length \p len.
66 void string::assign (const_pointer s, size_type len)
67 {
68 while (len && s[len - 1] == 0)
69 -- len;
70 resize (len);
71 copy (s, len);
72 }
73
74 /// Appends to itself the value of string \p s of length \p len.
75 void string::append (const_pointer s)
76 {
77 if (!s) s = "";
78 append (s, strlen (s));
79 }
80
81 /// Appends to itself the value of string \p s of length \p len.
82 void string::append (const_pointer s, size_type len)
83 {
84 while (len && s[len - 1] == 0)
85 -- len;
86 resize (size() + len);
87 copy_n (s, len, end() - len);
88 }
89
90 /// Appends to itself \p n characters of value \p c.
91 void string::append (size_type n, value_type c)
92 {
93 resize (size() + n);
94 fill_n (end() - n, n, c);
95 }
96
97 /// Copies into itself at offset \p start, the value of string \p p of length \p n.
98 string::size_type string::copyto (pointer p, size_type n, const_iterator start) const
99 {
100 assert (p && n);
101 if (!start)
102 start = begin();
103 const size_type btc = min(n-1, size());
104 copy_n (start, btc, p);
105 p[btc] = 0;
106 return (btc+1);
107 }
108
109 /// Returns comparison value regarding string \p s.
110 /// The return value is:
111 /// \li 1 if this string is greater (by value, not length) than string \p s
112 /// \li 0 if this string is equal to string \p s
113 /// \li -1 if this string is less than string \p s
114 ///
115 /*static*/ int string::compare (const_iterator first1, const_iterator last1, const_iterator first2, const_iterator last2)
116 {
117 assert (first1 <= last1 && (first2 <= last2 || !last2) && "Negative ranges result in memory allocation errors.");
118 const size_type len1 = distance (first1, last1), len2 = distance (first2, last2);
119 const int rvbylen = sign (int(len1 - len2));
120 int rv = memcmp (first1, first2, min (len1, len2));
121 return (rv ? rv : rvbylen);
122 }
123
124 /// Returns true if this string is equal to string \p s.
125 bool string::operator== (const_pointer s) const
126 {
127 if (!s) s = "";
128 return (size() == strlen(s) && 0 == memcmp (c_str(), s, size()));
129 }
130
131 /// Returns the beginning of character \p i.
132 string::const_iterator string::wiat (uoff_t i) const
133 {
134 utf8in_iterator<string::const_iterator> cfinder (begin());
135 cfinder += i;
136 return (cfinder.base());
137 }
138
139 /// Inserts wide character \p c at \p ipo \p n times as a UTF-8 string.
140 ///
141 /// \p ipo is a byte position, not a character position, and is intended
142 /// to be obtained from one of the find functions. Generally you are not
143 /// able to know the character position in a localized string; different
144 /// languages will have different character counts, so use find instead.
145 ///
146 void string::insert (const uoff_t ipo, wchar_t c, size_type n)
147 {
148 iterator ip (iat(ipo));
149 ip = iterator (memblock::insert (memblock::iterator(ip), n * Utf8Bytes(c)));
150 fill_n (utf8out (ip), n, c);
151 *end() = 0;
152 }
153
154 /// Inserts sequence of wide characters at \p ipo (byte position from a find call)
155 void string::insert (const uoff_t ipo, const wchar_t* first, const wchar_t* last, const size_type n)
156 {
157 iterator ip (iat(ipo));
158 size_type nti = distance (first, last), bti = 0;
159 for (uoff_t i = 0; i < nti; ++ i)
160 bti += Utf8Bytes(first[i]);
161 ip = iterator (memblock::insert (memblock::iterator(ip), n * bti));
162 utf8out_iterator<string::iterator> uout (utf8out (ip));
163 for (uoff_t j = 0; j < n; ++ j)
164 for (uoff_t k = 0; k < nti; ++ k, ++ uout)
165 *uout = first[k];
166 *end() = 0;
167 }
168
169 /// Inserts character \p c into this string at \p start.
170 string::iterator string::insert (iterator start, const_reference c, size_type n)
171 {
172 start = iterator (memblock::insert (memblock::iterator(start), n));
173 fill_n (start, n, c);
174 *end() = 0;
175 return (start);
176 }
177
178 /// Inserts \p count instances of string \p s at offset \p start.
179 string::iterator string::insert (iterator start, const_pointer s, size_type n)
180 {
181 if (!s) s = "";
182 return (insert (start, s, s + strlen(s), n));
183 }
184
185 /// Inserts [first,last] \p n times.
186 string::iterator string::insert (iterator start, const_pointer first, const_pointer last, size_type n)
187 {
188 assert (first <= last);
189 assert (begin() <= start && end() >= start);
190 assert ((first < begin() || first >= end() || size() + abs_distance(first,last) < capacity()) && "Insertion of self with autoresize is not supported");
191 start = iterator (memblock::insert (memblock::iterator(start), distance(first, last) * n));
192 fill (memblock::iterator(start), first, distance(first, last), n);
193 *end() = 0;
194 return (start);
195 }
196
197 /// Erases \p size bytes at \p ep.
198 string::iterator string::erase (iterator ep, size_type n)
199 {
200 string::iterator rv = memblock::erase (memblock::iterator(ep), n);
201 *end() = 0;
202 return (rv);
203 }
204
205 /// Erases \p n bytes at byte offset \p epo.
206 void string::erase (uoff_t epo, size_type n)
207 {
208 erase (iat(epo), n);
209 }
210
211 /// Replaces range [\p start, \p start + \p len] with string \p s.
212 void string::replace (iterator first, iterator last, const_pointer s)
213 {
214 if (!s) s = "";
215 replace (first, last, s, s + strlen(s));
216 }
217
218 /// Replaces range [\p start, \p start + \p len] with \p count instances of string \p s.
219 void string::replace (iterator first, iterator last, const_pointer i1, const_pointer i2, size_type n)
220 {
221 assert (first <= last);
222 assert (n || distance(first, last));
223 assert (first >= begin() && first <= end() && last >= first && last <= end());
224 assert ((i1 < begin() || i1 >= end() || abs_distance(i1,i2) * n + size() < capacity()) && "Replacement by self can not autoresize");
225 const size_type bte = distance(first, last), bti = distance(i1, i2) * n;
226 if (bti < bte)
227 first = iterator (memblock::erase (memblock::iterator(first), bte - bti));
228 else if (bte < bti)
229 first = iterator (memblock::insert (memblock::iterator(first), bti - bte));
230 fill (memblock::iterator(first), i1, distance(i1, i2), n);
231 *end() = 0;
232 }
233
234 /// Returns the offset of the first occurence of \p c after \p pos.
235 uoff_t string::find (const_reference c, uoff_t pos) const
236 {
237 const_iterator found = ::ustl::find (iat(pos), end(), c);
238 return (found < end() ? distance(begin(),found) : npos);
239 }
240
241 /// Returns the offset of the first occurence of substring \p s of length \p n after \p pos.
242 uoff_t string::find (const string& s, uoff_t pos) const
243 {
244 if (s.empty() || s.size() > size() - pos)
245 return (npos);
246 const uoff_t endi = s.size() - 1;
247 const_reference endchar = s[endi];
248 uoff_t lastPos = endi;
249 while (lastPos-- && s[lastPos] != endchar) ;
250 const size_type skip = endi - lastPos;
251 const_iterator i = iat(pos) + endi;
252 for (; i < end() && (i = ::ustl::find (i, end(), endchar)) < end(); i += skip)
253 if (memcmp (i - endi, s.c_str(), s.size()) == 0)
254 return (distance (begin(), i) - endi);
255 return (npos);
256 }
257
258 /// Returns the offset of the last occurence of character \p c before \p pos.
259 uoff_t string::rfind (const_reference c, uoff_t pos) const
260 {
261 for (int i = min(pos,size()-1); i >= 0; --i)
262 if (at(i) == c)
263 return (i);
264 return (npos);
265 }
266
267 /// Returns the offset of the last occurence of substring \p s of size \p n before \p pos.
268 uoff_t string::rfind (const string& s, uoff_t pos) const
269 {
270 const_iterator d = iat(pos) - 1;
271 const_iterator sp = begin() + s.size() - 1;
272 const_iterator m = s.end() - 1;
273 for (long int i = 0; d > sp && size_type(i) < s.size(); -- d)
274 for (i = 0; size_type(i) < s.size(); ++ i)
275 if (m[-i] != d[-i])
276 break;
277 return (d > sp ? distance (begin(), d + 2 - s.size()) : npos);
278 }
279
280 /// Returns the offset of the first occurence of one of characters in \p s of size \p n after \p pos.
281 uoff_t string::find_first_of (const string& s, uoff_t pos) const
282 {
283 for (uoff_t i = min(pos,size()); i < size(); ++ i)
284 if (s.find (at(i)) != npos)
285 return (i);
286 return (npos);
287 }
288
289 /// Returns the offset of the first occurence of one of characters not in \p s of size \p n after \p pos.
290 uoff_t string::find_first_not_of (const string& s, uoff_t pos) const
291 {
292 for (uoff_t i = min(pos,size()); i < size(); ++ i)
293 if (s.find (at(i)) == npos)
294 return (i);
295 return (npos);
296 }
297
298 /// Returns the offset of the last occurence of one of characters in \p s of size \p n before \p pos.
299 uoff_t string::find_last_of (const string& s, uoff_t pos) const
300 {
301 for (int i = min(pos,size()-1); i >= 0; -- i)
302 if (s.find (at(i)) != npos)
303 return (i);
304 return (npos);
305 }
306
307 /// Returns the offset of the last occurence of one of characters not in \p s of size \p n before \p pos.
308 uoff_t string::find_last_not_of (const string& s, uoff_t pos) const
309 {
310 for (int i = min(pos,size()-1); i >= 0; -- i)
311 if (s.find (at(i)) == npos)
312 return (i);
313 return (npos);
314 }
315
316 /// Equivalent to a vsprintf on the string.
317 int string::vformat (const char* fmt, va_list args)
318 {
319 #if HAVE_VA_COPY
320 va_list args2;
321 #else
322 #define args2 args
323 #undef __va_copy
324 #define __va_copy(x,y)
325 #endif
326 size_t rv = size();
327 do {
328 reserve (rv);
329 __va_copy (args2, args);
330 rv = vsnprintf (data(), memblock::capacity(), fmt, args2);
331 rv = min (rv, memblock::capacity());
332 } while (rv > capacity());
333 resize (min (rv, capacity()));
334 return (rv);
335 }
336
337 /// Equivalent to a sprintf on the string.
338 int string::format (const char* fmt, ...)
339 {
340 va_list args;
341 va_start (args, fmt);
342 const int rv = vformat (fmt, args);
343 va_end (args);
344 return (rv);
345 }
346
347 /// Returns the number of bytes required to write this object to a stream.
348 size_t string::stream_size (void) const
349 {
350 return (Utf8Bytes(size()) + size());
351 }
352
353 /// Reads the object from stream \p os
354 void string::read (istream& is)
355 {
356 char szbuf [8];
357 is >> szbuf[0];
358 size_t szsz (Utf8SequenceBytes (szbuf[0]) - 1), n = 0;
359 if (!is.verify_remaining ("read", "ustl::string", szsz)) return;
360 is.read (szbuf + 1, szsz);
361 n = *utf8in(szbuf);
362 if (!is.verify_remaining ("read", "ustl::string", n)) return;
363 resize (n);
364 is.read (data(), size());
365 }
366
367 /// Writes the object to stream \p os
368 void string::write (ostream& os) const
369 {
370 const written_size_type sz (size());
371 assert (sz == size() && "No support for writing strings larger than 4G");
372
373 char szbuf [8];
374 utf8out_iterator<char*> szout (szbuf);
375 *szout = sz;
376 size_t szsz = distance (szbuf, szout.base());
377
378 if (!os.verify_remaining ("write", "ustl::string", szsz + sz)) return;
379 os.write (szbuf, szsz);
380 os.write (cdata(), sz);
381 }
382
383 /// Returns a hash value for [first, last)
384 /*static*/ hashvalue_t string::hash (const char* first, const char* last)
385 {
386 hashvalue_t h = 0;
387 // This has the bits flowing into each other from both sides of the number
388 for (; first < last; ++ first)
389 h = *first + ((h << 7) | (h >> (BitsInType(hashvalue_t) - 7)));
390 return (h);
391 }
392
393 string::size_type string::minimumFreeCapacity (void) const throw() { return (1); }
394
395 } // namespace ustl