scummvm/engines/wintermute/StringUtil.cpp
2012-06-02 13:01:36 +02:00

394 lines
14 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This file is based on WME Lite.
* http://dead-code.org/redir.php?target=wmelite
* Copyright (c) 2011 Jan Nedoma
*/
#include "dcgf.h"
#include <algorithm>
#include <string>
#include <sstream>
#include "common/tokenizer.h"
#include "StringUtil.h"
#include "ConvertUTF.h"
namespace WinterMute {
//////////////////////////////////////////////////////////////////////////
void StringUtil::ToLowerCase(AnsiString &str) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
}
//////////////////////////////////////////////////////////////////////////
/*void StringUtil::ToLowerCase(WideString &str) {
std::transform(str.begin(), str.end(), str.begin(), ::towlower);
}*/
//////////////////////////////////////////////////////////////////////////
void StringUtil::ToUpperCase(AnsiString &str) {
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
}
//////////////////////////////////////////////////////////////////////////
/*void StringUtil::ToUpperCase(WideString &str) {
std::transform(str.begin(), str.end(), str.begin(), ::towupper);
}*/
//////////////////////////////////////////////////////////////////////////
bool StringUtil::CompareNoCase(const AnsiString &str1, const AnsiString &str2) {
AnsiString str1lc = str1;
AnsiString str2lc = str2;
ToLowerCase(str1lc);
ToLowerCase(str2lc);
return (str1lc == str2lc);
}
//////////////////////////////////////////////////////////////////////////
/*bool StringUtil::CompareNoCase(const WideString &str1, const WideString &str2) {
WideString str1lc = str1;
WideString str2lc = str2;
ToLowerCase(str1lc);
ToLowerCase(str2lc);
return (str1lc == str2lc);
}*/
//////////////////////////////////////////////////////////////////////////
WideString StringUtil::Utf8ToWide(const Utf8String &Utf8Str) {
error("StringUtil::Utf8ToWide - WideString not supported yet");
/* size_t WideSize = Utf8Str.size();
if (sizeof(wchar_t) == 2) {
wchar_t *WideStringNative = new wchar_t[WideSize + 1];
const UTF8 *SourceStart = reinterpret_cast<const UTF8 *>(Utf8Str.c_str());
const UTF8 *SourceEnd = SourceStart + WideSize;
UTF16 *TargetStart = reinterpret_cast<UTF16 *>(WideStringNative);
UTF16 *TargetEnd = TargetStart + WideSize + 1;
ConversionResult res = ConvertUTF8toUTF16(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion);
if (res != conversionOK) {
delete [] WideStringNative;
return L"";
}
*TargetStart = 0;
WideString ResultString(WideStringNative);
delete [] WideStringNative;
return ResultString;
} else if (sizeof(wchar_t) == 4) {
wchar_t *WideStringNative = new wchar_t[WideSize + 1];
const UTF8 *SourceStart = reinterpret_cast<const UTF8 *>(Utf8Str.c_str());
const UTF8 *SourceEnd = SourceStart + WideSize;
UTF32 *TargetStart = reinterpret_cast<UTF32 *>(WideStringNative);
UTF32 *TargetEnd = TargetStart + WideSize;
ConversionResult res = ConvertUTF8toUTF32(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion);
if (res != conversionOK) {
delete [] WideStringNative;
return L"";
}
*TargetStart = 0;
WideString ResultString(WideStringNative);
delete [] WideStringNative;
return ResultString;
} else {
return L"";
}*/
return "";
}
//////////////////////////////////////////////////////////////////////////
Utf8String StringUtil::WideToUtf8(const WideString &WideStr) {
error("StringUtil::WideToUtf8 - Widestring not supported yet");
/* size_t WideSize = WideStr.length();
if (sizeof(wchar_t) == 2) {
size_t Utf8Size = 3 * WideSize + 1;
char *Utf8StringNative = new char[Utf8Size];
const UTF16 *SourceStart = reinterpret_cast<const UTF16 *>(WideStr.c_str());
const UTF16 *SourceEnd = SourceStart + WideSize;
UTF8 *TargetStart = reinterpret_cast<UTF8 *>(Utf8StringNative);
UTF8 *TargetEnd = TargetStart + Utf8Size;
ConversionResult res = ConvertUTF16toUTF8(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion);
if (res != conversionOK) {
delete [] Utf8StringNative;
return (Utf8String)"";
}
*TargetStart = 0;
Utf8String ResultString(Utf8StringNative);
delete [] Utf8StringNative;
return ResultString;
} else if (sizeof(wchar_t) == 4) {
size_t Utf8Size = 4 * WideSize + 1;
char *Utf8StringNative = new char[Utf8Size];
const UTF32 *SourceStart = reinterpret_cast<const UTF32 *>(WideStr.c_str());
const UTF32 *SourceEnd = SourceStart + WideSize;
UTF8 *TargetStart = reinterpret_cast<UTF8 *>(Utf8StringNative);
UTF8 *TargetEnd = TargetStart + Utf8Size;
ConversionResult res = ConvertUTF32toUTF8(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion);
if (res != conversionOK) {
delete [] Utf8StringNative;
return (Utf8String)"";
}
*TargetStart = 0;
Utf8String ResultString(Utf8StringNative);
delete [] Utf8StringNative;
return ResultString;
} else {
return (Utf8String)"";
}*/
return "";
}
//////////////////////////////////////////////////////////////////////////
WideString StringUtil::AnsiToWide(const AnsiString &str) {
// using default os locale!
error("StringUtil::AnsiToWide - WideString not supported yet");
/* setlocale(LC_CTYPE, "");
size_t WideSize = mbstowcs(NULL, str.c_str(), 0) + 1;
wchar_t *wstr = new wchar_t[WideSize];
mbstowcs(wstr, str.c_str(), WideSize);
WideString ResultString(wstr);
delete [] wstr;
return ResultString;*/
return "";
}
//////////////////////////////////////////////////////////////////////////
AnsiString StringUtil::WideToAnsi(const WideString &wstr) {
// using default os locale!
error("StringUtil::WideToAnsi - WideString not supported yet");
/* setlocale(LC_CTYPE, "");
size_t WideSize = wcstombs(NULL, wstr.c_str(), 0) + 1;
char *str = new char[WideSize];
wcstombs(str, wstr.c_str(), WideSize);
AnsiString ResultString(str);
delete [] str;
return ResultString;*/
return "";
}
//////////////////////////////////////////////////////////////////////////
bool StringUtil::StartsWith(const AnsiString &str, const AnsiString &pattern, bool ignoreCase) {
/* size_t strLength = str.size();
size_t patternLength = pattern.size();
if (strLength < patternLength || patternLength == 0)
return false;
AnsiString startPart = str.substr(0, patternLength);
if (ignoreCase) return CompareNoCase(startPart, pattern);
else return (startPart == pattern);*/
if (!ignoreCase)
return str.hasPrefix(pattern);
else {
size_t strLength = str.size();
size_t patternLength = pattern.size();
if (strLength < patternLength || patternLength == 0)
return false;
AnsiString startPart(str.c_str(), patternLength);
uint32 likeness = str.compareToIgnoreCase(pattern.c_str());
return (likeness == 0);
}
}
//////////////////////////////////////////////////////////////////////////
bool StringUtil::EndsWith(const AnsiString &str, const AnsiString &pattern, bool ignoreCase) {
/* size_t strLength = str.size(); // TODO: Remove
size_t patternLength = pattern.size();
if (strLength < patternLength || patternLength == 0)
return false;
AnsiString endPart = str.substr(strLength - patternLength, patternLength);
if (ignoreCase) return CompareNoCase(endPart, pattern);
else return (endPart == pattern);*/
if (!ignoreCase) {
return str.hasSuffix(pattern);
} else {
size_t strLength = str.size();
size_t patternLength = pattern.size();
if (strLength < patternLength || patternLength == 0)
return false;
Common::String endPart(str.c_str() + (strLength - patternLength), patternLength);
uint32 likeness = str.compareToIgnoreCase(pattern.c_str());
return (likeness != 0);
}
}
//////////////////////////////////////////////////////////////////////////
bool StringUtil::IsUtf8BOM(const byte *Buffer, uint32 BufferSize) {
if (BufferSize > 3 && Buffer[0] == 0xEF && Buffer[1] == 0xBB && Buffer[2] == 0xBF) return true;
else return false;
}
//////////////////////////////////////////////////////////////////////////
AnsiString StringUtil::Replace(const AnsiString &str, const AnsiString &from, const AnsiString &to) {
if (from.empty() || from == to) return str;
AnsiString result = str;
/*size_t pos = 0;*/
while (result.contains(from)) {
const char *startPtr = strstr(result.c_str(), from.c_str());
uint32 index = startPtr - result.c_str();
Common::String tail(result.c_str() + index + to.size());
result = Common::String(result.c_str(), index);
result += to;
result += tail;
/* pos = result.find(from, pos);
if (pos == result.npos) break;
result.replace(pos, from.size(), to);
pos += to.size();*/
}
return result;
}
//////////////////////////////////////////////////////////////////////////
AnsiString StringUtil::Trim(const AnsiString &str, bool fromLeft, bool fromRight, const AnsiString &chars) {
AnsiString trimmedStr = str;
if (fromRight) {
//trimmedStr.erase(trimmedStr.find_last_not_of(chars) + 1); // TODO
warning("fromRight-trim not implemented yet, %s", chars.c_str());
}
if (fromLeft) {
uint32 lastOf = LastIndexOf(str, chars, 0);
trimmedStr = Common::String(trimmedStr.c_str() + lastOf);
//trimmedStr.erase(0, trimmedStr.find_first_not_of(chars));
}
return trimmedStr;
}
//////////////////////////////////////////////////////////////////////////
int StringUtil::IndexOf(const WideString &str, const WideString &toFind, size_t startFrom) {
/*size_t pos = str.find(toFind, startFrom);
if (pos == str.npos) return -1;
else return pos;*/
const char *index = strstr(str.c_str(), toFind.c_str());
if (index == NULL)
return -1;
else
return index - str.c_str();
}
//////////////////////////////////////////////////////////////////////////
int StringUtil::LastIndexOf(const WideString &str, const WideString &toFind, size_t startFrom) {
/*size_t pos = str.rfind(toFind, startFrom);
if (pos == str.npos) return -1;
else return pos;*/
int32 lastIndex = -1;
bool found = false;
for (size_t i = startFrom; i < str.size(); i++) {
found = false;
for (size_t j = 0; j < toFind.size(); j++) {
if (str[i + j] != toFind[j]) {
found = false;
break;
} else {
found = true;
}
}
if (found)
lastIndex = i;
}
return lastIndex;
}
//////////////////////////////////////////////////////////////////////////
AnsiString StringUtil::ToString(size_t val) {
/* std::ostringstream str;
str << val;
return str.str();*/
return Common::String::format("%u", (uint32)val);
}
//////////////////////////////////////////////////////////////////////////
AnsiString StringUtil::ToString(int val) {
/* std::ostringstream str;
str << val;
return str.str();*/
return Common::String::format("%d", val);
}
//////////////////////////////////////////////////////////////////////////
AnsiString StringUtil::ToString(float val) {
/* std::ostringstream str;
str << val;
return str.str();*/
return Common::String::format("%f", val);
}
//////////////////////////////////////////////////////////////////////////
AnsiString StringUtil::ToString(double val) {
/* std::ostringstream str;
str << val;
return str.str();*/
return Common::String::format("%f", val);
}
//////////////////////////////////////////////////////////////////////////
void StringUtil::Split(const AnsiString &list, const AnsiString &delimiters, AnsiStringArray &result, bool keepEmptyItems) {
result.clear();
//TODO: Verify this, wrt keepEmptyItems.
Common::StringTokenizer tokenizer(list.c_str(), delimiters.c_str());
//typedef boost::char_separator<char> separator_t;
//typedef boost::tokenizer<separator_t, AnsiString::const_iterator, AnsiString> tokenizer_t;
//separator_t del(delimiters.c_str(), "", keepEmptyItems ? boost::keep_empty_tokens : boost::drop_empty_tokens);
//tokenizer_t tokens(list, del);
while (!tokenizer.empty()) {
Common::String copy(tokenizer.nextToken().c_str());
result.push_back(copy);
}
}
} // end of namespace WinterMute