mirror of
https://github.com/debauchee/barrier.git
synced 2024-12-20 17:41:52 +03:00
fee4095624
synergy.cpp and server.cpp into cmd/synergyd as synergyd.cpp. Moved and renamed related files. Moved remaining source files into lib/.... Modified and added makefiles as appropriate. Result is that library files are under lib with each library in its own directory and program files are under cmd with each command in its own directory.
200 lines
4.1 KiB
C++
200 lines
4.1 KiB
C++
#include "CString.h"
|
|
#include "common.h"
|
|
#include "stdvector.h"
|
|
#include <cctype>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <algorithm>
|
|
|
|
#if WINDOWS_LIKE
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#include <windows.h>
|
|
#define vsnprintf _vsnprintf
|
|
#endif
|
|
|
|
//
|
|
// CStringUtil
|
|
//
|
|
|
|
CString
|
|
CStringUtil::format(const char* fmt, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
CString result = vformat(fmt, args);
|
|
va_end(args);
|
|
return result;
|
|
}
|
|
|
|
CString
|
|
CStringUtil::vformat(const char* fmt, va_list args)
|
|
{
|
|
// find highest indexed substitution and the locations of substitutions
|
|
std::vector<size_t> pos;
|
|
std::vector<size_t> width;
|
|
std::vector<int> index;
|
|
int maxIndex = 0;
|
|
for (const char* scan = fmt; *scan != '\0'; ++scan) {
|
|
if (*scan == '%') {
|
|
++scan;
|
|
if (*scan == '\0') {
|
|
break;
|
|
}
|
|
else if (*scan == '%') {
|
|
// literal
|
|
index.push_back(0);
|
|
pos.push_back(static_cast<int>(scan - 1 - fmt));
|
|
width.push_back(2);
|
|
}
|
|
else if (*scan == '{') {
|
|
// get argument index
|
|
char* end;
|
|
int i = static_cast<int>(strtol(scan + 1, &end, 10));
|
|
if (*end != '}') {
|
|
// invalid index -- ignore
|
|
scan = end - 1;
|
|
}
|
|
else {
|
|
index.push_back(i);
|
|
pos.push_back(static_cast<int>(scan - 1 - fmt));
|
|
width.push_back(static_cast<int>(end - scan + 2));
|
|
if (i > maxIndex) {
|
|
maxIndex = i;
|
|
}
|
|
scan = end;
|
|
}
|
|
}
|
|
else {
|
|
// improper escape -- ignore
|
|
}
|
|
}
|
|
}
|
|
|
|
// get args
|
|
std::vector<const char*> value;
|
|
std::vector<size_t> length;
|
|
value.push_back("%");
|
|
length.push_back(1);
|
|
for (int i = 0; i < maxIndex; ++i) {
|
|
const char* arg = va_arg(args, const char*);
|
|
value.push_back(arg);
|
|
length.push_back(strlen(arg));
|
|
}
|
|
|
|
// compute final length
|
|
size_t resultLength = strlen(fmt);
|
|
const int n = static_cast<int>(pos.size());
|
|
for (int i = 0; i < n; ++i) {
|
|
resultLength -= width[i];
|
|
resultLength += length[index[i]];
|
|
}
|
|
|
|
// substitute
|
|
CString result;
|
|
result.reserve(resultLength);
|
|
size_t src = 0;
|
|
for (int i = 0; i < n; ++i) {
|
|
result.append(fmt + src, pos[i] - src);
|
|
result.append(value[index[i]]);
|
|
src = pos[i] + width[i];
|
|
}
|
|
result.append(fmt + src);
|
|
|
|
return result;
|
|
}
|
|
|
|
CString
|
|
CStringUtil::print(const char* fmt, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
CString result = vprint(fmt, args);
|
|
va_end(args);
|
|
return result;
|
|
}
|
|
|
|
CString
|
|
CStringUtil::vprint(const char* fmt, va_list args)
|
|
{
|
|
char tmp[1024];
|
|
char* buffer = vsprint(tmp, sizeof(tmp) / sizeof(tmp[0]), 0, 0, fmt, args);
|
|
if (buffer == tmp) {
|
|
return buffer;
|
|
}
|
|
else {
|
|
CString result(buffer);
|
|
delete[] buffer;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
char*
|
|
CStringUtil::vsprint(char* buffer, int len,
|
|
int prefix, int suffix, const char* fmt, va_list args)
|
|
{
|
|
assert(len > 0);
|
|
|
|
// try writing to input buffer
|
|
int n;
|
|
if (buffer != NULL && len >= prefix + suffix) {
|
|
n = vsnprintf(buffer + prefix, len - (prefix + suffix), fmt, args);
|
|
if (n >= 0 && n <= len - (prefix + suffix))
|
|
return buffer;
|
|
}
|
|
|
|
// start allocating buffers until we write the whole string
|
|
buffer = NULL;
|
|
do {
|
|
delete[] buffer;
|
|
len *= 2;
|
|
buffer = new char[len + (prefix + suffix)];
|
|
n = vsnprintf(buffer + prefix, len - (prefix + suffix), fmt, args);
|
|
} while (n < 0 || n > len - (prefix + suffix));
|
|
|
|
return buffer;
|
|
}
|
|
|
|
|
|
//
|
|
// CStringUtil::CaselessCmp
|
|
//
|
|
|
|
bool
|
|
CStringUtil::CaselessCmp::cmpEqual(
|
|
const CString::value_type& a,
|
|
const CString::value_type& b)
|
|
{
|
|
// FIXME -- use std::tolower but not in all versions of libstdc++ have it
|
|
return tolower(a) == tolower(b);
|
|
}
|
|
|
|
bool
|
|
CStringUtil::CaselessCmp::cmpLess(
|
|
const CString::value_type& a,
|
|
const CString::value_type& b)
|
|
{
|
|
// FIXME -- use std::tolower but not in all versions of libstdc++ have it
|
|
return tolower(a) < tolower(b);
|
|
}
|
|
|
|
bool
|
|
CStringUtil::CaselessCmp::less(const CString& a, const CString& b)
|
|
{
|
|
return std::lexicographical_compare(
|
|
a.begin(), a.end(),
|
|
b.begin(), b.end(),
|
|
&CStringUtil::CaselessCmp::cmpLess);
|
|
}
|
|
|
|
bool
|
|
CStringUtil::CaselessCmp::equal(const CString& a, const CString& b)
|
|
{
|
|
return !(less(a, b) || less(b, a));
|
|
}
|
|
|
|
bool
|
|
CStringUtil::CaselessCmp::operator()(const CString& a, const CString& b) const
|
|
{
|
|
return less(a, b);
|
|
}
|