| /* |
| * Project: VizKit |
| * Version: 2.3 |
| |
| * Date: 20090823 |
| * File: VisualString.cpp |
| * |
| */ |
| |
| /*************************************************************************** |
| |
| Copyright (c) 2004-2009 Heiko Wichmann (http://www.imagomat.de/vizkit) |
| |
| |
| This software is provided 'as-is', without any expressed or implied warranty. |
| In no event will the authors be held liable for any damages |
| arising from the use of this software. |
| |
| Permission is granted to anyone to use this software for any purpose, |
| including commercial applications, and to alter it and redistribute it |
| freely, subject to the following restrictions: |
| |
| 1. The origin of this software must not be misrepresented; |
| you must not claim that you wrote the original software. |
| If you use this software in a product, an acknowledgment |
| in the product documentation would be appreciated |
| but is not required. |
| |
| 2. Altered source versions must be plainly marked as such, |
| and must not be misrepresented as being the original software. |
| |
| 3. This notice may not be removed or altered from any source distribution. |
| |
| ***************************************************************************/ |
| |
| #include "VisualString.h" |
| #include "VisualFile.h" |
| #include "VisualDispatch.h" |
| #include "VisualErrorHandling.h" |
| #include "VisualNetwork.h" |
| #include "VisualNotification.h" |
| |
| |
| using namespace VizKit; |
| |
| |
| VisualString::VisualString() { |
| theString = NULL; |
| utf8representation = NULL; |
| utf16representation = NULL; |
| numberOfCharacters = 0; |
| numberOfNonWhitespaceCharacters = 0; |
| numberOfWords = 0; |
| numberOfLines = 0; |
| } |
| |
| |
| VisualString::VisualString(const char* const aStringVal, sint32 numberOfBytes) { |
| theString = NULL; |
| utf8representation = NULL; |
| utf16representation = NULL; |
| numberOfCharacters = 0; |
| numberOfNonWhitespaceCharacters = 0; |
| numberOfWords = 0; |
| numberOfLines = 0; |
| if (!aStringVal) return; |
| |
| if (numberOfBytes == -1) { |
| initWithUTF8String(aStringVal); |
| } else { |
| initWithUTF8Buffer(aStringVal, numberOfBytes); |
| } |
| } |
| |
| |
| VisualString::VisualString(const uint16* const aStringVal, sint32 aNumberOfCharacters) { |
| theString = NULL; |
| utf8representation = NULL; |
| utf16representation = NULL; |
| numberOfCharacters = 0; |
| numberOfNonWhitespaceCharacters = 0; |
| numberOfWords = 0; |
| numberOfLines = 0; |
| if (!aStringVal) return; |
| |
| if (aNumberOfCharacters == -1) { |
| initWithUTF16String(aStringVal); |
| } else { |
| initWithUTF16Buffer(aStringVal, aNumberOfCharacters); |
| } |
| } |
| |
| |
| VisualString::VisualString(ConstStringDataRef aStringVal) { |
| initWithConstStringDataRef(aStringVal); |
| } |
| |
| |
| void VisualString::initWithUTF8String(const char* const aStringVal) { |
| this->clear(); |
| if (aStringVal != NULL) { |
| uint32 numberOfBytes = strlen(aStringVal); |
| #if TARGET_OS_MAC |
| Boolean isExternalRepresentation = false; |
| CFStringRef theStringRef = CFStringCreateWithBytes(kCFAllocatorDefault, (const uint8*)aStringVal, numberOfBytes, kCFStringEncodingUTF8, isExternalRepresentation); |
| this->numberOfCharacters = CFStringGetLength(theStringRef); |
| theString = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, theStringRef); |
| CFRelease(theStringRef); |
| #endif |
| #if TARGET_OS_WIN |
| DWORD dwFlags = 0; |
| int destinationSize = 0; |
| numberOfBytes = -1; // utf8 string is null terminated |
| // MSDN: If this parameter is -1, the function processes the entire input string, |
| // including the terminating null character. |
| // Therefore, the resulting Unicode string has a terminating null character, |
| // and the length returned by the function includes this character. |
| int requiredSize = MultiByteToWideChar(CP_UTF8, dwFlags, aStringVal, numberOfBytes, theString, destinationSize); |
| if (requiredSize > 0) { |
| destinationSize = requiredSize; |
| this->theString = (wchar_t*)malloc(destinationSize * sizeof(wchar_t)); |
| int sizeConverted = MultiByteToWideChar(CP_UTF8, dwFlags, aStringVal, numberOfBytes, theString, destinationSize); |
| this->numberOfCharacters = destinationSize - 1; |
| } |
| #endif |
| } |
| numberOfNonWhitespaceCharacters = 0; |
| numberOfWords = 0; |
| numberOfLines = 0; |
| this->calcStatistics(); |
| } |
| |
| |
| void VisualString::initWithUTF8Buffer(const char* const aStringVal, uint32 numberOfBytes) { |
| this->clear(); |
| if (aStringVal != NULL) { |
| #if TARGET_OS_MAC |
| Boolean isExternalRepresentation = false; |
| CFStringRef theStringRef = CFStringCreateWithBytes(kCFAllocatorDefault, (const uint8*)aStringVal, numberOfBytes, kCFStringEncodingUTF8, isExternalRepresentation); |
| this->numberOfCharacters = CFStringGetLength(theStringRef); |
| theString = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, theStringRef); |
| CFRelease(theStringRef); |
| #endif |
| #if TARGET_OS_WIN |
| DWORD dwFlags = 0; |
| int destinationSize = 0; |
| int requiredSize = MultiByteToWideChar(CP_UTF8, dwFlags, aStringVal, numberOfBytes, theString, destinationSize); |
| if (requiredSize > 0) { |
| destinationSize = requiredSize; |
| this->theString = (wchar_t*)malloc((destinationSize + 1) * sizeof(wchar_t)); |
| int sizeConverted = MultiByteToWideChar(CP_UTF8, dwFlags, aStringVal, numberOfBytes, theString, destinationSize); |
| this->theString[destinationSize] = L'\0'; |
| this->numberOfCharacters = destinationSize; |
| } |
| #endif |
| } |
| numberOfNonWhitespaceCharacters = 0; |
| numberOfWords = 0; |
| numberOfLines = 0; |
| this->calcStatistics(); |
| } |
| |
| |
| void VisualString::initWithUTF16String(const uint16* const aStringVal) { |
| this->clear(); |
| if (aStringVal != NULL) { |
| #if TARGET_OS_MAC |
| uint16 maxStringLength = 65536 - 1; |
| const uint16* stringPointer = aStringVal; |
| for (uint16 i = 0; i < (maxStringLength - 1); i++) { |
| if (*stringPointer == 0) { |
| this->numberOfCharacters = stringPointer - aStringVal; |
| break; |
| } |
| stringPointer++; |
| } |
| this->theString = CFStringCreateMutable(kCFAllocatorDefault, 0); |
| CFStringAppendCharacters(this->theString, aStringVal, (CFIndex)this->numberOfCharacters); |
| #endif |
| #if TARGET_OS_WIN |
| this->numberOfCharacters = wcslen((wchar_t*)aStringVal); |
| size_t sizeInBytes = (numberOfCharacters + 1) * sizeof(wchar_t); |
| this->theString = (wchar_t*)malloc(sizeInBytes); |
| memcpy(theString, aStringVal, sizeInBytes); |
| #endif |
| } |
| numberOfNonWhitespaceCharacters = 0; |
| numberOfWords = 0; |
| numberOfLines = 0; |
| this->calcStatistics(); |
| } |
| |
| |
| void VisualString::initWithUTF16Buffer(const uint16* const aStringVal, uint32 aNumberOfCharacters) { |
| this->clear(); |
| if (aStringVal != NULL) { |
| this->numberOfCharacters = aNumberOfCharacters; |
| #if TARGET_OS_MAC |
| this->theString = CFStringCreateMutable(kCFAllocatorDefault, 0); |
| CFStringAppendCharacters(this->theString, aStringVal, (CFIndex)this->numberOfCharacters); |
| #endif |
| #if TARGET_OS_WIN |
| size_t sizeInBytes = (this->numberOfCharacters + 1) * sizeof(wchar_t); |
| this->theString = (wchar_t*)malloc(sizeInBytes); |
| memcpy(theString, aStringVal, this->numberOfCharacters * sizeof(wchar_t)); |
| this->theString[this->numberOfCharacters] = L'\0'; |
| #endif |
| } |
| numberOfNonWhitespaceCharacters = 0; |
| numberOfWords = 0; |
| numberOfLines = 0; |
| this->calcStatistics(); |
| } |
| |
| |
| bool VisualString::initWithContentsOfFile(VisualFile& aFile) { |
| |
| bool success = false; |
| |
| size_t size; |
| success = aFile.getSize(size); |
| if (!success) { |
| return success; |
| } |
| |
| void* fileData = NULL; |
| success = aFile.getData(&fileData, size); |
| if (!success) { |
| return success; |
| } |
| |
| this->initWithUTF8Buffer((const char*)fileData, size); |
| |
| free(fileData); |
| |
| return success; |
| } |
| |
| |
| bool VisualString::initWithContentsOfURL(const char* const aURL, const VisualItemIdentifier& anId) { |
| this->clear(); |
| VisualString urlString(aURL); |
| bool success = VisualNetwork::addToDownloadQueue(urlString, this, anId); |
| return success; |
| } |
| |
| |
| bool VisualString::initWithConstStringDataRef(ConstStringDataRef constStringDataRef) { |
| |
| theString = NULL; |
| utf8representation = NULL; |
| utf16representation = NULL; |
| numberOfCharacters = 0; |
| numberOfNonWhitespaceCharacters = 0; |
| numberOfWords = 0; |
| numberOfLines = 0; |
| |
| if (constStringDataRef != NULL) { |
| |
| #if TARGET_OS_MAC |
| this->numberOfCharacters = CFStringGetLength(constStringDataRef); |
| this->theString = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, constStringDataRef); |
| #endif |
| |
| #if TARGET_OS_WIN |
| numberOfCharacters = wcslen(constStringDataRef); |
| size_t sizeInBytes = (numberOfCharacters + 1) * sizeof(wchar_t); |
| theString = (wchar_t*)malloc(sizeInBytes); |
| memcpy(theString, constStringDataRef, sizeInBytes); |
| #endif |
| } |
| |
| numberOfNonWhitespaceCharacters = 0; |
| numberOfWords = 0; |
| numberOfLines = 0; |
| this->calcStatistics(); |
| return true; |
| } |
| |
| |
| VisualString::~VisualString() { |
| this->clear(); |
| } |
| |
| |
| VisualString::VisualString(const VisualString& other) : VisualObject(other) { |
| this->copy(other); |
| } |
| |
| |
| VisualString& VisualString::operator=(const VisualString& other) { |
| |
| if (this == &other) return *this; |
| |
| VisualObject::operator=(other); |
| |
| this->clear(); |
| |
| this->copy(other); |
| |
| return *this; |
| } |
| |
| |
| bool VisualString::operator<(const VisualString& other) const { |
| bool compareResult = false; |
| if (other.theString != NULL && this->theString != NULL) { |
| #if TARGET_OS_MAC |
| uint16 compareOptions = 0; |
| if (CFStringCompare(this->theString, other.theString, compareOptions) == kCFCompareLessThan) { |
| #endif |
| #if TARGET_OS_WIN |
| if (wcscmp(this->theString, other.theString) < 0) { |
| #endif |
| compareResult = true; |
| } |
| } |
| return compareResult; |
| } |
| |
| |
| bool VisualString::operator==(const VisualString& other) const { |
| bool compareResult = false; |
| if (other.theString != NULL && this->theString != NULL) { |
| #if TARGET_OS_MAC |
| uint16 compareOptions = 0; |
| if (CFStringCompare(this->theString, other.theString, compareOptions) == kCFCompareEqualTo) { |
| #endif |
| #if TARGET_OS_WIN |
| if (wcscmp(this->theString, other.theString) == 0) { |
| #endif |
| compareResult = true; |
| } |
| } else if (other.theString == NULL && this->theString == NULL) { |
| compareResult = true; |
| } |
| return compareResult; |
| } |
| |
| |
| bool VisualString::operator!=(const VisualString& other) const { |
| return !(*this == other); |
| } |
| |
| |
| void VisualString::copy(const VisualString& other) { |
| if (other.numberOfCharacters > 0) { |
| #if TARGET_OS_MAC |
| this->theString = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, other.theString); |
| #endif |
| #if TARGET_OS_WIN |
| size_t sizeInBytes = (other.numberOfCharacters + 1) * sizeof(wchar_t); |
| this->theString = (wchar_t *)malloc(sizeInBytes); |
| memcpy(theString, other.theString, sizeInBytes); |
| #endif |
| } else { |
| this->theString = NULL; |
| } |
| if (other.utf8representation != NULL) { |
| this->utf8representation = (char*)malloc(strlen(other.utf8representation) * sizeof(char)); |
| memcpy(this->utf8representation, other.utf8representation, strlen(other.utf8representation)); |
| } else { |
| this->utf8representation = NULL; |
| } |
| if (other.utf16representation != NULL) { |
| this->utf16representation = (uint16*)malloc(sizeof(other.utf16representation) * sizeof(char)); |
| memcpy(this->utf16representation, other.utf16representation, sizeof(other.utf16representation)); |
| } else { |
| this->utf16representation = NULL; |
| } |
| this->numberOfCharacters = other.numberOfCharacters; |
| this->numberOfNonWhitespaceCharacters = other.numberOfNonWhitespaceCharacters; |
| this->calcStatistics(); |
| } |
| |
| |
| void VisualString::clear() { |
| if (this->theString != NULL) { |
| #if TARGET_OS_MAC |
| CFRelease(this->theString); |
| #endif |
| #if TARGET_OS_WIN |
| free(this->theString); |
| #endif |
| this->theString = NULL; |
| } |
| if (this->utf8representation != NULL) { |
| free(this->utf8representation); |
| this->utf8representation = NULL; |
| } |
| if (this->utf16representation != NULL) { |
| free(this->utf16representation); |
| this->utf16representation = NULL; |
| } |
| if (arrayOfWords.size() > 0) { |
| arrayOfWords.clear(); |
| } |
| if (this->arrayOfLines.size() > 0) { |
| this->arrayOfLines.clear(); |
| } |
| this->numberOfCharacters = 0; |
| this->numberOfNonWhitespaceCharacters = 0; |
| this->numberOfWords = 0; |
| this->numberOfLines = 0; |
| this->calcStatistics(); |
| } |
| |
| |
| const VisualString& VisualString::operator+(const VisualString& other) { |
| VisualString* stringCopy = this->clone(); |
| uint32 prevNumberOfCharacters = stringCopy->numberOfCharacters; |
| stringCopy->numberOfCharacters += other.numberOfCharacters; |
| if (stringCopy->numberOfCharacters > prevNumberOfCharacters) { |
| #if TARGET_OS_MAC |
| if (prevNumberOfCharacters == 0) { |
| stringCopy = other.clone(); |
| } else { |
| if (other.numberOfCharacters > 0) { |
| CFStringAppend(stringCopy->theString, other.getCharactersPointer()); |
| } |
| } |
| #endif |
| #if TARGET_OS_WIN |
| size_t sizeInBytes = (stringCopy->numberOfCharacters + 1) * sizeof(wchar_t); |
| free(stringCopy->theString); |
| stringCopy->theString = (wchar_t*)malloc(sizeInBytes); |
| for (uint32 i = 0; i < prevNumberOfCharacters; i++) { |
| stringCopy->theString[i] = this->theString[i]; |
| } |
| uint32 count = 0; |
| for (uint32 i = prevNumberOfCharacters; i < stringCopy->numberOfCharacters; i++) { |
| stringCopy->theString[i] = other.theString[count]; |
| count++; |
| } |
| stringCopy->theString[stringCopy->numberOfCharacters] = L'\0'; |
| #endif |
| } |
| stringCopy->numberOfNonWhitespaceCharacters = 0; |
| stringCopy->numberOfWords = 0; |
| stringCopy->numberOfLines = 0; |
| stringCopy->calcStatistics(); |
| return *stringCopy; |
| } |
| |
| |
| const VisualString& VisualString::operator+(const char* charString) { |
| VisualString* stringCopy = new VisualString(*this); |
| uint32 prevNumberOfCharacters = stringCopy->numberOfCharacters; |
| stringCopy->numberOfCharacters += strlen(charString); |
| if (stringCopy->numberOfCharacters > prevNumberOfCharacters) { |
| #if TARGET_OS_MAC |
| if (prevNumberOfCharacters == 0) { |
| stringCopy->initWithUTF8String(charString); |
| } else { |
| CFStringAppendCString(stringCopy->theString, charString, kCFStringEncodingUTF8); |
| } |
| #endif |
| #if TARGET_OS_WIN |
| size_t sizeInBytes = (stringCopy->numberOfCharacters + 1) * sizeof(wchar_t); |
| free(stringCopy->theString); |
| stringCopy->theString = (wchar_t*)malloc(sizeInBytes); |
| for (uint32 i = 0; i < prevNumberOfCharacters; i++) { |
| stringCopy->theString[i] = this->theString[i]; |
| } |
| uint32 count = 0; |
| for (uint32 i = prevNumberOfCharacters; i < stringCopy->numberOfCharacters; i++) { |
| stringCopy->theString[i] = (wchar_t)charString[count]; |
| count++; |
| } |
| stringCopy->theString[stringCopy->numberOfCharacters] = L'\0'; |
| #endif |
| } |
| stringCopy->numberOfNonWhitespaceCharacters = 0; |
| stringCopy->numberOfWords = 0; |
| stringCopy->numberOfLines = 0; |
| stringCopy->calcStatistics(); |
| return *stringCopy; |
| } |
| |
| |
| VisualString* VisualString::clone(void) const { |
| return new VisualString(*this); |
| } |
| |
| |
| uint32 VisualString::getNumberOfCharacters() const { |
| return this->numberOfCharacters; |
| } |
| |
| |
| uint32 VisualString::getNumberOfNonWhitespaceCharacters() const { |
| return this->numberOfNonWhitespaceCharacters; |
| } |
| |
| |
| bool VisualString::isEmpty(void) const { |
| if (this->numberOfNonWhitespaceCharacters == 0) { |
| return true; |
| } |
| return false; |
| } |
| |
| |
| uint32 VisualString::getNumberOfWords(void) const { |
| return this->numberOfWords; |
| } |
| |
| |
| uint32 VisualString::getNumberOfLines(void) const { |
| return this->numberOfLines; |
| } |
| |
| |
| VisualString* VisualString::createStringWithLine(uint32 index) const { |
| VisualString* stringAtLine = NULL; |
| #if TARGET_OS_WIN |
| stringAtLine = new VisualString((uint16*)&this->theString[this->arrayOfLines[index].startIndex], this->arrayOfLines[index].numberOfCharacters); |
| #endif |
| #if TARGET_OS_MAC |
| CFStringRef string = CFStringCreateWithSubstring(kCFAllocatorDefault, this->theString, CFRangeMake(this->arrayOfLines[index].startIndex, this->arrayOfLines[index].numberOfCharacters)); |
| stringAtLine = new VisualString(string); |
| CFRelease(string); |
| #endif |
| return stringAtLine; |
| } |
| |
| |
| VisualString* VisualString::createStringWithWord(uint32 index) const { |
| VisualString* wordAtIndex = NULL; |
| #if TARGET_OS_WIN |
| wordAtIndex = new VisualString((uint16*)&this->theString[this->arrayOfWords[index].startIndex], this->arrayOfWords[index].numberOfCharacters); |
| #endif |
| #if TARGET_OS_MAC |
| CFStringRef string = CFStringCreateWithSubstring(kCFAllocatorDefault, this->theString, CFRangeMake(this->arrayOfWords[index].startIndex, this->arrayOfWords[index].numberOfCharacters)); |
| wordAtIndex = new VisualString(string); |
| CFRelease(string); |
| #endif |
| return wordAtIndex; |
| } |
| |
| |
| ConstStringDataRef VisualString::getCharactersPointer() const { |
| return this->theString; |
| } |
| |
| |
| const char* const VisualString::getUtf8Representation() { |
| if (this->utf8representation != NULL) { |
| free(this->utf8representation); |
| this->utf8representation = NULL; |
| } |
| #if TARGET_OS_MAC |
| if (this->theString != NULL) { |
| CFRange range = {0, CFStringGetLength(this->theString)}; |
| uint8 lossByte = 0; |
| Boolean isExternalRepresentation = false; |
| CFIndex maxBufLen = 0; |
| CFIndex numberOfBytes = 0; |
| CFIndex numberOfCharsConverted; |
| numberOfCharsConverted = CFStringGetBytes(this->theString, range, kCFStringEncodingUTF8, lossByte, isExternalRepresentation, NULL, maxBufLen, &numberOfBytes); |
| if ((numberOfCharsConverted == CFStringGetLength(this->theString)) && (numberOfBytes > 0)) { |
| this->utf8representation = (char*)malloc(numberOfBytes + 1); |
| numberOfCharsConverted = CFStringGetBytes(this->theString, range, kCFStringEncodingUTF8, lossByte, isExternalRepresentation, (uint8*)this->utf8representation, numberOfBytes, &numberOfBytes); |
| this->utf8representation[numberOfBytes] = '\0'; |
| } |
| } |
| |
| /* |
| const char* scriptPathConstCStr = CFStringGetCStringPtr(scriptFilePath.getCharactersPointer(), kCFStringEncodingUTF8); |
| char* scriptPathCStr = NULL; |
| if (scriptPathConstCStr == NULL) { |
| CFIndex stringLength = CFStringGetLength(scriptFileSystemPath); |
| CFIndex maxSize = CFStringGetMaximumSizeForEncoding(stringLength, kCFStringEncodingUTF8); |
| scriptPathCStr = (char*)malloc((maxSize + 1) * sizeof(char)); |
| bool success = CFStringGetCString(scriptFileSystemPath, scriptPathCStr, maxSize, kCFStringEncodingUTF8); |
| if (success == false) { |
| return false; |
| } |
| } |
| CFRelease(scriptFileSystemPath); |
| */ |
| |
| #endif |
| |
| #if TARGET_OS_WIN |
| DWORD dwFlags = 0; |
| int cbMultiByte = 0; |
| LPCSTR lpDefaultChar = NULL; |
| LPBOOL lpUsedDefaultChar = NULL; |
| int numberOfDestinationBytes = 0; |
| int numberOfBytesRequired = WideCharToMultiByte(CP_UTF8, dwFlags, this->theString, this->numberOfCharacters, this->utf8representation, numberOfDestinationBytes, lpDefaultChar, lpUsedDefaultChar); |
| if (numberOfBytesRequired > 0) { |
| numberOfDestinationBytes = numberOfBytesRequired; |
| this->utf8representation = (char*)malloc(numberOfDestinationBytes + 1); |
| int bytesConverted = WideCharToMultiByte(CP_UTF8, dwFlags, this->theString, this->numberOfCharacters, this->utf8representation, numberOfDestinationBytes, lpDefaultChar, lpUsedDefaultChar); |
| this->utf8representation[numberOfDestinationBytes] = '\0'; |
| } |
| #endif |
| |
| return this->utf8representation; |
| } |
| |
| |
| |
| const uint16* const VisualString::getUtf16Representation() { |
| #if TARGET_OS_MAC |
| if (this->utf16representation != NULL) { |
| free(this->utf16representation); |
| this->utf16representation = NULL; |
| } |
| if (this->theString != NULL) { |
| CFIndex length = CFStringGetLength(this->theString); |
| this->utf16representation = (uint16*)malloc(((length + 1) * sizeof(uint16))); |
| CFStringGetCharacters(this->theString, CFRangeMake(0, length), this->utf16representation); |
| this->utf16representation[length] = 0; |
| } |
| |
| return this->utf16representation; |
| #endif |
| #if TARGET_OS_WIN |
| return (uint16*)this->theString; |
| #endif |
| } |
| |
| |
| VisualString VisualString::getSubstring(uint32 startIdx, uint32 numberOfSubstringCharacters) const { |
| VisualString subString; |
| if ((startIdx + numberOfSubstringCharacters) > this->numberOfCharacters) { |
| return subString; |
| } |
| uint32 numberOfUTF16Characters = 1; |
| for (uint32 i = startIdx; i < (startIdx + numberOfSubstringCharacters); i++) { |
| uint16 characterAtIndex = this->getCharacterAtIndex(i); |
| VisualString* character = VisualString::createWithUTF16Buffer(&characterAtIndex, numberOfUTF16Characters); |
| if (character) { |
| subString = subString + *character; |
| delete character; |
| } |
| } |
| return subString; |
| } |
| |
| |
| void VisualString::normalizeLineEndings() { |
| #if TARGET_OS_WIN |
| VisualString* normalizedString = new VisualString; |
| size_t numberOfCharacters = this->getNumberOfCharacters(); |
| uint32 numberOfCharactersOfSubstring = 1; |
| uint16 verticalTabChar = 0x000B; // 11 |
| uint16 lineFeedChar = 0x000A; // 10 |
| uint16 carriageReturnChar = 0x000D; // 13 |
| VisualString verticalTab; |
| verticalTab.initWithUTF16Buffer(&verticalTabChar, numberOfCharactersOfSubstring); |
| VisualString lineFeed; |
| lineFeed.initWithUTF16Buffer(&lineFeedChar, numberOfCharactersOfSubstring); |
| VisualString carriageReturn; |
| carriageReturn.initWithUTF16Buffer(&carriageReturnChar, numberOfCharactersOfSubstring); |
| |
| for (size_t i = 0; i < numberOfCharacters; i++) { |
| VisualString character = this->getSubstring(i, numberOfCharactersOfSubstring); |
| if ((character == carriageReturn) && (i < (numberOfCharacters - 1))) { |
| *normalizedString = *normalizedString + character; |
| VisualString nextCharacter = this->getSubstring(i + 1, numberOfCharactersOfSubstring); |
| if (nextCharacter != lineFeed) { |
| *normalizedString = *normalizedString + lineFeed; |
| } |
| } else if ((character == carriageReturn) && (i == (numberOfCharacters - 1))) { |
| *normalizedString = *normalizedString + character; |
| *normalizedString = *normalizedString + lineFeed; |
| } else if (character == verticalTab) { |
| *normalizedString = *normalizedString + carriageReturn; |
| *normalizedString = *normalizedString + lineFeed; |
| } else { |
| *normalizedString = *normalizedString + character; |
| } |
| } |
| #endif |
| #if TARGET_OS_MAC |
| VisualString* normalizedString = this->clone(); |
| #endif |
| |
| this->initWithUTF16Buffer(normalizedString->getUtf16Representation(), normalizedString->getNumberOfCharacters()); |
| |
| delete normalizedString; |
| } |
| |
| |
| uint16 VisualString::getCharacterAtIndex(uint32 index) const { |
| #if TARGET_OS_MAC |
| return CFStringGetCharacterAtIndex(this->theString, index); |
| #endif |
| #if TARGET_OS_WIN |
| return this->theString[index]; |
| #endif |
| } |
| |
| |
| bool VisualString::characterIsNewlineCharacter(uint16 character) { |
| #if TARGET_OS_MAC |
| uint8 uniCharArrayLength = 5; |
| uint16* uniCharArray = (uint16*)malloc(uniCharArrayLength * sizeof(uint16)); |
| uniCharArray[0] = 0x000D; // CR |
| uniCharArray[1] = 0x000A; // LF |
| uniCharArray[2] = 0x2028; // LSEP |
| uniCharArray[3] = 0x2029; // PSEP |
| uniCharArray[4] = 0x0085; // NL |
| for (uint8 i = 0; i < uniCharArrayLength; i++) { |
| if (character == uniCharArray[i]) { |
| return true; |
| } |
| } |
| delete uniCharArray; |
| #endif |
| #if TARGET_OS_WIN |
| if ((character == L'\n') || (character == L'\r')) { |
| return true; |
| } |
| #endif |
| return false; |
| } |
| |
| |
| bool VisualString::characterIsWhitespaceCharacter(uint16 character) { |
| |
| // word separators |
| // delimiters(" \t\n~;()'\"<>:{}[]+-=&*#.,/\\"); |
| |
| #if TARGET_OS_MAC |
| CFCharacterSetRef whitespaceAndNewlineSet = CFCharacterSetGetPredefined(kCFCharacterSetWhitespaceAndNewline); |
| Boolean isWhitespace = CFCharacterSetIsCharacterMember(whitespaceAndNewlineSet, character); |
| if (isWhitespace) { |
| return true; |
| } else { |
| return false; |
| } |
| #endif |
| #if TARGET_OS_WIN |
| if ((character == L' ') || (character == L'\n') || (character == L'\r') || (character == L'\t')) { |
| return true; |
| } |
| #endif |
| return false; |
| } |
| |
| |
| void VisualString::writeDebugLog() const { |
| #if TARGET_OS_MAC |
| logString(this); |
| CFShowStr(this->theString); |
| #endif |
| #if TARGET_OS_WIN |
| writeLogW(this->theString); |
| #endif |
| } |
| |
| |
| std::vector<VisualString> VisualString::splitWithDelimiter(const VisualString& delimiter) { |
| std::vector<VisualString> stringArray; |
| // todo |
| /* |
| #if TARGET_OS_MAC |
| CFArrayRef array = CFStringCreateArrayBySeparatingStrings(kCFAllocatorDefault, this->getCharactersPointer(), delimiter.getCharactersPointer()); |
| for (CFIndex i = 0; i < CFArrayGetCount(array); i++) { |
| CFStringRef stringRef = (CFStringRef)CFArrayGetValueAtIndex(array, i); |
| CFIndex length = CFStringGetLength(stringRef); |
| uint16* unicodeBuffer = (uint16*)malloc(length * sizeof(uint16)); |
| CFStringGetCharacters(stringRef, CFRangeMake(0, length), unicodeBuffer); |
| VisualString visualString; |
| visualString.initWithUTF16Buffer(unicodeBuffer, length); |
| stringArray.push_back(visualString); |
| free(unicodeBuffer); |
| } |
| CFRelease(array); |
| #endif |
| */ |
| |
| //#if TARGET_OS_WIN |
| uint16 delimiterChar = const_cast<VisualString&>(delimiter).getCharacterAtIndex(0); |
| VisualStringSubstringPointer substring; |
| substring.startIndex = 0; |
| substring.numberOfCharacters = 0; |
| uint32 currCharPointerEnd = 0; |
| uint32 prevCharPointerEnd = 0; |
| for (uint32 i = 0; i < this->getNumberOfCharacters(); i++) { |
| uint16 currChar = this->getCharacterAtIndex(i); |
| if (currChar == delimiterChar) { |
| substring.numberOfCharacters = currCharPointerEnd - prevCharPointerEnd; |
| uint16* unicodeBuffer = (uint16*)malloc(substring.numberOfCharacters * sizeof(uint16)); |
| uint16* stringBufferSrc = const_cast<uint16*>(this->getUtf16Representation()); |
| stringBufferSrc += prevCharPointerEnd; |
| memcpy(unicodeBuffer, stringBufferSrc, substring.numberOfCharacters * sizeof(uint16)); |
| VisualString visualString; |
| visualString.initWithUTF16Buffer(unicodeBuffer, substring.numberOfCharacters); |
| stringArray.push_back(visualString); |
| free(unicodeBuffer); |
| substring.startIndex = i + 1; |
| prevCharPointerEnd = i + 1; |
| } |
| currCharPointerEnd++; |
| } |
| substring.numberOfCharacters = currCharPointerEnd - prevCharPointerEnd; |
| if (substring.numberOfCharacters > 0) { |
| uint16* unicodeBuffer = (uint16*)malloc(substring.numberOfCharacters * sizeof(uint16)); |
| uint16* stringBufferSrc = const_cast<uint16*>(this->getUtf16Representation()); |
| stringBufferSrc += prevCharPointerEnd; |
| memcpy(unicodeBuffer, stringBufferSrc, substring.numberOfCharacters * sizeof(uint16)); |
| VisualString visualString; |
| visualString.initWithUTF16Buffer(unicodeBuffer, substring.numberOfCharacters); |
| stringArray.push_back(visualString); |
| free(unicodeBuffer); |
| } |
| //#endif |
| return stringArray; |
| } |
| |
| |
| void VisualString::trim() { |
| #if TARGET_OS_MAC |
| CFStringTrimWhitespace(this->theString); |
| #endif |
| } |
| |
| |
| VisualString* VisualString::createJoinedString(std::vector<VisualString> stringVector) { |
| VisualString string; |
| uint32 numberOfLines = stringVector.size(); |
| for (uint32 i = 0; i < numberOfLines; i++) { |
| string = string + stringVector[i]; |
| string = string + "\n"; |
| } |
| VisualString* returnString = VisualString::createWithUTF8String(string.getUtf8Representation()); |
| return returnString; |
| } |
| |
| |
| void VisualString::calcStatistics() { |
| |
| if (this->arrayOfWords.size() > 0) { |
| this->arrayOfWords.clear(); |
| } |
| if (this->arrayOfLines.size() > 0) { |
| this->arrayOfLines.clear(); |
| } |
| |
| if (this->numberOfCharacters == 0) return; |
| |
| this->numberOfNonWhitespaceCharacters = 0; |
| this->numberOfWords = 0; |
| this->numberOfLines = 0; |
| |
| bool scannerIsInWord = false; |
| bool scannerIsInLine = false; |
| sint32 lineStartPos = -1; |
| sint32 wordStartPos = -1; |
| uint32 numberOfLineCharsScanned = 0; |
| uint32 numberOfWordCharsScanned = 0; |
| |
| VisualStringSubstringPointer visualStringSubstringPointer; |
| |
| for (uint32 i = 0; i < this->numberOfCharacters; i++) { |
| if (this->characterIsNewlineCharacter(this->getCharacterAtIndex(i)) == true) { |
| if (scannerIsInLine == true) { |
| visualStringSubstringPointer.startIndex = lineStartPos; |
| visualStringSubstringPointer.numberOfCharacters = numberOfLineCharsScanned; |
| this->arrayOfLines.push_back(visualStringSubstringPointer); |
| this->numberOfLines++; |
| lineStartPos = -1; |
| numberOfLineCharsScanned = 0; |
| scannerIsInLine = false; |
| } |
| } else { |
| if (scannerIsInLine == false) { |
| scannerIsInLine = true; |
| lineStartPos = i; |
| } |
| numberOfLineCharsScanned++; |
| } |
| if (this->characterIsWhitespaceCharacter(this->getCharacterAtIndex(i)) == true) { |
| if (scannerIsInWord == true) { |
| visualStringSubstringPointer.startIndex = wordStartPos; |
| visualStringSubstringPointer.numberOfCharacters = numberOfWordCharsScanned; |
| this->arrayOfWords.push_back(visualStringSubstringPointer); |
| this->numberOfWords++; |
| wordStartPos = -1; |
| numberOfWordCharsScanned = 0; |
| scannerIsInWord = false; |
| } |
| } else { |
| if (scannerIsInWord == false) { |
| scannerIsInWord = true; |
| wordStartPos = i; |
| } |
| numberOfWordCharsScanned++; |
| this->numberOfNonWhitespaceCharacters++; |
| } |
| } |
| if (this->characterIsNewlineCharacter(this->getCharacterAtIndex(this->numberOfCharacters - 1)) == false) { |
| visualStringSubstringPointer.startIndex = lineStartPos; |
| visualStringSubstringPointer.numberOfCharacters = numberOfLineCharsScanned; |
| this->arrayOfLines.push_back(visualStringSubstringPointer); |
| this->numberOfLines++; |
| } |
| if (this->characterIsWhitespaceCharacter(this->getCharacterAtIndex(this->numberOfCharacters - 1)) == false) { |
| visualStringSubstringPointer.startIndex = wordStartPos; |
| visualStringSubstringPointer.numberOfCharacters = numberOfWordCharsScanned; |
| this->arrayOfWords.push_back(visualStringSubstringPointer); |
| this->numberOfWords++; |
| } |
| |
| } |
| |
| |
| VisualString* VisualString::createWithUTF8String(const char* const aStringVal) { |
| VisualString* aVisualString = new VisualString(aStringVal); |
| return aVisualString; |
| } |
| |
| |
| VisualString* VisualString::createWithUTF8Buffer(const char* const aStringVal, uint32 numberOfBytes) { |
| VisualString* aVisualString = new VisualString(aStringVal, numberOfBytes); |
| return aVisualString; |
| } |
| |
| |
| VisualString* VisualString::createWithUTF16String(const uint16* const aStringVal) { |
| VisualString* aVisualString = new VisualString(aStringVal); |
| return aVisualString; |
| } |
| |
| |
| VisualString* VisualString::createWithUTF16Buffer(const uint16* const aStringVal, uint32 aNumberOfCharacters) { |
| VisualString* aVisualString = new VisualString(aStringVal, aNumberOfCharacters); |
| return aVisualString; |
| } |
| |
| |
| VisualString* VisualString::createWithContentsOfFile(VisualFile& aFile) { |
| VisualString* aVisualString = new VisualString; |
| bool success = aVisualString->initWithContentsOfFile(aFile); |
| if (!success) { |
| delete aVisualString; |
| aVisualString = NULL; |
| } |
| return aVisualString; |
| } |
| |
| |
| VisualString* VisualString::createWithContentsOfURL(const char* const aURL, const VisualItemIdentifier& anId) { |
| VisualString* aVisualString = new VisualString; |
| bool success = aVisualString->initWithContentsOfURL(aURL, anId); |
| if (!success) { |
| delete aVisualString; |
| aVisualString = NULL; |
| } |
| return aVisualString; |
| } |
| |
| |
| VisualString* VisualString::createWithConstStringDataRef(ConstStringDataRef constStringDataRef) { |
| VisualString* aVisualString = new VisualString; |
| bool success = aVisualString->initWithConstStringDataRef(constStringDataRef); |
| if (!success) { |
| delete aVisualString; |
| aVisualString = NULL; |
| } |
| return aVisualString; |
| } |
| |
| |
| void VisualString::dataLoadDidEnd(const VisualItemIdentifier& identifier) { |
| if (this->hasData()) { |
| this->initWithUTF8Buffer((const char*)this->getData(), this->getDataSize()); |
| } |
| this->freeData(); |
| if (this->theString != NULL) { |
| VisualNotification aNotification(identifier); |
| aNotification.setKey(kStringWithIdentifierLoadedAndCreatedMsg); |
| aNotification.setPointer(this); |
| aNotification.post(); |
| } |
| } |