• Main Page
  • Classes
  • Files
  • File List

CStringUtil.cpp

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

Generated on Tue May 21 2013 00:00:06 for Synergy by  doxygen 1.7.1