00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <float.h>
00021 #include <ctype.h>
00022 #include <stdio.h>
00023
00024 #include <vector>
00025 #include <string>
00026 #include <iostream>
00027
00028 #include <archon/util/text.H>
00029
00030 using namespace std;
00031
00032 namespace Archon
00033 {
00034 namespace Utilities
00035 {
00036 namespace Text
00037 {
00038 string toString(void *v)
00039 {
00040 char buf[100];
00041 sprintf(buf, "%p", v);
00042 return buf;
00043 }
00044
00045 string toString(bool v)
00046 {
00047 return v ? "true" : "false";
00048 }
00049
00050 string toString(short v)
00051 {
00052 char buf[100];
00053 sprintf(buf, "%hd", v);
00054 return buf;
00055 }
00056
00057 string toString(unsigned short v)
00058 {
00059 char buf[100];
00060 sprintf(buf, "%hu", v);
00061 return buf;
00062 }
00063
00064 string toString(int v)
00065 {
00066 char buf[100];
00067 sprintf(buf, "%d", v);
00068 return buf;
00069 }
00070
00071 string toString(unsigned v)
00072 {
00073 char buf[100];
00074 sprintf(buf, "%u", v);
00075 return buf;
00076 }
00077
00078 string toString(long v)
00079 {
00080 char buf[100];
00081 sprintf(buf, "%ld", v);
00082 return buf;
00083 }
00084
00085 string toString(unsigned long v)
00086 {
00087 char buf[100];
00088 sprintf(buf, "%lu", v);
00089 return buf;
00090 }
00091
00092 string toString(float v)
00093 {
00094 char buf[100];
00095 sprintf(buf, "%g", static_cast<double>(v));
00096 return buf;
00097 }
00098
00099 string toString(double v)
00100 {
00101 char buf[100];
00102 sprintf(buf, "%.10g", v);
00103 return buf;
00104 }
00105
00106 string toString(long double v)
00107 {
00108 char buf[100];
00109 sprintf(buf, "%.15Lg", v);
00110 return buf;
00111 }
00112
00113
00114 bool isPrefixOf(string prefix, string s, bool ignoreCase)
00115 {
00116 return ignoreCase ?
00117 compareIgnoreCase(prefix, s.substr(0, prefix.size())) == 0 :
00118 s.compare(0, prefix.size(), prefix) == 0;
00119 }
00120
00121 bool isSuffixOf(string suffix, string s, bool ignoreCase)
00122 {
00123 return s.size() >= suffix.size() &&
00124 (ignoreCase ?
00125 compareIgnoreCase(suffix, s.substr(s.size()-suffix.size())) == 0 :
00126 s.compare(s.size()-suffix.size(), string::npos, suffix) == 0);
00127 }
00128
00129 string toLowerCase(string s)
00130 {
00131 string::iterator i = s.begin();
00132 while(i != s.end())
00133 {
00134 *i = static_cast<char>(tolower(*i));
00135 ++i;
00136 }
00137 return s;
00138 }
00139
00140 string toUpperCase(string s)
00141 {
00142 string::iterator i = s.begin();
00143 while(i != s.end())
00144 {
00145 *i = static_cast<char>(toupper(*i));
00146 ++i;
00147 }
00148 return s;
00149 }
00150
00151 string initCap(string s)
00152 {
00153 if(s.size())
00154 s[0] = static_cast<char>(toupper(s[0]));
00155 return s;
00156 }
00157
00158 string trim(string s)
00159 {
00160 string::iterator i = s.begin();
00161 while(i != s.end() && isspace(static_cast<unsigned char>(*i))) ++i;
00162 string::iterator j = s.end();
00163 while(i != j && isspace(static_cast<unsigned char>(*(j-1)))) --j;
00164 return string(i, j);
00165 }
00166
00167 string lineTrim(string s)
00168 {
00169 string::iterator i = s.begin();
00170 string::iterator f = i;
00171 while(i != s.end() && isspace(static_cast<unsigned char>(*i)))
00172 {
00173 char c = *i++;
00174 if(c == '\n' || c == '\r') f = i;
00175 }
00176 string::iterator j = s.end();
00177 while(i != j && isspace(static_cast<unsigned char>(*(j-1)))) --j;
00178 return i == j ? "" : string(f, j);
00179 }
00180
00181 int compareIgnoreCase(const string &a, const string &b)
00182 {
00183 string::const_iterator i = a.begin();
00184 string::const_iterator j = b.begin();
00185 while(i != a.end() && j != b.end())
00186 {
00187 const int ca = toupper(static_cast<unsigned char>(*i));
00188 const int cb = toupper(static_cast<unsigned char>(*j));
00189 if(ca != cb) return ca - cb;
00190 ++i;
00191 ++j;
00192 }
00193 return a.size() - b.size();
00194 }
00195
00196 string escapeNonprintable(const string &s)
00197 {
00198 string t;
00199 t+='"';
00200 t.reserve(s.size()+2);
00201 for(unsigned i=0; i<s.size(); ++i)
00202 {
00203 const int ch = static_cast<unsigned char>(s[i]);
00204 switch(ch)
00205 {
00206 case '\n': t+="\\n"; break;
00207 case '\t': t+="\\t"; break;
00208 case '\v': t+="\\v"; break;
00209 case '\b': t+="\\b"; break;
00210 case '\r': t+="\\r"; break;
00211 case '\f': t+="\\f"; break;
00212 case '\a': t+="\\a"; break;
00213 case '\\': t+="\\\\"; break;
00214 case '"' : t+="\\\""; break;
00215 default:
00216 if(ch <= 0x1f || ch >= 0x7f && ch <= 0xa0 || ch == 0xad)
00217 {
00218 char buffer[8];
00219 sprintf(buffer, "\\x%02x", ch);
00220 t+=buffer;
00221 }
00222 else t+=ch;
00223 }
00224 }
00225 t+='"';
00226 return t;
00227 }
00228
00233 ustring escapeNonprintable(const ustring &s)
00234 {
00235 ustring t;
00236 t+='"';
00237 t.reserve(s.size()+2);
00238 for(unsigned i=0; i<s.size(); ++i)
00239 {
00240 const uchar ch = s[i];
00241 switch(ch)
00242 {
00243 case '\n': t+=Unicode::decodeUtf8("\\n"); break;
00244 case '\t': t+=Unicode::decodeUtf8("\\t"); break;
00245 case '\v': t+=Unicode::decodeUtf8("\\v"); break;
00246 case '\b': t+=Unicode::decodeUtf8("\\b"); break;
00247 case '\r': t+=Unicode::decodeUtf8("\\r"); break;
00248 case '\f': t+=Unicode::decodeUtf8("\\f"); break;
00249 case '\a': t+=Unicode::decodeUtf8("\\a"); break;
00250 case '\\': t+=Unicode::decodeUtf8("\\\\"); break;
00251 case '"' : t+=Unicode::decodeUtf8("\\\""); break;
00252 default:
00253 if(ch <= 0x1f || ch >= 0x7f && ch <= 0xa0 || ch == 0xad)
00254 {
00255 char buffer[8];
00256 sprintf(buffer, "\\x%02x", ch);
00257 t+=Unicode::decodeUtf8(buffer);
00258 }
00259 else t+=ch;
00260 }
00261 }
00262 t+='"';
00263 return t;
00264 }
00265
00266 string format(string value, int width)
00267 {
00268 string buffer;
00269 StringTokenizer tokenizer(value, " \t\r\n", true);
00270
00271 int position = 0;
00272 int pendingNewlines = 0;
00273
00274 while(tokenizer.hasMoreElements())
00275 {
00276 string word = tokenizer.nextToken();
00277
00278 if(word == " " || word == "\t" || word == "\r") continue;
00279
00280 if(word == "\n")
00281 {
00282 if(width < 0) continue;
00283 ++pendingNewlines;
00284 position = 0;
00285 continue;
00286 }
00287
00288 if(pendingNewlines > 0)
00289 {
00290 for(int i=0; i<pendingNewlines; ++i) buffer += "\n";
00291 pendingNewlines = 0;
00292 }
00293
00294 if(width > 0)
00295 {
00296
00297 if(position > 0 && int(word.length()) + position >= width)
00298 {
00299 buffer += "\n";
00300 position = 0;
00301 }
00302
00303
00304 while(position == 0 && int(word.length()) > width)
00305 {
00306 buffer += string(word, 0, width);
00307 buffer += "\n";
00308 word = string(word, width);
00309 }
00310 }
00311
00312 if(position > 0)
00313 {
00314 buffer += " ";
00315 ++position;
00316 }
00317 buffer += word;
00318 position += word.length();
00319 }
00320
00321 return buffer;
00322 }
00323
00324 int width(string s)
00325 {
00326 int w = 0;
00327 unsigned p = 0;
00328 do
00329 {
00330 unsigned _p = s.find('\n', p);
00331 if(_p == string::npos) _p = s.length();
00332 int _w = _p - p;
00333 if(_w > w) w = _w;
00334 p = _p + 1;
00335 }
00336 while(p <= s.size());
00337 return w;
00338 }
00339
00340 int height(string s)
00341 {
00342 int h = 0;
00343 unsigned p = 0;
00344 for(;;)
00345 {
00346 const unsigned _p = s.find('\n', p);
00347 if(_p == string::npos)
00348 {
00349 if(s.size() - p > 0) ++h;
00350 break;
00351 }
00352 ++h;
00353 p = _p + 1;
00354 }
00355
00356 return h;
00357 }
00358
00359 string extractLine(string s, int i)
00360 {
00361 if(i<0) return "";
00362 unsigned p = 0;
00363 while(i>0)
00364 {
00365 const unsigned _p = s.find('\n', p);
00366 if(_p == string::npos) return "";
00367 p = _p + 1;
00368 --i;
00369 }
00370 unsigned q = s.find('\n', p);
00371 if(q == string::npos) q = s.size();
00372 if(p == s.size()) return "";
00373 return s.substr(p, q-p);
00374 }
00375
00376 string format(Table<string> &table, int maxTotalWidth, int columnSpacing, bool header)
00377 {
00378 if(!table.getRows()) return "";
00379
00380
00381 vector<int> columnWidths(table.getCols());
00382 for(int i=0; i<table.getRows(); ++i)
00383 for(int j=0; j<table.getCols(); ++j)
00384 {
00385 const int w = width(table(i, j));
00386 if(w > columnWidths[j]) columnWidths[j] = w;
00387 }
00388
00389
00390 int totalWidth = 0;
00391 for(int i=0; i<table.getCols(); ++i)
00392 {
00393 totalWidth += columnWidths[i];
00394 if(i<table.getCols()-1) totalWidth += columnSpacing;
00395 }
00396
00397 if(maxTotalWidth > 0 && totalWidth > maxTotalWidth)
00398 {
00399
00400 const int netWidth = maxTotalWidth - (table.getCols()-1) * columnSpacing;
00401 vector<double> excess(table.getCols());
00402 for(int i=0; i<table.getCols(); ++i)
00403 excess[i] = columnWidths[i] - netWidth * table.columnWidthFractions[i];
00404 while(totalWidth > maxTotalWidth)
00405 {
00406
00407 double e = DBL_MIN;
00408 int j = -1;
00409 for(int i=0; i<table.getCols(); ++i)
00410 if(excess[i] > e) e = excess[j = i];
00411
00412 if(columnWidths[j] > 1) --columnWidths[j];
00413 excess[j] -= 1;
00414 --totalWidth;
00415 }
00416
00417
00418 for(int i=0; i<table.getRows(); ++i)
00419 for(int j=0; j<table.getCols(); ++j)
00420 table(i, j) = format(table(i, j), columnWidths[j]);
00421 }
00422
00423
00424 string buffer;
00425 for(int i=0; i<table.getRows(); ++i)
00426 {
00427 int h = 0;
00428 for(int j=0; j<table.getCols(); ++j)
00429 {
00430 int _h = height(table(i, j));
00431 if(_h > h) h = _h;
00432 }
00433
00434 for(int l=0; l<h; ++l)
00435 {
00436 for(int j=0; j<table.getCols(); ++j)
00437 {
00438 string cellLine = extractLine(table(i, j), l);
00439 buffer += cellLine;
00440 if(j<table.getCols()-1)
00441 {
00442 int w = cellLine.length();
00443 while(w<columnWidths[j]+columnSpacing)
00444 {
00445 buffer += " ";
00446 ++w;
00447 }
00448 }
00449 }
00450
00451 buffer += "\n";
00452 }
00453
00454 if(header && i == 0)
00455 {
00456 for(int j=0; j<totalWidth; ++j) buffer += "-";
00457 buffer += "\n";
00458 }
00459 }
00460
00461 return buffer;
00462 }
00463 }
00464 }
00465 }