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