source: vendor/synergy/current/lib/base/CStringUtil.cpp

Last change on this file was 2749, checked in by bird, 19 years ago

synergy v1.3.1 sources (zip).

File size: 4.2 KB
Line 
1/*
2 * synergy -- mouse and keyboard sharing utility
3 * Copyright (C) 2002 Chris Schoeneman
4 *
5 * This package is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * found in the file COPYING that should have accompanied this file.
8 *
9 * This package is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include "CStringUtil.h"
16#include "CArch.h"
17#include "common.h"
18#include "stdvector.h"
19#include <cctype>
20#include <cstdio>
21#include <cstdlib>
22#include <algorithm>
23
24//
25// CStringUtil
26//
27
28CString
29CStringUtil::format(const char* fmt, ...)
30{
31 va_list args;
32 va_start(args, fmt);
33 CString result = vformat(fmt, args);
34 va_end(args);
35 return result;
36}
37
38CString
39CStringUtil::vformat(const char* fmt, va_list args)
40{
41 // find highest indexed substitution and the locations of substitutions
42 std::vector<size_t> pos;
43 std::vector<size_t> width;
44 std::vector<int> index;
45 int maxIndex = 0;
46 for (const char* scan = fmt; *scan != '\0'; ++scan) {
47 if (*scan == '%') {
48 ++scan;
49 if (*scan == '\0') {
50 break;
51 }
52 else if (*scan == '%') {
53 // literal
54 index.push_back(0);
55 pos.push_back(static_cast<int>(scan - 1 - fmt));
56 width.push_back(2);
57 }
58 else if (*scan == '{') {
59 // get argument index
60 char* end;
61 int i = static_cast<int>(strtol(scan + 1, &end, 10));
62 if (*end != '}') {
63 // invalid index -- ignore
64 scan = end - 1;
65 }
66 else {
67 index.push_back(i);
68 pos.push_back(static_cast<int>(scan - 1 - fmt));
69 width.push_back(static_cast<int>(end - scan + 2));
70 if (i > maxIndex) {
71 maxIndex = i;
72 }
73 scan = end;
74 }
75 }
76 else {
77 // improper escape -- ignore
78 }
79 }
80 }
81
82 // get args
83 std::vector<const char*> value;
84 std::vector<size_t> length;
85 value.push_back("%");
86 length.push_back(1);
87 for (int i = 0; i < maxIndex; ++i) {
88 const char* arg = va_arg(args, const char*);
89 size_t len = strlen(arg);
90 value.push_back(arg);
91 length.push_back(len);
92 }
93
94 // compute final length
95 size_t resultLength = strlen(fmt);
96 const int n = static_cast<int>(pos.size());
97 for (int i = 0; i < n; ++i) {
98 resultLength -= width[i];
99 resultLength += length[index[i]];
100 }
101
102 // substitute
103 CString result;
104 result.reserve(resultLength);
105 size_t src = 0;
106 for (int i = 0; i < n; ++i) {
107 result.append(fmt + src, pos[i] - src);
108 result.append(value[index[i]]);
109 src = pos[i] + width[i];
110 }
111 result.append(fmt + src);
112
113 return result;
114}
115
116CString
117CStringUtil::print(const char* fmt, ...)
118{
119 char tmp[1024];
120 char* buffer = tmp;
121 int len = (int)(sizeof(tmp) / sizeof(tmp[0]));
122 CString result;
123 while (buffer != NULL) {
124 // try printing into the buffer
125 va_list args;
126 va_start(args, fmt);
127 int n = ARCH->vsnprintf(buffer, len, fmt, args);
128 va_end(args);
129
130 // if the buffer wasn't big enough then make it bigger and try again
131 if (n < 0 || n > len) {
132 if (buffer != tmp) {
133 delete[] buffer;
134 }
135 len *= 2;
136 buffer = new char[len];
137 }
138
139 // if it was big enough then save the string and don't try again
140 else {
141 result = buffer;
142 if (buffer != tmp) {
143 delete[] buffer;
144 }
145 buffer = NULL;
146 }
147 }
148
149 return result;
150}
151
152
153//
154// CStringUtil::CaselessCmp
155//
156
157bool
158CStringUtil::CaselessCmp::cmpEqual(
159 const CString::value_type& a,
160 const CString::value_type& b)
161{
162 // should use std::tolower but not in all versions of libstdc++ have it
163 return tolower(a) == tolower(b);
164}
165
166bool
167CStringUtil::CaselessCmp::cmpLess(
168 const CString::value_type& a,
169 const CString::value_type& b)
170{
171 // should use std::tolower but not in all versions of libstdc++ have it
172 return tolower(a) < tolower(b);
173}
174
175bool
176CStringUtil::CaselessCmp::less(const CString& a, const CString& b)
177{
178 return std::lexicographical_compare(
179 a.begin(), a.end(),
180 b.begin(), b.end(),
181 &CStringUtil::CaselessCmp::cmpLess);
182}
183
184bool
185CStringUtil::CaselessCmp::equal(const CString& a, const CString& b)
186{
187 return !(less(a, b) || less(b, a));
188}
189
190bool
191CStringUtil::CaselessCmp::operator()(const CString& a, const CString& b) const
192{
193 return less(a, b);
194}
Note: See TracBrowser for help on using the repository browser.