String.cc revision 10447:a465576671d4
1#include "String.h"
2
3#include <cstdarg>
4#include <cstdio>
5#include <iostream>
6#include <ios>
7
8namespace LibUtil
9{
10    const unsigned int String::msBufferSize = 4096;
11
12    String String::format(const String& format_, ...)
13    {
14        char buffer[msBufferSize];
15
16        va_list args;
17        va_start(args, format_);
18        vsnprintf(buffer, msBufferSize, format_.c_str(), args);
19        va_end(args);
20
21        return (String)(buffer);
22    }
23
24    String String::format(const String& format_, va_list args_)
25    {
26        char buffer[msBufferSize];
27
28        vsnprintf(buffer, msBufferSize, format_.c_str(), args_);
29
30        return (String)(buffer);
31    }
32
33    String::String()
34    {}
35
36    String::String(const string& str_)
37        : string(str_)
38    {}
39
40    String::String(const char* str_, size_t n_)
41        : string(str_, n_)
42    {}
43
44    String::String(const char* str_)
45        : string(str_)
46    {}
47
48    String::String(size_t n_, char c_)
49        : string(n_, c_)
50    {}
51
52    String::String(int value_)
53        : string(toString<int>(value_))
54    {}
55
56    String::String(unsigned int value_)
57        : string(toString<unsigned int>(value_))
58    {}
59
60    String::String(long value_)
61        : string(toString<long>(value_))
62    {}
63
64    String::String(unsigned long value_)
65        : string(toString<unsigned long>(value_))
66    {}
67
68    String::String(float value_)
69        : string(toString<float>(value_))
70    {}
71
72    String::String(double value_)
73        : string(toString<double>(value_))
74    {}
75
76    String::String(bool value_)
77        : string(toString<bool>(value_))
78    {}
79
80    String::~String()
81    {}
82
83    String& String::trim()
84    {
85        // Remove leading and trailing whitespace
86        static const char whitespace[] = " \n\t\v\r\f";
87        erase(0, find_first_not_of(whitespace));
88        erase(find_last_not_of(whitespace) + 1U);
89        return (*this);
90    }
91
92    String& String::substitute(const String& str1_, const String& str2_)
93    {
94        size_t str1Size = str1_.size();
95        size_t str2Size = str2_.size();
96
97        size_t pos;
98        pos = find(str1_);
99        while(pos != string::npos)
100        {
101            replace(pos, str1Size, str2_);
102            pos += str2Size;
103            pos = find(str1_, pos);
104        }
105        return (*this);
106    }
107
108    vector<String> String::split(const char* delimiters_) const
109    {
110        vector<String> result;
111
112        if(size() == 0)
113        {
114            return result;
115        }
116
117        size_t currPos, nextPos;
118        currPos = 0;
119        nextPos = find_first_of(delimiters_);
120        while(1)
121        {
122            if(nextPos == string::npos)
123            {
124                if(currPos != size())
125                {
126                    result.push_back(substr(currPos));
127                }
128                break;
129            }
130
131            if(nextPos != currPos)
132            {
133                result.push_back(substr(currPos, nextPos - currPos));
134            }
135            currPos = nextPos + 1;
136            nextPos = find_first_of(delimiters_, currPos);
137        }
138
139        return result;
140    }
141
142    vector<String> String::split(const String* delimiters_, unsigned int num_delimiters_) const
143    {
144        vector<String> result;
145
146        if(size() == 0)
147        {
148            return result;
149        }
150
151        if(num_delimiters_ == 1)
152        {
153            size_t currPos, nextPos;
154            currPos = 0;
155            nextPos = find(delimiters_[0]);
156            while(1)
157            {
158                if(nextPos == String::npos)
159                {
160                    result.push_back(substr(currPos));
161                    break;
162                }
163
164                if(nextPos != currPos)
165                {
166                    result.push_back(substr(currPos, nextPos - currPos));
167                }
168                currPos = nextPos + delimiters_[0].size();
169                nextPos = find(delimiters_[0], currPos);
170            }
171        }
172        else
173        {
174            // Currently the length of the delimiters are not checked
175            unsigned int delimiterLength = 0;
176            size_t currPos, nextPos;
177            currPos = 0;
178            nextPos = size();
179            for(unsigned int i = 0; i < num_delimiters_; ++i)
180            {
181                size_t tempPos = find(delimiters_[i], currPos);
182                if((tempPos != String::npos) && (tempPos < nextPos))
183                {
184                    nextPos = tempPos;
185                    delimiterLength = delimiters_[i].size();
186                }
187            }
188            while(1)
189            {
190                if((nextPos == String::npos) || (nextPos == size()))
191                {
192                    result.push_back(substr(currPos));
193                    break;
194                }
195
196                if(nextPos != currPos)
197                {
198                    result.push_back(substr(currPos, nextPos - currPos));
199                }
200                currPos = nextPos + delimiterLength;
201                nextPos = size();
202                delimiterLength = 0;
203                for(unsigned int i = 0; i < num_delimiters_; ++i)
204                {
205                    size_t tempPos = find(delimiters_[i], currPos);
206                    if((tempPos != String::npos) && (tempPos < nextPos))
207                    {
208                        nextPos = tempPos;
209                        delimiterLength = delimiters_[i].size();
210                    }
211                }
212            }
213        }
214        return result;
215    }
216
217    vector<String> String::splitByString(const String& delimiter_) const
218    {
219        return split(&delimiter_, 1);
220    }
221
222    bool String::contain(const String& str_) const
223    {
224        return (find(str_) != String::npos);
225    }
226
227    const char* String::toCString() const
228    {
229        return this->c_str();
230    }
231
232    int String::toInt() const
233    {
234        return fromString<int>(*this);
235    }
236
237    unsigned int String::toUInt() const
238    {
239        return fromString<unsigned int>(*this);
240    }
241
242    long String::toLong() const
243    {
244        return fromString<long>(*this);
245    }
246
247    unsigned long String::toULong() const
248    {
249        return fromString<unsigned long>(*this);
250    }
251
252    float String::toFloat() const
253    {
254        return fromString<float>(*this);
255    }
256
257    double String::toDouble() const
258    {
259        return fromString<double>(*this);
260    }
261
262    bool String::toBool() const
263    {
264        return fromString<bool>(*this);
265    }
266
267    String::operator const char*() const
268    {
269        return this->c_str();
270    }
271
272    String::operator int() const
273    {
274        return fromString<int>(*this);
275    }
276
277    String::operator unsigned int() const
278    {
279        return fromString<unsigned int>(*this);
280    }
281
282    String::operator long() const
283    {
284        return fromString<long>(*this);
285    }
286
287    String::operator unsigned long() const
288    {
289        return fromString<unsigned long>(*this);
290    }
291
292    String::operator float() const
293    {
294        return fromString<float>(*this);
295    }
296
297    String::operator double() const
298    {
299        return fromString<double>(*this);
300    }
301
302    String::operator bool() const
303    {
304        return fromString<bool>(*this);
305    }
306
307    String& String::operator=(char c_)
308    {
309        this->assign(1, c_);
310        return *this;
311    }
312
313    std::istream& safeGetline(std::istream& is_, String& str_)
314    {
315        str_.clear();
316
317        // The characters in the stream are read one-by-one using a std::streambuf.
318        // That is faster than reading them one-by-one using the std::istream.
319        // Code that uses streambuf this way must be guarded by a sentry object.
320        // The sentry object performs various tasks,
321        // such as thread synchronization and updating the stream state.
322
323        std::istream::sentry se(is_, true);
324        std::streambuf* sb = is_.rdbuf();
325
326        while(1)
327        {
328            int c = sb->sbumpc();
329            switch(c)
330            {
331                case '\r':
332                    c = sb->sgetc();
333                    if(c == '\n')
334                        sb->sbumpc();
335                    return is_;
336                case '\n':
337                    return is_;
338                case EOF:
339                    is_.setstate(std::ios_base::failbit|std::ios_base::eofbit);
340                    return is_;
341                default:
342                    str_ += String(1, (char)c);
343            }
344        }
345    }
346} // namespace LibUtil
347
348