00001 #ifndef STR_HH
00002 #define STR_HH
00003
00004 #include <string>
00005 #include <vector>
00006 #include <stdexcept>
00007
00008 #include <stdio.h>
00009 #include <stdarg.h>
00010 #include <stdlib.h>
00011 #include <math.h>
00012
00017 namespace str {
00018
00024 inline std::string fmt(size_t size, const char *fmt, ...)
00025 {
00026 va_list ap;
00027 va_start(ap, fmt);
00028 char *buf = new char[size];
00029 vsnprintf(buf, size, fmt, ap);
00030 va_end(ap);
00031
00032 std::string str(buf);
00033 delete[] buf;
00034 return str;
00035 }
00036
00041 inline void clean(std::string &str, const char *chars = " \n\t")
00042 {
00043 int i;
00044
00045
00046
00047 for (i = str.length(); i > 0; i--)
00048 if (!strchr(chars, str[i - 1]))
00049 break;
00050 str.erase(i);
00051
00052
00053
00054 for (i = 0; i < (int)str.length(); i++)
00055 if (!strchr(chars, str[i]))
00056 break;
00057 str.erase(0, i);
00058 }
00059
00065 inline std::string cleaned(const std::string &str,
00066 const char *chars = " \n\t")
00067 {
00068 std::string ret = str;
00069 clean(ret, chars);
00070 return ret;
00071 }
00072
00084 inline std::vector<std::string>
00085 split(const std::string &str, const char *delims, bool group,
00086 unsigned int num_fields = 0)
00087 {
00088 std::vector<std::string> fields;
00089 size_t begin = 0;
00090 size_t end = 0;
00091
00092 fields.clear();
00093 bool delim_pending = false;
00094 while (begin < str.length()) {
00095
00096
00097 if (num_fields > 0 && fields.size() == num_fields - 1) {
00098 delim_pending = false;
00099 fields.push_back(str.substr(begin));
00100 break;
00101 }
00102
00103
00104 delim_pending = false;
00105 while (end < str.length()) {
00106 if (strchr(delims, str[end])) {
00107 delim_pending = true;
00108 break;
00109 }
00110 end++;
00111 }
00112 fields.push_back(str.substr(begin, end - begin));
00113
00114
00115 end++;
00116 if (group)
00117 while (end < str.length() && strchr(delims, str[end]))
00118 end++;
00119
00120 begin = end;
00121 }
00122
00123 if (delim_pending)
00124 fields.push_back("");
00125
00126 return fields;
00127 }
00128
00139 inline long str2long(const std::string &str, int base = 10)
00140 {
00141 char *endptr;
00142 const char *c_str = str.c_str();
00143
00144 long value = strtol(c_str, &endptr, base);
00145 if (value == LONG_MIN || value == LONG_MAX)
00146 throw std::out_of_range("str::str2long: argument out of range");
00147 if (*c_str == '\0' || *endptr != '\0')
00148 throw std::invalid_argument("str::str2long: invalid string");
00149
00150 return value;
00151 }
00152
00163 inline unsigned long str2ulong(const std::string &str, int base = 10)
00164 {
00165 char *endptr;
00166 const char *c_str = str.c_str();
00167
00168 unsigned long value = strtoul(c_str, &endptr, base);
00169 if (value == ULONG_MAX)
00170 throw std::out_of_range("str::str2ulong: argument out of range");
00171 if (*c_str == '\0' || *endptr != '\0')
00172 throw std::invalid_argument("str::str2ulong: invalid string");
00173
00174 return value;
00175 }
00176
00185 inline float str2float(const std::string &str)
00186 {
00187 char *endptr;
00188 const char *c_str = str.c_str();
00189
00190 float value = strtof(c_str, &endptr);
00191 if (value == -HUGE_VALF || value == HUGE_VALF)
00192 throw std::out_of_range("str::str2float: argument out of range");
00193 if (*c_str == '\0' || *endptr != '\0')
00194 throw std::invalid_argument("str::str2float: invalid string");
00195
00196 return value;
00197 }
00198
00199
00205 template <class T>
00206 std::vector<T> long_vec(const std::string &str)
00207 {
00208 std::vector<std::string> str_vec(
00209 str::split(str::cleaned(str), " \t\n", true));
00210 std::vector<T> vec(str_vec.size());
00211 for (size_t i = 0; i < str_vec.size(); i++)
00212 vec[i] = str::str2long(str_vec[i]);
00213 return vec;
00214 }
00215
00221 inline std::vector<float> float_vec(const std::string &str)
00222 {
00223 std::vector<std::string> str_vec(
00224 str::split(str::cleaned(str), " \t\n", true));
00225 std::vector<float> vec(str_vec.size());
00226 for (size_t i = 0; i < str_vec.size(); i++)
00227 vec[i] = str::str2float(str_vec[i]);
00228 return vec;
00229 }
00230
00236 inline std::string chomped(const std::string &str, const char *chars = "\n")
00237 {
00238 if (!str.empty() && strchr(chars, str[str.length() - 1]))
00239 return str.substr(0, str.length() - 1);
00240 return str;
00241 }
00242
00248 inline std::string &chomp(std::string &str, const char *chars = "\n")
00249 {
00250 if (!str.empty() && strchr(chars, str[str.length() - 1]))
00251 str.erase(str.end() - 1);
00252 return str;
00253 }
00254
00262 inline bool
00263 read_line(std::string &str, FILE *file = stdin, bool do_chomp = false)
00264 {
00265 char *ptr;
00266 char buf[4096];
00267
00268 str.erase();
00269 while (1) {
00270 ptr = fgets(buf, 4096, file);
00271 if (!ptr)
00272 break;
00273
00274 str.append(buf);
00275 if (str[str.length() - 1] == '\n') {
00276 break;
00277 }
00278 }
00279
00280 if (ferror(file) || str.length() == 0)
00281 return false;
00282
00283 if (do_chomp)
00284 chomp(str, "\n");
00285
00286 return true;
00287 }
00288
00289
00290 };
00291
00292 #endif