Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

CStringUtil.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2002 Chris Schoeneman
00004  * 
00005  * This package is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * found in the file COPYING that should have accompanied this file.
00008  * 
00009  * This package is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  */
00014 
00015 #include "CStringUtil.h"
00016 #include "CArch.h"
00017 #include "common.h"
00018 #include "stdvector.h"
00019 #include <cctype>
00020 #include <cstdio>
00021 #include <cstdlib>
00022 #include <cstring>
00023 #include <algorithm>
00024 
00025 //
00026 // CStringUtil
00027 //
00028 
00029 CString
00030 CStringUtil::format(const char* fmt, ...)
00031 {
00032     va_list args;
00033     va_start(args, fmt);
00034     CString result = vformat(fmt, args);
00035     va_end(args);
00036     return result;
00037 }
00038 
00039 CString
00040 CStringUtil::vformat(const char* fmt, va_list args)
00041 {
00042     // find highest indexed substitution and the locations of substitutions
00043     std::vector<size_t> pos;
00044     std::vector<size_t> width;
00045     std::vector<int> index;
00046     int maxIndex = 0;
00047     for (const char* scan = fmt; *scan != '\0'; ++scan) {
00048         if (*scan == '%') {
00049             ++scan;
00050             if (*scan == '\0') {
00051                 break;
00052             }
00053             else if (*scan == '%') {
00054                 // literal
00055                 index.push_back(0);
00056                 pos.push_back(static_cast<int>(scan - 1 - fmt));
00057                 width.push_back(2);
00058             }
00059             else if (*scan == '{') {
00060                 // get argument index
00061                 char* end;
00062                 int i = static_cast<int>(strtol(scan + 1, &end, 10));
00063                 if (*end != '}') {
00064                     // invalid index -- ignore
00065                     scan = end - 1;
00066                 }
00067                 else {
00068                     index.push_back(i);
00069                     pos.push_back(static_cast<int>(scan - 1 - fmt));
00070                     width.push_back(static_cast<int>(end - scan + 2));
00071                     if (i > maxIndex) {
00072                         maxIndex = i;
00073                     }
00074                     scan = end;
00075                 }
00076             }
00077             else {
00078                 // improper escape -- ignore
00079             }
00080         }
00081     }
00082 
00083     // get args
00084     std::vector<const char*> value;
00085     std::vector<size_t> length;
00086     value.push_back("%");
00087     length.push_back(1);
00088     for (int i = 0; i < maxIndex; ++i) {
00089         const char* arg = va_arg(args, const char*);
00090         size_t len = strlen(arg);
00091         value.push_back(arg);
00092         length.push_back(len);
00093     }
00094 
00095     // compute final length
00096     size_t resultLength = strlen(fmt);
00097     const int n = static_cast<int>(pos.size());
00098     for (int i = 0; i < n; ++i) {
00099         resultLength -= width[i];
00100         resultLength += length[index[i]];
00101     }
00102 
00103     // substitute
00104     CString result;
00105     result.reserve(resultLength);
00106     size_t src = 0;
00107     for (int i = 0; i < n; ++i) {
00108         result.append(fmt + src, pos[i] - src);
00109         result.append(value[index[i]]);
00110         src = pos[i] + width[i];
00111     }
00112     result.append(fmt + src);
00113 
00114     return result;
00115 }
00116 
00117 CString
00118 CStringUtil::print(const char* fmt, ...)
00119 {
00120     char tmp[1024];
00121     char* buffer = tmp;
00122     int len      = (int)(sizeof(tmp) / sizeof(tmp[0]));
00123     CString result;
00124     while (buffer != NULL) {
00125         // try printing into the buffer
00126         va_list args;
00127         va_start(args, fmt);
00128         int n = ARCH->vsnprintf(buffer, len, fmt, args);
00129         va_end(args);
00130 
00131         // if the buffer wasn't big enough then make it bigger and try again
00132         if (n < 0 || n > len) {
00133             if (buffer != tmp) {
00134                 delete[] buffer;
00135             }
00136             len   *= 2;
00137             buffer = new char[len];
00138         }
00139 
00140         // if it was big enough then save the string and don't try again
00141         else {
00142             result = buffer;
00143             if (buffer != tmp) {
00144                 delete[] buffer;
00145             }
00146             buffer = NULL;
00147         }
00148     }
00149 
00150     return result;
00151 }
00152 
00153 
00154 //
00155 // CStringUtil::CaselessCmp
00156 //
00157 
00158 bool
00159 CStringUtil::CaselessCmp::cmpEqual(
00160                 const CString::value_type& a,
00161                 const CString::value_type& b)
00162 {
00163     // should use std::tolower but not in all versions of libstdc++ have it
00164     return tolower(a) == tolower(b);
00165 }
00166 
00167 bool
00168 CStringUtil::CaselessCmp::cmpLess(
00169                 const CString::value_type& a,
00170                 const CString::value_type& b)
00171 {
00172     // should use std::tolower but not in all versions of libstdc++ have it
00173     return tolower(a) < tolower(b);
00174 }
00175 
00176 bool
00177 CStringUtil::CaselessCmp::less(const CString& a, const CString& b)
00178 {
00179     return std::lexicographical_compare(
00180                                 a.begin(), a.end(),
00181                                 b.begin(), b.end(),
00182                                 &CStringUtil::CaselessCmp::cmpLess);
00183 }
00184 
00185 bool
00186 CStringUtil::CaselessCmp::equal(const CString& a, const CString& b)
00187 {
00188     return !(less(a, b) || less(b, a));
00189 }
00190 
00191 bool
00192 CStringUtil::CaselessCmp::operator()(const CString& a, const CString& b) const
00193 {
00194     return less(a, b);
00195 }

Generated on Fri Nov 6 00:21:14 2009 for synergy-plus by  doxygen 1.3.9.1