1/* Copyright (c) 2012 Massachusetts Institute of Technology
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 * THE SOFTWARE.
20 */
21
22#ifndef __STRING_H__
23#define __STRING_H__
24
25#include <string>
26#include <cstdarg>
27#include <vector>
28#include <sstream>
29#include <bitset>
30
31namespace LibUtil
32{
33    using std::string;
34    using std::vector;
35
36    class String : public string
37    {
38        public:
39            static String format(const String& format_, ...);
40            static String format(const String& format_, va_list args_);
41            template<class T> static String toString(const T& value_);
42            static String toBitString(unsigned int value_, unsigned int num_bits_);
43            template<class T> static T fromString(const String& str_);
44
45        private:
46            static const unsigned int msBufferSize;
47
48        public:
49            String();
50            String(const string& str_);
51            String(const char* str_, size_t n);
52            String(const char* str_);
53            String(size_t n, char c);
54            String(int value_);
55            String(unsigned int value_);
56            String(long value_);
57            String(unsigned long value_);
58            String(float value_);
59            String(double value_);
60            String(bool value_);
61            ~String();
62
63        public:
64            // Remove leading and trailing whitespace
65            String& trim();
66            // Substitute str1 with str2
67            String& substitute(const String& str1_, const String& str2_);
68            // Split the String into vector of Strings separated by delimiters_
69            vector<String> split(const char* delimiters_) const;
70            vector<String> split(const String* delimiters_, unsigned int num_delimiters_ = 1) const;
71            vector<String> splitByString(const String& delimiters_) const;
72
73            // Check if contains str
74            bool contain(const String& str_) const;
75
76        public:
77            // Convertions
78            const char* toCString() const;
79            int toInt() const;
80            unsigned int toUInt() const;
81            long toLong() const;
82            unsigned long toULong() const;
83            float toFloat() const;
84            double toDouble() const;
85            bool toBool() const;
86            operator const char*() const;
87            operator int() const;
88            operator unsigned int() const;
89            operator long() const;
90            operator unsigned long() const;
91            operator float() const;
92            operator double() const;
93            operator bool() const;
94            String& operator=(char c_);
95    };
96
97    template<class T> String String::toString(const T& value_)
98    {
99        std::ostringstream ost;
100        ost << value_;
101        return ost.str();
102    }
103
104    template<> inline String String::toString<bool>(const bool& value_)
105    {
106        if(value_ == true)
107        {
108            return "TRUE";
109        }
110        else
111        {
112            return "FALSE";
113        }
114    }
115
116    inline String String::toBitString(unsigned int value_, unsigned int num_bits_)
117    {
118        std::bitset<sizeof(unsigned int)*8> bitSet(value_);
119        String ret = String(bitSet.to_string());
120        ret = ret.substr(ret.length()-num_bits_);
121        return ret;
122    }
123
124    template<class T> T String::fromString(const String& str_)
125    {
126        T ret;
127        std::istringstream ist(str_);
128        ist >> ret;
129        return ret;
130    }
131
132    template<> inline String String::fromString<String>(const String& str_)
133    {
134        return str_;
135    }
136
137    template<> inline bool String::fromString<bool>(const String& str_)
138    {
139        bool ret;
140        if((str_ == String("TRUE")) || (str_ == String("true")))
141        {
142            ret = true;
143        }
144        else if((str_ == string("FALSE")) || (str_ == String("false")))
145        {
146            ret = false;
147        }
148        else
149        {
150            //std::cerr << "Invalid bool value: " << str_ << std::endl;
151            throw ("Invalid bool value: " + str_);
152        }
153        return ret;
154    }
155
156    template<class T> String arrayToString(
157            const T* array_, unsigned int start_index_, unsigned int end_index_,
158            const String& delimiters_
159            )
160    {
161        // Ensure end_index_ >= start_index_ + 1
162        if(end_index_ <= start_index_)
163        {
164            throw("Invalid index range: start_index = " + (String)start_index_ + ", end_index = " + (String)end_index_);
165        }
166
167        String ret = "[";
168        for(unsigned int i = start_index_; i < (end_index_-1); ++i)
169        {
170            ret += (String)array_[i] + delimiters_;
171        }
172        ret += (String)array_[end_index_-1] + "]";
173        return ret;
174    }
175
176    template<class T> String arrayToString(const T* array_, unsigned int num_elements_)
177    {
178        return arrayToString(array_, 0, num_elements_, ", ");
179    }
180
181    template<class T> String arrayToString(const T* array_, unsigned int start_index_, unsigned int end_index_)
182    {
183        return arrayToString(array_, start_index_, end_index_);
184    }
185
186    template<class T> String vectorToString(
187        const vector<T>& vector_, unsigned int start_index_, unsigned int end_index_,
188        const String& delimiters_
189        )
190    {
191        // Ensure end_index_ >= start_index_ + 1, or if the vector is empty
192        if((end_index_ <= start_index_) || (end_index_ > vector_.size()))
193        {
194            // If the vector is empty, return empty array
195            if (vector_.size() == 0)
196                return "[]";
197
198            throw("Invalid index range: start_index = " + (String)start_index_ + ", end_index = " + (String)end_index_);
199        }
200
201        String ret = "[";
202        for(unsigned int i = start_index_; i < (end_index_-1); ++i)
203        {
204            ret += (String)vector_[i] + delimiters_;
205        }
206        ret += (String)vector_[end_index_-1] + "]";
207        return ret;
208    }
209
210    template<class T> String vectorToString(const vector<T>& vector_)
211    {
212        return vectorToString(vector_, 0, vector_.size(), ", ");
213    }
214
215    template<class T> String vectorToString(const vector<T>& vector_, unsigned int num_elements_)
216    {
217        return vectorToString(vector_, 0, num_elements_, ", ");
218    }
219
220    template<class T> String vectorToString(const vector<T>& vector_, unsigned int start_index_, unsigned int end_index_)
221    {
222        return vectorToString(vector_, start_index_, end_index_);
223    }
224
225    template<class T> vector<T> castStringVector(const vector<String>& vector_)
226    {
227        vector<T> ret_vector;
228        for(unsigned int i = 0; i < vector_.size(); ++i)
229        {
230            ret_vector.push_back((T)vector_[i]);
231        }
232        return ret_vector;
233    }
234
235    std::istream& safeGetline(std::istream& is_, String& str_);
236} // namespace LibUtil
237
238#endif // __STRING_H__
239
240