blob: fb20c2df4a2dfe7885158fe0a0a164cc6ab43c86 [file] [log] [blame] [edit]
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "StringUtilities.h"
#define WHITESPACE " \n\r\t"
#define WIDE_WHITESPACE L" \n\r\t"
namespace webdriver {
StringUtilities::StringUtilities(void) {
}
StringUtilities::~StringUtilities(void) {
}
std::wstring StringUtilities::ToWString(const std::string& input) {
// Assumption: The wstring character count will be the same as the length of
// the string character count. Allocate the buffer with that many wchar_t items
// so that the first MultiByteToWideChar call will succeed most of the time as
// an optimization.
std::wstring output = L"";
int input_string_byte_count = static_cast<int>(input.size()) + 1;
int wide_string_length = input_string_byte_count;
std::vector<wchar_t> output_buffer(wide_string_length);
bool convert_failed = (0 == ::MultiByteToWideChar(CP_UTF8,
0,
input.c_str(),
input_string_byte_count,
&output_buffer[0],
wide_string_length));
if (convert_failed) {
if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// Buffer wasn't big enough. Call MultiByteToWideChar again with
// NULL values to determine how big the buffer should be.
wide_string_length = ::MultiByteToWideChar(CP_UTF8,
0,
input.c_str(),
input_string_byte_count,
NULL,
0);
output_buffer.resize(wide_string_length);
convert_failed = (0 == ::MultiByteToWideChar(CP_UTF8,
0,
input.c_str(),
input_string_byte_count,
&output_buffer[0],
wide_string_length));
if (!convert_failed) {
output = &output_buffer[0];
}
}
} else {
output = &output_buffer[0];
}
return output;
}
std::string StringUtilities::ToString(const std::wstring& input) {
// Assumption: The byte count of the resulting narrow string will be at most
// four times the character count of the input wstring. Allocate the buffer
// with that many char items (bytes) so that the first WideCharToMultiByte
// call will succeed most of the time as an optimization.
std::string output = "";
int wide_string_length = static_cast<int>(input.size()) + 1;
int output_string_byte_count = wide_string_length * 4;
std::vector<char> string_buffer(output_string_byte_count);
bool convert_failed = (0 == ::WideCharToMultiByte(CP_UTF8,
0,
input.c_str(),
wide_string_length,
&string_buffer[0],
output_string_byte_count,
NULL,
NULL));
if (convert_failed) {
if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// Buffer wasn't big enough. Call WideCharToMultiByte again with
// NULL values to determine how big the buffer should be.
output_string_byte_count = ::WideCharToMultiByte(CP_UTF8,
0,
input.c_str(),
wide_string_length,
NULL,
0,
NULL,
NULL);
string_buffer.resize(output_string_byte_count);
convert_failed = (0 == ::WideCharToMultiByte(CP_UTF8,
0,
input.c_str(),
wide_string_length,
&string_buffer[0],
output_string_byte_count,
NULL,
NULL));
if (!convert_failed) {
output = &string_buffer[0];
}
}
} else {
output = &string_buffer[0];
}
return output;
}
std::string StringUtilities::Format(const char* format, ...) {
va_list args;
va_start(args, format);
size_t buffer_size = _vscprintf(format, args);
std::vector<char> buffer(buffer_size + 1);
_vsnprintf_s(&buffer[0], buffer.size(), buffer_size + 1, format, args);
va_end(args);
std::string formatted = &buffer[0];
return formatted;
}
std::wstring StringUtilities::Format(const wchar_t* format, ...) {
va_list args;
va_start(args, format);
size_t buffer_size = _vscwprintf(format, args);
std::vector<wchar_t> buffer(buffer_size + 1);
_vsnwprintf_s(&buffer[0], buffer.size(), buffer_size + 1, format, args);
va_end(args);
std::wstring formatted = &buffer[0];
return formatted;
}
void StringUtilities::ToBuffer(const std::string& input, std::vector<char>* buffer) {
buffer->resize(input.size() + 1);
strcpy_s(&((*buffer)[0]), buffer->size(), input.c_str());
(*buffer)[buffer->size() - 1] = L'\0';
}
void StringUtilities::ToBuffer(const std::wstring& input, std::vector<wchar_t>* buffer) {
buffer->resize(input.size() + 1);
wcscpy_s(&((*buffer)[0]), buffer->size(), input.c_str());
(*buffer)[buffer->size() - 1] = L'\0';
}
std::string StringUtilities::Trim(const std::string& input) {
return TrimRight(TrimLeft(input));
}
std::string StringUtilities::TrimLeft(const std::string& input) {
size_t startpos = input.find_first_not_of(WHITESPACE);
return (startpos == std::string::npos) ? "" : input.substr(startpos);
}
std::string StringUtilities::TrimRight(const std::string& input) {
size_t endpos = input.find_last_not_of(WHITESPACE);
return (endpos == std::string::npos) ? "" : input.substr(0, endpos + 1);
}
std::wstring StringUtilities::Trim(const std::wstring& input) {
return TrimRight(TrimLeft(input));
}
std::wstring StringUtilities::TrimLeft(const std::wstring& input) {
size_t startpos = input.find_first_not_of(WIDE_WHITESPACE);
return (startpos == std::wstring::npos) ? L"" : input.substr(startpos);
}
std::wstring StringUtilities::TrimRight(const std::wstring& input) {
size_t endpos = input.find_last_not_of(WIDE_WHITESPACE);
return (endpos == std::wstring::npos) ? L"" : input.substr(0, endpos + 1);
}
void StringUtilities::Split(const std::string& input,
const std::string& delimiter,
std::vector<std::string>* tokens) {
std::string input_copy = input;
while (input_copy.size() > 0) {
size_t delimiter_pos = input_copy.find(delimiter);
std::string token = input_copy.substr(0, delimiter_pos);
if (delimiter_pos == std::string::npos) {
input_copy = "";
} else {
input_copy = input_copy.substr(delimiter_pos + delimiter.size());
}
tokens->push_back(token);
}
}
void StringUtilities::Split(const std::wstring& input,
const std::wstring& delimiter,
std::vector<std::wstring>* tokens) {
std::wstring input_copy = input;
while (input_copy.size() > 0) {
size_t delimiter_pos = input_copy.find(delimiter);
std::wstring token = input_copy.substr(0, delimiter_pos);
if (delimiter_pos == std::wstring::npos) {
input_copy = L"";
} else {
input_copy = input_copy.substr(delimiter_pos + delimiter.size());
}
tokens->push_back(token);
}
}
std::wstring StringUtilities::CreateGuid() {
UUID guid;
RPC_WSTR guid_string = NULL;
RPC_STATUS status = ::UuidCreate(&guid);
if (status != RPC_S_OK) {
// If we encounter an error, not bloody much we can do about it.
// Just log it and continue.
// LOG(WARN) << "UuidCreate returned a status other then RPC_S_OK: " << status;
}
status = ::UuidToString(&guid, &guid_string);
if (status != RPC_S_OK) {
// If we encounter an error, not bloody much we can do about it.
// Just log it and continue.
// LOG(WARN) << "UuidToString returned a status other then RPC_S_OK: " << status;
}
// RPC_WSTR is currently typedef'd in RpcDce.h (pulled in by rpc.h)
// as unsigned short*. It needs to be typedef'd as wchar_t*
wchar_t* cast_guid_string = reinterpret_cast<wchar_t*>(guid_string);
std::wstring returned_guid(cast_guid_string);
::RpcStringFree(&guid_string);
return returned_guid;
}
void StringUtilities::ComposeUnicodeString(std::wstring* input) {
StringUtilities::NormalizeUnicodeString(NormalizationC, input);
}
void StringUtilities::DecomposeUnicodeString(std::wstring* input) {
StringUtilities::NormalizeUnicodeString(NormalizationD, input);
}
void StringUtilities::NormalizeUnicodeString(NORM_FORM normalization_form,
std::wstring* input) {
if (FALSE == ::IsNormalizedString(normalization_form, input->c_str(), -1)) {
int required = ::NormalizeString(normalization_form,
input->c_str(),
-1,
NULL,
0);
std::vector<wchar_t> buffer(required);
::NormalizeString(normalization_form,
input->c_str(),
-1,
&buffer[0],
static_cast<int>(buffer.size()));
*input = &buffer[0];
}
}
} // namespace webdriver