提交 f102f9c1 编写于 作者: A Adam Barth 提交者: GitHub

Remove dead code (#2991)

This code is unused.
上级 d8d5708f
......@@ -27,7 +27,6 @@
#include "flutter/sky/engine/platform/FloatConversion.h"
#include "flutter/sky/engine/platform/fonts/FontSelector.h"
#include "flutter/sky/engine/platform/graphics/GraphicsContextStateSaver.h"
#include "flutter/sky/engine/platform/text/StringTruncator.h"
#include "flutter/sky/engine/public/platform/Platform.h"
#include "flutter/sky/engine/wtf/text/StringBuilder.h"
......
......@@ -189,22 +189,11 @@ source_set("platform") {
"text/BidiRunList.h",
"text/BidiTextRun.cpp",
"text/BidiTextRun.h",
"text/DateTimeFormat.cpp",
"text/DateTimeFormat.h",
"text/DecodeEscapeSequences.h",
"text/LineEnding.cpp",
"text/LineEnding.h",
"text/LocaleToScriptMapping.cpp",
"text/LocaleToScriptMapping.h",
"text/NonCJKGlyphOrientation.h",
"text/ParserUtilities.h",
"text/QuotedPrintable.cpp",
"text/QuotedPrintable.h",
"text/SegmentedString.cpp",
"text/SegmentedString.h",
"text/StringTruncator.cpp",
"text/StringTruncator.h",
"text/SuffixTree.h",
"text/SurrogatePairAwareTextIterator.cpp",
"text/SurrogatePairAwareTextIterator.h",
"text/TextBoundaries.cpp",
......@@ -215,8 +204,6 @@ source_set("platform") {
"text/TextBreakIteratorICU.cpp",
"text/TextBreakIteratorInternalICU.cpp",
"text/TextBreakIteratorInternalICU.h",
"text/TextCheckerClient.h",
"text/TextChecking.h",
"text/TextDecoration.h",
"text/TextDirection.h",
"text/TextPath.h",
......
/*
* Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "flutter/sky/engine/platform/text/DateTimeFormat.h"
#include "flutter/sky/engine/wtf/ASCIICType.h"
#include "flutter/sky/engine/wtf/text/StringBuilder.h"
namespace blink {
static const DateTimeFormat::FieldType lowerCaseToFieldTypeMap[26] = {
DateTimeFormat::FieldTypePeriod, // a
DateTimeFormat::FieldTypeInvalid, // b
DateTimeFormat::FieldTypeLocalDayOfWeekStandAlon, // c
DateTimeFormat::FieldTypeDayOfMonth, // d
DateTimeFormat::FieldTypeLocalDayOfWeek, // e
DateTimeFormat::FieldTypeInvalid, // f
DateTimeFormat::FieldTypeModifiedJulianDay, // g
DateTimeFormat::FieldTypeHour12, // h
DateTimeFormat::FieldTypeInvalid, // i
DateTimeFormat::FieldTypeInvalid, // j
DateTimeFormat::FieldTypeHour24, // k
DateTimeFormat::FieldTypeInvalid, // l
DateTimeFormat::FieldTypeMinute, // m
DateTimeFormat::FieldTypeInvalid, // n
DateTimeFormat::FieldTypeInvalid, // o
DateTimeFormat::FieldTypeInvalid, // p
DateTimeFormat::FieldTypeQuaterStandAlone, // q
DateTimeFormat::FieldTypeInvalid, // r
DateTimeFormat::FieldTypeSecond, // s
DateTimeFormat::FieldTypeInvalid, // t
DateTimeFormat::FieldTypeExtendedYear, // u
DateTimeFormat::FieldTypeNonLocationZone, // v
DateTimeFormat::FieldTypeWeekOfYear, // w
DateTimeFormat::FieldTypeInvalid, // x
DateTimeFormat::FieldTypeYear, // y
DateTimeFormat::FieldTypeZone, // z
};
static const DateTimeFormat::FieldType upperCaseToFieldTypeMap[26] = {
DateTimeFormat::FieldTypeMillisecondsInDay, // A
DateTimeFormat::FieldTypeInvalid, // B
DateTimeFormat::FieldTypeInvalid, // C
DateTimeFormat::FieldTypeDayOfYear, // D
DateTimeFormat::FieldTypeDayOfWeek, // E
DateTimeFormat::FieldTypeDayOfWeekInMonth, // F
DateTimeFormat::FieldTypeEra, // G
DateTimeFormat::FieldTypeHour23, // H
DateTimeFormat::FieldTypeInvalid, // I
DateTimeFormat::FieldTypeInvalid, // J
DateTimeFormat::FieldTypeHour11, // K
DateTimeFormat::FieldTypeMonthStandAlone, // L
DateTimeFormat::FieldTypeMonth, // M
DateTimeFormat::FieldTypeInvalid, // N
DateTimeFormat::FieldTypeInvalid, // O
DateTimeFormat::FieldTypeInvalid, // P
DateTimeFormat::FieldTypeQuater, // Q
DateTimeFormat::FieldTypeInvalid, // R
DateTimeFormat::FieldTypeFractionalSecond, // S
DateTimeFormat::FieldTypeInvalid, // T
DateTimeFormat::FieldTypeInvalid, // U
DateTimeFormat::FieldTypeInvalid, // V
DateTimeFormat::FieldTypeWeekOfMonth, // W
DateTimeFormat::FieldTypeInvalid, // X
DateTimeFormat::FieldTypeYearOfWeekOfYear, // Y
DateTimeFormat::FieldTypeRFC822Zone, // Z
};
static DateTimeFormat::FieldType mapCharacterToFieldType(const UChar ch)
{
if (isASCIIUpper(ch))
return upperCaseToFieldTypeMap[ch - 'A'];
if (isASCIILower(ch))
return lowerCaseToFieldTypeMap[ch - 'a'];
return DateTimeFormat::FieldTypeLiteral;
}
bool DateTimeFormat::parse(const String& source, TokenHandler& tokenHandler)
{
enum State {
StateInQuote,
StateInQuoteQuote,
StateLiteral,
StateQuote,
StateSymbol,
} state = StateLiteral;
FieldType fieldType = FieldTypeLiteral;
StringBuilder literalBuffer;
int fieldCounter = 0;
for (unsigned index = 0; index < source.length(); ++index) {
const UChar ch = source[index];
switch (state) {
case StateInQuote:
if (ch == '\'') {
state = StateInQuoteQuote;
break;
}
literalBuffer.append(ch);
break;
case StateInQuoteQuote:
if (ch == '\'') {
literalBuffer.append('\'');
state = StateInQuote;
break;
}
fieldType = mapCharacterToFieldType(ch);
if (fieldType == FieldTypeInvalid)
return false;
if (fieldType == FieldTypeLiteral) {
literalBuffer.append(ch);
state = StateLiteral;
break;
}
if (literalBuffer.length()) {
tokenHandler.visitLiteral(literalBuffer.toString());
literalBuffer.clear();
}
fieldCounter = 1;
state = StateSymbol;
break;
case StateLiteral:
if (ch == '\'') {
state = StateQuote;
break;
}
fieldType = mapCharacterToFieldType(ch);
if (fieldType == FieldTypeInvalid)
return false;
if (fieldType == FieldTypeLiteral) {
literalBuffer.append(ch);
break;
}
if (literalBuffer.length()) {
tokenHandler.visitLiteral(literalBuffer.toString());
literalBuffer.clear();
}
fieldCounter = 1;
state = StateSymbol;
break;
case StateQuote:
literalBuffer.append(ch);
state = ch == '\'' ? StateLiteral : StateInQuote;
break;
case StateSymbol: {
ASSERT(fieldType != FieldTypeInvalid);
ASSERT(fieldType != FieldTypeLiteral);
ASSERT(literalBuffer.isEmpty());
FieldType fieldType2 = mapCharacterToFieldType(ch);
if (fieldType2 == FieldTypeInvalid)
return false;
if (fieldType == fieldType2) {
++fieldCounter;
break;
}
tokenHandler.visitField(fieldType, fieldCounter);
if (fieldType2 == FieldTypeLiteral) {
if (ch == '\'') {
state = StateQuote;
} else {
literalBuffer.append(ch);
state = StateLiteral;
}
break;
}
fieldCounter = 1;
fieldType = fieldType2;
break;
}
}
}
ASSERT(fieldType != FieldTypeInvalid);
switch (state) {
case StateLiteral:
case StateInQuoteQuote:
if (literalBuffer.length())
tokenHandler.visitLiteral(literalBuffer.toString());
return true;
case StateQuote:
case StateInQuote:
if (literalBuffer.length())
tokenHandler.visitLiteral(literalBuffer.toString());
return false;
case StateSymbol:
ASSERT(fieldType != FieldTypeLiteral);
ASSERT(!literalBuffer.length());
tokenHandler.visitField(fieldType, fieldCounter);
return true;
}
ASSERT_NOT_REACHED();
return false;
}
static bool isASCIIAlphabetOrQuote(UChar ch)
{
return isASCIIAlpha(ch) || ch == '\'';
}
void DateTimeFormat::quoteAndAppendLiteral(const String& literal, StringBuilder& buffer)
{
if (literal.length() <= 0)
return;
if (literal.find(isASCIIAlphabetOrQuote) == kNotFound) {
buffer.append(literal);
return;
}
if (literal.find('\'') == kNotFound) {
buffer.append('\'');
buffer.append(literal);
buffer.append('\'');
return;
}
for (unsigned i = 0; i < literal.length(); ++i) {
if (literal[i] == '\'') {
buffer.appendLiteral("''");
} else {
String escaped = literal.substring(i);
escaped.replace("'", "''");
buffer.append('\'');
buffer.append(escaped);
buffer.append('\'');
return;
}
}
}
} // namespace blink
/*
* Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
#ifndef SKY_ENGINE_PLATFORM_TEXT_DATETIMEFORMAT_H_
#define SKY_ENGINE_PLATFORM_TEXT_DATETIMEFORMAT_H_
#include "flutter/sky/engine/platform/PlatformExport.h"
#include "flutter/sky/engine/wtf/Forward.h"
namespace blink {
// DateTimeFormat parses date time format defined in Unicode Technical
// standard 35, Locale Data Markup Language (LDML)[1].
// [1] LDML http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns
class PLATFORM_EXPORT DateTimeFormat {
public:
enum FieldType {
FieldTypeInvalid,
FieldTypeLiteral,
// Era: AD
FieldTypeEra = 'G',
// Year: 1996
FieldTypeYear = 'y',
FieldTypeYearOfWeekOfYear = 'Y',
FieldTypeExtendedYear = 'u',
// Quater: Q2
FieldTypeQuater = 'Q',
FieldTypeQuaterStandAlone = 'q',
// Month: September
FieldTypeMonth = 'M',
FieldTypeMonthStandAlone = 'L',
// Week: 42
FieldTypeWeekOfYear = 'w',
FieldTypeWeekOfMonth = 'W',
// Day: 12
FieldTypeDayOfMonth = 'd',
FieldTypeDayOfYear = 'D',
FieldTypeDayOfWeekInMonth = 'F',
FieldTypeModifiedJulianDay = 'g',
// Week Day: Tuesday
FieldTypeDayOfWeek = 'E',
FieldTypeLocalDayOfWeek = 'e',
FieldTypeLocalDayOfWeekStandAlon = 'c',
// Period: AM or PM
FieldTypePeriod = 'a',
// Hour: 7
FieldTypeHour12 = 'h',
FieldTypeHour23 = 'H',
FieldTypeHour11 = 'K',
FieldTypeHour24 = 'k',
// Minute: 59
FieldTypeMinute = 'm',
// Second: 12
FieldTypeSecond = 's',
FieldTypeFractionalSecond = 'S',
FieldTypeMillisecondsInDay = 'A',
// Zone: PDT
FieldTypeZone = 'z',
FieldTypeRFC822Zone = 'Z',
FieldTypeNonLocationZone = 'v',
};
class TokenHandler {
public:
virtual ~TokenHandler() { }
virtual void visitField(FieldType, int numberOfPatternCharacters) = 0;
virtual void visitLiteral(const String&) = 0;
};
// Returns true if succeeded, false if failed.
static bool parse(const String&, TokenHandler&);
static void quoteAndAppendLiteral(const String&, StringBuilder&);
};
} // namespace blink
#endif // SKY_ENGINE_PLATFORM_TEXT_DATETIMEFORMAT_H_
/*
* Copyright (C) 2011 Daniel Bates (dbates@intudata.com). All Rights Reserved.
* Copyright (c) 2012 Google, inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SKY_ENGINE_PLATFORM_TEXT_DECODEESCAPESEQUENCES_H_
#define SKY_ENGINE_PLATFORM_TEXT_DECODEESCAPESEQUENCES_H_
#include "flutter/sky/engine/wtf/ASCIICType.h"
#include "flutter/sky/engine/wtf/Assertions.h"
#include "flutter/sky/engine/wtf/text/StringBuilder.h"
#include "flutter/sky/engine/wtf/text/TextEncoding.h"
namespace blink {
// See <http://en.wikipedia.org/wiki/Percent-encoding#Non-standard_implementations>.
struct Unicode16BitEscapeSequence {
enum { sequenceSize = 6 }; // e.g. %u26C4
static size_t findInString(const String& string, size_t startPosition) { return string.find("%u", startPosition); }
static size_t findEndOfRun(const String& string, size_t startPosition, size_t endPosition)
{
size_t runEnd = startPosition;
while (endPosition - runEnd >= sequenceSize && string[runEnd] == '%' && string[runEnd + 1] == 'u'
&& isASCIIHexDigit(string[runEnd + 2]) && isASCIIHexDigit(string[runEnd + 3])
&& isASCIIHexDigit(string[runEnd + 4]) && isASCIIHexDigit(string[runEnd + 5])) {
runEnd += sequenceSize;
}
return runEnd;
}
template<typename CharType>
static String decodeRun(const CharType* run, size_t runLength, const WTF::TextEncoding&)
{
// Each %u-escape sequence represents a UTF-16 code unit.
// See <http://www.w3.org/International/iri-edit/draft-duerst-iri.html#anchor29>.
// For 16-bit escape sequences, we know that findEndOfRun() has given us a contiguous run of sequences
// without any intervening characters, so decode the run without additional checks.
size_t numberOfSequences = runLength / sequenceSize;
StringBuilder builder;
builder.reserveCapacity(numberOfSequences);
while (numberOfSequences--) {
UChar codeUnit = (toASCIIHexValue(run[2]) << 12) | (toASCIIHexValue(run[3]) << 8) | (toASCIIHexValue(run[4]) << 4) | toASCIIHexValue(run[5]);
builder.append(codeUnit);
run += sequenceSize;
}
return builder.toString();
}
};
struct URLEscapeSequence {
enum { sequenceSize = 3 }; // e.g. %41
static size_t findInString(const String& string, size_t startPosition) { return string.find('%', startPosition); }
static size_t findEndOfRun(const String& string, size_t startPosition, size_t endPosition)
{
// Make the simplifying assumption that supported encodings may have up to two unescaped characters
// in the range 0x40 - 0x7F as the trailing bytes of their sequences which need to be passed into the
// decoder as part of the run. In other words, we end the run at the first value outside of the
// 0x40 - 0x7F range, after two values in this range, or at a %-sign that does not introduce a valid
// escape sequence.
size_t runEnd = startPosition;
int numberOfTrailingCharacters = 0;
while (runEnd < endPosition) {
if (string[runEnd] == '%') {
if (endPosition - runEnd >= sequenceSize && isASCIIHexDigit(string[runEnd + 1]) && isASCIIHexDigit(string[runEnd + 2])) {
runEnd += sequenceSize;
numberOfTrailingCharacters = 0;
} else
break;
} else if (string[runEnd] >= 0x40 && string[runEnd] <= 0x7F && numberOfTrailingCharacters < 2) {
runEnd += 1;
numberOfTrailingCharacters += 1;
} else
break;
}
return runEnd;
}
template<typename CharType>
static String decodeRun(const CharType* run, size_t runLength, const WTF::TextEncoding& encoding)
{
// For URL escape sequences, we know that findEndOfRun() has given us a run where every %-sign introduces
// a valid escape sequence, but there may be characters between the sequences.
Vector<char, 512> buffer;
buffer.resize(runLength); // Unescaping hex sequences only makes the length smaller.
char* p = buffer.data();
const CharType* runEnd = run + runLength;
while (run < runEnd) {
if (run[0] == '%') {
*p++ = (toASCIIHexValue(run[1]) << 4) | toASCIIHexValue(run[2]);
run += sequenceSize;
} else {
*p++ = run[0];
run += 1;
}
}
ASSERT(buffer.size() >= static_cast<size_t>(p - buffer.data())); // Prove buffer not overrun.
return (encoding.isValid() ? encoding : UTF8Encoding()).decode(buffer.data(), p - buffer.data());
}
};
template<typename EscapeSequence>
String decodeEscapeSequences(const String& string, const WTF::TextEncoding& encoding)
{
StringBuilder result;
size_t length = string.length();
size_t decodedPosition = 0;
size_t searchPosition = 0;
size_t encodedRunPosition;
while ((encodedRunPosition = EscapeSequence::findInString(string, searchPosition)) != kNotFound) {
size_t encodedRunEnd = EscapeSequence::findEndOfRun(string, encodedRunPosition, length);
searchPosition = encodedRunEnd;
if (encodedRunEnd == encodedRunPosition) {
++searchPosition;
continue;
}
String decoded = string.is8Bit() ?
EscapeSequence::decodeRun(string.characters8() + encodedRunPosition, encodedRunEnd - encodedRunPosition, encoding) :
EscapeSequence::decodeRun(string.characters16() + encodedRunPosition, encodedRunEnd - encodedRunPosition, encoding);
if (decoded.isEmpty())
continue;
result.append(string, decodedPosition, encodedRunPosition - decodedPosition);
result.append(decoded);
decodedPosition = encodedRunEnd;
}
result.append(string, decodedPosition, length - decodedPosition);
return result.toString();
}
} // namespace blink
#endif // SKY_ENGINE_PLATFORM_TEXT_DECODEESCAPESEQUENCES_H_
/*
* Copyright (C) 2008 Apple Inc. All Rights Reserved.
* Copyright (C) 2002, 2003 The Karbon Developers
* Copyright (C) 2006, 2007 Rob Buis <buis@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef SKY_ENGINE_PLATFORM_TEXT_PARSERUTILITIES_H_
#define SKY_ENGINE_PLATFORM_TEXT_PARSERUTILITIES_H_
#include "flutter/sky/engine/wtf/text/WTFString.h"
namespace blink {
template<typename CharType>
inline bool skipString(const CharType*& ptr, const CharType* end, const CharType* name, int length)
{
if (end - ptr < length)
return false;
if (memcmp(name, ptr, sizeof(CharType) * length))
return false;
ptr += length;
return true;
}
inline bool skipString(const UChar*& ptr, const UChar* end, const LChar* name, int length)
{
if (end - ptr < length)
return false;
for (int i = 0; i < length; ++i) {
if (ptr[i] != name[i])
return false;
}
ptr += length;
return true;
}
template<typename CharType>
inline bool skipString(const CharType*& ptr, const CharType* end, const char* str)
{
int length = strlen(str);
if (end - ptr < length)
return false;
for (int i = 0; i < length; ++i) {
if (ptr[i] != str[i])
return false;
}
ptr += length;
return true;
}
} // namespace blink
#endif // SKY_ENGINE_PLATFORM_TEXT_PARSERUTILITIES_H_
/*
* Copyright (C) 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "flutter/sky/engine/platform/text/QuotedPrintable.h"
#include "flutter/sky/engine/wtf/ASCIICType.h"
namespace blink {
static const size_t maximumLineLength = 76;
static const char crlfLineEnding[] = "\r\n";
static size_t lengthOfLineEndingAtIndex(const char* input, size_t inputLength, size_t index)
{
ASSERT_WITH_SECURITY_IMPLICATION(index < inputLength);
if (input[index] == '\n')
return 1; // Single LF.
if (input[index] == '\r') {
if ((index + 1) == inputLength || input[index + 1] != '\n')
return 1; // Single CR (Classic Mac OS).
return 2; // CR-LF.
}
return 0;
}
void quotedPrintableEncode(const Vector<char>& in, Vector<char>& out)
{
quotedPrintableEncode(in.data(), in.size(), out);
}
void quotedPrintableEncode(const char* input, size_t inputLength, Vector<char>& out)
{
out.clear();
out.reserveCapacity(inputLength);
size_t currentLineLength = 0;
for (size_t i = 0; i < inputLength; ++i) {
bool isLastCharacter = (i == inputLength - 1);
char currentCharacter = input[i];
bool requiresEncoding = false;
// All non-printable ASCII characters and = require encoding.
if ((currentCharacter < ' ' || currentCharacter > '~' || currentCharacter == '=') && currentCharacter != '\t')
requiresEncoding = true;
// Space and tab characters have to be encoded if they appear at the end of a line.
if (!requiresEncoding && (currentCharacter == '\t' || currentCharacter == ' ') && (isLastCharacter || lengthOfLineEndingAtIndex(input, inputLength, i + 1)))
requiresEncoding = true;
// End of line should be converted to CR-LF sequences.
if (!isLastCharacter) {
size_t lengthOfLineEnding = lengthOfLineEndingAtIndex(input, inputLength, i);
if (lengthOfLineEnding) {
out.append(crlfLineEnding, strlen(crlfLineEnding));
currentLineLength = 0;
i += (lengthOfLineEnding - 1); // -1 because we'll ++ in the for() above.
continue;
}
}
size_t lengthOfEncodedCharacter = 1;
if (requiresEncoding)
lengthOfEncodedCharacter += 2;
if (!isLastCharacter)
lengthOfEncodedCharacter += 1; // + 1 for the = (soft line break).
// Insert a soft line break if necessary.
if (currentLineLength + lengthOfEncodedCharacter > maximumLineLength) {
out.append('=');
out.append(crlfLineEnding, strlen(crlfLineEnding));
currentLineLength = 0;
}
// Finally, insert the actual character(s).
if (requiresEncoding) {
out.append('=');
out.append(upperNibbleToASCIIHexDigit(currentCharacter));
out.append(lowerNibbleToASCIIHexDigit(currentCharacter));
currentLineLength += 3;
} else {
out.append(currentCharacter);
currentLineLength++;
}
}
}
void quotedPrintableDecode(const Vector<char>& in, Vector<char>& out)
{
quotedPrintableDecode(in.data(), in.size(), out);
}
void quotedPrintableDecode(const char* data, size_t dataLength, Vector<char>& out)
{
out.clear();
if (!dataLength)
return;
for (size_t i = 0; i < dataLength; ++i) {
char currentCharacter = data[i];
if (currentCharacter != '=') {
out.append(currentCharacter);
continue;
}
// We are dealing with a '=xx' sequence.
if (dataLength - i < 3) {
// Unfinished = sequence, append as is.
out.append(currentCharacter);
continue;
}
char upperCharacter = data[++i];
char lowerCharacter = data[++i];
if (upperCharacter == '\r' && lowerCharacter == '\n')
continue;
if (!isASCIIHexDigit(upperCharacter) || !isASCIIHexDigit(lowerCharacter)) {
// Invalid sequence, = followed by non hex digits, just insert the characters as is.
out.append('=');
out.append(upperCharacter);
out.append(lowerCharacter);
continue;
}
out.append(static_cast<char>(toASCIIHexValue(upperCharacter, lowerCharacter)));
}
}
}
/*
* Copyright (C) 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SKY_ENGINE_PLATFORM_TEXT_QUOTEDPRINTABLE_H_
#define SKY_ENGINE_PLATFORM_TEXT_QUOTEDPRINTABLE_H_
#include "flutter/sky/engine/platform/PlatformExport.h"
#include "flutter/sky/engine/wtf/Vector.h"
namespace blink {
PLATFORM_EXPORT void quotedPrintableEncode(const Vector<char>&, Vector<char>&);
PLATFORM_EXPORT void quotedPrintableEncode(const char*, size_t, Vector<char>&);
PLATFORM_EXPORT void quotedPrintableDecode(const Vector<char>&, Vector<char>&);
PLATFORM_EXPORT void quotedPrintableDecode(const char*, size_t, Vector<char>&);
} // namespace blink
#endif // SKY_ENGINE_PLATFORM_TEXT_QUOTEDPRINTABLE_H_
/*
Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "flutter/sky/engine/platform/text/SegmentedString.h"
namespace blink {
unsigned SegmentedString::length() const
{
unsigned length = m_currentString.m_length;
if (m_pushedChar1) {
++length;
if (m_pushedChar2)
++length;
}
if (isComposite()) {
Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin();
Deque<SegmentedSubstring>::const_iterator e = m_substrings.end();
for (; it != e; ++it)
length += it->m_length;
}
return length;
}
void SegmentedString::setExcludeLineNumbers()
{
m_currentString.setExcludeLineNumbers();
if (isComposite()) {
Deque<SegmentedSubstring>::iterator it = m_substrings.begin();
Deque<SegmentedSubstring>::iterator e = m_substrings.end();
for (; it != e; ++it)
it->setExcludeLineNumbers();
}
}
void SegmentedString::clear()
{
m_pushedChar1 = 0;
m_pushedChar2 = 0;
m_currentChar = 0;
m_currentString.clear();
m_numberOfCharactersConsumedPriorToCurrentString = 0;
m_numberOfCharactersConsumedPriorToCurrentLine = 0;
m_currentLine = 0;
m_substrings.clear();
m_closed = false;
m_empty = true;
m_fastPathFlags = NoFastPath;
m_advanceFunc = &SegmentedString::advanceEmpty;
m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
}
void SegmentedString::append(const SegmentedSubstring& s)
{
ASSERT(!m_closed);
if (!s.m_length)
return;
if (!m_currentString.m_length) {
m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed();
m_currentString = s;
updateAdvanceFunctionPointers();
} else {
m_substrings.append(s);
}
m_empty = false;
}
void SegmentedString::prepend(const SegmentedSubstring& s)
{
ASSERT(!escaped());
ASSERT(!s.numberOfCharactersConsumed());
if (!s.m_length)
return;
// FIXME: We're assuming that the prepend were originally consumed by
// this SegmentedString. We're also ASSERTing that s is a fresh
// SegmentedSubstring. These assumptions are sufficient for our
// current use, but we might need to handle the more elaborate
// cases in the future.
m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed();
m_numberOfCharactersConsumedPriorToCurrentString -= s.m_length;
if (!m_currentString.m_length) {
m_currentString = s;
updateAdvanceFunctionPointers();
} else {
// Shift our m_currentString into our list.
m_substrings.prepend(m_currentString);
m_currentString = s;
updateAdvanceFunctionPointers();
}
m_empty = false;
}
void SegmentedString::close()
{
// Closing a stream twice is likely a coding mistake.
ASSERT(!m_closed);
m_closed = true;
}
void SegmentedString::append(const SegmentedString& s)
{
ASSERT(!m_closed);
if (s.m_pushedChar1) {
Vector<UChar, 2> unconsumedData;
unconsumedData.append(s.m_pushedChar1);
if (s.m_pushedChar2)
unconsumedData.append(s.m_pushedChar2);
append(SegmentedSubstring(String(unconsumedData)));
}
append(s.m_currentString);
if (s.isComposite()) {
Deque<SegmentedSubstring>::const_iterator it = s.m_substrings.begin();
Deque<SegmentedSubstring>::const_iterator e = s.m_substrings.end();
for (; it != e; ++it)
append(*it);
}
m_currentChar = m_pushedChar1 ? m_pushedChar1 : (m_currentString.m_length ? m_currentString.getCurrentChar() : 0);
}
void SegmentedString::prepend(const SegmentedString& s)
{
ASSERT(!escaped());
ASSERT(!s.escaped());
if (s.isComposite()) {
Deque<SegmentedSubstring>::const_reverse_iterator it = s.m_substrings.rbegin();
Deque<SegmentedSubstring>::const_reverse_iterator e = s.m_substrings.rend();
for (; it != e; ++it)
prepend(*it);
}
prepend(s.m_currentString);
m_currentChar = m_currentString.m_length ? m_currentString.getCurrentChar() : 0;
}
void SegmentedString::advanceSubstring()
{
if (isComposite()) {
m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed();
m_currentString = m_substrings.takeFirst();
// If we've previously consumed some characters of the non-current
// string, we now account for those characters as part of the current
// string, not as part of "prior to current string."
m_numberOfCharactersConsumedPriorToCurrentString -= m_currentString.numberOfCharactersConsumed();
updateAdvanceFunctionPointers();
} else {
m_currentString.clear();
m_empty = true;
m_fastPathFlags = NoFastPath;
m_advanceFunc = &SegmentedString::advanceEmpty;
m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
}
}
String SegmentedString::toString() const
{
StringBuilder result;
if (m_pushedChar1) {
result.append(m_pushedChar1);
if (m_pushedChar2)
result.append(m_pushedChar2);
}
m_currentString.appendTo(result);
if (isComposite()) {
Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin();
Deque<SegmentedSubstring>::const_iterator e = m_substrings.end();
for (; it != e; ++it)
it->appendTo(result);
}
return result.toString();
}
void SegmentedString::advance(unsigned count, UChar* consumedCharacters)
{
ASSERT_WITH_SECURITY_IMPLICATION(count <= length());
for (unsigned i = 0; i < count; ++i) {
consumedCharacters[i] = currentChar();
advance();
}
}
void SegmentedString::advance8()
{
ASSERT(!m_pushedChar1);
decrementAndCheckLength();
m_currentChar = m_currentString.incrementAndGetCurrentChar8();
}
void SegmentedString::advance16()
{
ASSERT(!m_pushedChar1);
decrementAndCheckLength();
m_currentChar = m_currentString.incrementAndGetCurrentChar16();
}
void SegmentedString::advanceAndUpdateLineNumber8()
{
ASSERT(!m_pushedChar1);
ASSERT(m_currentString.getCurrentChar() == m_currentChar);
if (m_currentChar == '\n') {
++m_currentLine;
m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1;
}
decrementAndCheckLength();
m_currentChar = m_currentString.incrementAndGetCurrentChar8();
}
void SegmentedString::advanceAndUpdateLineNumber16()
{
ASSERT(!m_pushedChar1);
ASSERT(m_currentString.getCurrentChar() == m_currentChar);
if (m_currentChar == '\n') {
++m_currentLine;
m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1;
}
decrementAndCheckLength();
m_currentChar = m_currentString.incrementAndGetCurrentChar16();
}
void SegmentedString::advanceSlowCase()
{
if (m_pushedChar1) {
m_pushedChar1 = m_pushedChar2;
m_pushedChar2 = 0;
if (m_pushedChar1) {
m_currentChar = m_pushedChar1;
return;
}
updateAdvanceFunctionPointers();
} else if (m_currentString.m_length) {
if (!--m_currentString.m_length)
advanceSubstring();
} else if (!isComposite()) {
m_currentString.clear();
m_empty = true;
m_fastPathFlags = NoFastPath;
m_advanceFunc = &SegmentedString::advanceEmpty;
m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
}
m_currentChar = m_currentString.m_length ? m_currentString.getCurrentChar() : 0;
}
void SegmentedString::advanceAndUpdateLineNumberSlowCase()
{
if (m_pushedChar1) {
m_pushedChar1 = m_pushedChar2;
m_pushedChar2 = 0;
if (m_pushedChar1) {
m_currentChar = m_pushedChar1;
return;
}
updateAdvanceFunctionPointers();
} else if (m_currentString.m_length) {
if (m_currentString.getCurrentChar() == '\n' && m_currentString.doNotExcludeLineNumbers()) {
++m_currentLine;
// Plus 1 because numberOfCharactersConsumed value hasn't incremented yet; it does with m_length decrement below.
m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1;
}
if (!--m_currentString.m_length)
advanceSubstring();
else
m_currentString.incrementAndGetCurrentChar(); // Only need the ++
} else if (!isComposite()) {
m_currentString.clear();
m_empty = true;
m_fastPathFlags = NoFastPath;
m_advanceFunc = &SegmentedString::advanceEmpty;
m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
}
m_currentChar = m_currentString.m_length ? m_currentString.getCurrentChar() : 0;
}
void SegmentedString::advanceEmpty()
{
ASSERT(!m_currentString.m_length && !isComposite());
m_currentChar = 0;
}
void SegmentedString::updateSlowCaseFunctionPointers()
{
m_fastPathFlags = NoFastPath;
m_advanceFunc = &SegmentedString::advanceSlowCase;
m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceAndUpdateLineNumberSlowCase;
}
OrdinalNumber SegmentedString::currentLine() const
{
return OrdinalNumber::fromZeroBasedInt(m_currentLine);
}
OrdinalNumber SegmentedString::currentColumn() const
{
int zeroBasedColumn = numberOfCharactersConsumed() - m_numberOfCharactersConsumedPriorToCurrentLine;
return OrdinalNumber::fromZeroBasedInt(zeroBasedColumn);
}
void SegmentedString::setCurrentPosition(OrdinalNumber line, OrdinalNumber columnAftreProlog, int prologLength)
{
m_currentLine = line.zeroBasedInt();
m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + prologLength - columnAftreProlog.zeroBasedInt();
}
}
/*
Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef SKY_ENGINE_PLATFORM_TEXT_SEGMENTEDSTRING_H_
#define SKY_ENGINE_PLATFORM_TEXT_SEGMENTEDSTRING_H_
#include "flutter/sky/engine/platform/PlatformExport.h"
#include "flutter/sky/engine/wtf/Deque.h"
#include "flutter/sky/engine/wtf/text/StringBuilder.h"
#include "flutter/sky/engine/wtf/text/TextPosition.h"
#include "flutter/sky/engine/wtf/text/WTFString.h"
namespace blink {
class SegmentedString;
class PLATFORM_EXPORT SegmentedSubstring {
public:
SegmentedSubstring()
: m_length(0)
, m_doNotExcludeLineNumbers(true)
, m_is8Bit(false)
{
m_data.string16Ptr = 0;
}
SegmentedSubstring(const String& str)
: m_length(str.length())
, m_doNotExcludeLineNumbers(true)
, m_string(str)
{
if (m_length) {
if (m_string.is8Bit()) {
m_is8Bit = true;
m_data.string8Ptr = m_string.characters8();
} else {
m_is8Bit = false;
m_data.string16Ptr = m_string.characters16();
}
} else {
m_is8Bit = false;
}
}
void clear() { m_length = 0; m_data.string16Ptr = 0; m_is8Bit = false;}
bool is8Bit() { return m_is8Bit; }
bool excludeLineNumbers() const { return !m_doNotExcludeLineNumbers; }
bool doNotExcludeLineNumbers() const { return m_doNotExcludeLineNumbers; }
void setExcludeLineNumbers() { m_doNotExcludeLineNumbers = false; }
int numberOfCharactersConsumed() const { return m_string.length() - m_length; }
void appendTo(StringBuilder& builder) const
{
int offset = m_string.length() - m_length;
if (!offset) {
if (m_length)
builder.append(m_string);
} else {
builder.append(m_string.substring(offset, m_length));
}
}
UChar getCurrentChar8()
{
return *m_data.string8Ptr;
}
UChar getCurrentChar16()
{
return m_data.string16Ptr ? *m_data.string16Ptr : 0;
}
UChar incrementAndGetCurrentChar8()
{
ASSERT(m_data.string8Ptr);
return *++m_data.string8Ptr;
}
UChar incrementAndGetCurrentChar16()
{
ASSERT(m_data.string16Ptr);
return *++m_data.string16Ptr;
}
String currentSubString(unsigned length)
{
int offset = m_string.length() - m_length;
return m_string.substring(offset, length);
}
ALWAYS_INLINE UChar getCurrentChar()
{
ASSERT(m_length);
if (is8Bit())
return getCurrentChar8();
return getCurrentChar16();
}
ALWAYS_INLINE UChar incrementAndGetCurrentChar()
{
ASSERT(m_length);
if (is8Bit())
return incrementAndGetCurrentChar8();
return incrementAndGetCurrentChar16();
}
public:
union {
const LChar* string8Ptr;
const UChar* string16Ptr;
} m_data;
int m_length;
private:
bool m_doNotExcludeLineNumbers;
bool m_is8Bit;
String m_string;
};
class PLATFORM_EXPORT SegmentedString {
public:
SegmentedString()
: m_pushedChar1(0)
, m_pushedChar2(0)
, m_currentChar(0)
, m_numberOfCharactersConsumedPriorToCurrentString(0)
, m_numberOfCharactersConsumedPriorToCurrentLine(0)
, m_currentLine(0)
, m_closed(false)
, m_empty(true)
, m_fastPathFlags(NoFastPath)
, m_advanceFunc(&SegmentedString::advanceEmpty)
, m_advanceAndUpdateLineNumberFunc(&SegmentedString::advanceEmpty)
{
}
SegmentedString(const String& str)
: m_pushedChar1(0)
, m_pushedChar2(0)
, m_currentString(str)
, m_currentChar(0)
, m_numberOfCharactersConsumedPriorToCurrentString(0)
, m_numberOfCharactersConsumedPriorToCurrentLine(0)
, m_currentLine(0)
, m_closed(false)
, m_empty(!str.length())
, m_fastPathFlags(NoFastPath)
{
if (m_currentString.m_length)
m_currentChar = m_currentString.getCurrentChar();
updateAdvanceFunctionPointers();
}
void clear();
void close();
void append(const SegmentedString&);
void prepend(const SegmentedString&);
bool excludeLineNumbers() const { return m_currentString.excludeLineNumbers(); }
void setExcludeLineNumbers();
void push(UChar c)
{
if (!m_pushedChar1) {
m_pushedChar1 = c;
m_currentChar = m_pushedChar1 ? m_pushedChar1 : m_currentString.getCurrentChar();
updateSlowCaseFunctionPointers();
} else {
ASSERT(!m_pushedChar2);
m_pushedChar2 = c;
}
}
bool isEmpty() const { return m_empty; }
unsigned length() const;
bool isClosed() const { return m_closed; }
enum LookAheadResult {
DidNotMatch,
DidMatch,
NotEnoughCharacters,
};
LookAheadResult lookAhead(const String& string) { return lookAheadInline(string, true); }
LookAheadResult lookAheadIgnoringCase(const String& string) { return lookAheadInline(string, false); }
void advance()
{
if (m_fastPathFlags & Use8BitAdvance) {
ASSERT(!m_pushedChar1);
bool haveOneCharacterLeft = (--m_currentString.m_length == 1);
m_currentChar = m_currentString.incrementAndGetCurrentChar8();
if (!haveOneCharacterLeft)
return;
updateSlowCaseFunctionPointers();
return;
}
(this->*m_advanceFunc)();
}
inline void advanceAndUpdateLineNumber()
{
if (m_fastPathFlags & Use8BitAdvance) {
ASSERT(!m_pushedChar1);
bool haveNewLine = (m_currentChar == '\n') & !!(m_fastPathFlags & Use8BitAdvanceAndUpdateLineNumbers);
bool haveOneCharacterLeft = (--m_currentString.m_length == 1);
m_currentChar = m_currentString.incrementAndGetCurrentChar8();
if (!(haveNewLine | haveOneCharacterLeft))
return;
if (haveNewLine) {
++m_currentLine;
m_numberOfCharactersConsumedPriorToCurrentLine = m_numberOfCharactersConsumedPriorToCurrentString + m_currentString.numberOfCharactersConsumed();
}
if (haveOneCharacterLeft)
updateSlowCaseFunctionPointers();
return;
}
(this->*m_advanceAndUpdateLineNumberFunc)();
}
void advanceAndASSERT(UChar expectedCharacter)
{
ASSERT_UNUSED(expectedCharacter, currentChar() == expectedCharacter);
advance();
}
void advanceAndASSERTIgnoringCase(UChar expectedCharacter)
{
ASSERT_UNUSED(expectedCharacter, WTF::Unicode::foldCase(currentChar()) == WTF::Unicode::foldCase(expectedCharacter));
advance();
}
void advancePastNonNewline()
{
ASSERT(currentChar() != '\n');
advance();
}
void advancePastNewlineAndUpdateLineNumber()
{
ASSERT(currentChar() == '\n');
if (!m_pushedChar1 && m_currentString.m_length > 1) {
int newLineFlag = m_currentString.doNotExcludeLineNumbers();
m_currentLine += newLineFlag;
if (newLineFlag)
m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1;
decrementAndCheckLength();
m_currentChar = m_currentString.incrementAndGetCurrentChar();
return;
}
advanceAndUpdateLineNumberSlowCase();
}
// Writes the consumed characters into consumedCharacters, which must
// have space for at least |count| characters.
void advance(unsigned count, UChar* consumedCharacters);
bool escaped() const { return m_pushedChar1; }
int numberOfCharactersConsumed() const
{
int numberOfPushedCharacters = 0;
if (m_pushedChar1) {
++numberOfPushedCharacters;
if (m_pushedChar2)
++numberOfPushedCharacters;
}
return m_numberOfCharactersConsumedPriorToCurrentString + m_currentString.numberOfCharactersConsumed() - numberOfPushedCharacters;
}
String toString() const;
UChar currentChar() const { return m_currentChar; }
// The method is moderately slow, comparing to currentLine method.
OrdinalNumber currentColumn() const;
OrdinalNumber currentLine() const;
// Sets value of line/column variables. Column is specified indirectly by a parameter columnAftreProlog
// which is a value of column that we should get after a prolog (first prologLength characters) has been consumed.
void setCurrentPosition(OrdinalNumber line, OrdinalNumber columnAftreProlog, int prologLength);
private:
enum FastPathFlags {
NoFastPath = 0,
Use8BitAdvanceAndUpdateLineNumbers = 1 << 0,
Use8BitAdvance = 1 << 1,
};
void append(const SegmentedSubstring&);
void prepend(const SegmentedSubstring&);
void advance8();
void advance16();
void advanceAndUpdateLineNumber8();
void advanceAndUpdateLineNumber16();
void advanceSlowCase();
void advanceAndUpdateLineNumberSlowCase();
void advanceEmpty();
void advanceSubstring();
void updateSlowCaseFunctionPointers();
void decrementAndCheckLength()
{
ASSERT(m_currentString.m_length > 1);
if (--m_currentString.m_length == 1)
updateSlowCaseFunctionPointers();
}
void updateAdvanceFunctionPointers()
{
if ((m_currentString.m_length > 1) && !m_pushedChar1) {
if (m_currentString.is8Bit()) {
m_advanceFunc = &SegmentedString::advance8;
m_fastPathFlags = Use8BitAdvance;
if (m_currentString.doNotExcludeLineNumbers()) {
m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceAndUpdateLineNumber8;
m_fastPathFlags |= Use8BitAdvanceAndUpdateLineNumbers;
} else {
m_advanceAndUpdateLineNumberFunc = &SegmentedString::advance8;
}
return;
}
m_advanceFunc = &SegmentedString::advance16;
m_fastPathFlags = NoFastPath;
if (m_currentString.doNotExcludeLineNumbers())
m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceAndUpdateLineNumber16;
else
m_advanceAndUpdateLineNumberFunc = &SegmentedString::advance16;
return;
}
if (!m_currentString.m_length && !isComposite()) {
m_advanceFunc = &SegmentedString::advanceEmpty;
m_fastPathFlags = NoFastPath;
m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
}
updateSlowCaseFunctionPointers();
}
inline LookAheadResult lookAheadInline(const String& string, bool caseSensitive)
{
if (!m_pushedChar1 && string.length() <= static_cast<unsigned>(m_currentString.m_length)) {
String currentSubstring = m_currentString.currentSubString(string.length());
if (currentSubstring.startsWith(string, caseSensitive))
return DidMatch;
return DidNotMatch;
}
return lookAheadSlowCase(string, caseSensitive);
}
LookAheadResult lookAheadSlowCase(const String& string, bool caseSensitive)
{
unsigned count = string.length();
if (count > length())
return NotEnoughCharacters;
UChar* consumedCharacters;
String consumedString = String::createUninitialized(count, consumedCharacters);
advance(count, consumedCharacters);
LookAheadResult result = DidNotMatch;
if (consumedString.startsWith(string, caseSensitive))
result = DidMatch;
prepend(SegmentedString(consumedString));
return result;
}
bool isComposite() const { return !m_substrings.isEmpty(); }
UChar m_pushedChar1;
UChar m_pushedChar2;
SegmentedSubstring m_currentString;
UChar m_currentChar;
int m_numberOfCharactersConsumedPriorToCurrentString;
int m_numberOfCharactersConsumedPriorToCurrentLine;
int m_currentLine;
Deque<SegmentedSubstring> m_substrings;
bool m_closed;
bool m_empty;
unsigned char m_fastPathFlags;
void (SegmentedString::*m_advanceFunc)();
void (SegmentedString::*m_advanceAndUpdateLineNumberFunc)();
};
}
#endif // SKY_ENGINE_PLATFORM_TEXT_SEGMENTEDSTRING_H_
/*
* Copyright (C) 2014 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "flutter/sky/engine/platform/text/SegmentedString.h"
#include <gtest/gtest.h>
using blink::SegmentedString;
namespace {
TEST(SegmentedStringTest, CurrentChar)
{
SegmentedString original(String("cde"));
{
SegmentedString copied(original);
SegmentedString assigned;
assigned = original;
EXPECT_EQ("cde", original.toString());
EXPECT_EQ('c', original.currentChar());
EXPECT_EQ('c', copied.currentChar());
EXPECT_EQ('c', assigned.currentChar());
}
original.push('a');
{
SegmentedString copied(original);
SegmentedString assigned;
assigned = original;
EXPECT_EQ("acde", original.toString());
EXPECT_EQ('a', original.currentChar());
EXPECT_EQ('a', copied.currentChar());
EXPECT_EQ('a', assigned.currentChar());
}
original.push('b');
{
// Two consecutive push means to push the second char *after* the
// first char in SegmentedString.
SegmentedString copied(original);
SegmentedString assigned;
assigned = original;
EXPECT_EQ("abcde", original.toString());
EXPECT_EQ('a', original.currentChar());
EXPECT_EQ('a', copied.currentChar());
EXPECT_EQ('a', assigned.currentChar());
}
original.advance();
{
SegmentedString copied(original);
SegmentedString assigned;
assigned = original;
EXPECT_EQ("bcde", original.toString());
EXPECT_EQ('b', original.currentChar());
EXPECT_EQ('b', copied.currentChar());
EXPECT_EQ('b', assigned.currentChar());
}
}
} // namespace
/*
* Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "flutter/sky/engine/platform/text/StringTruncator.h"
#include "flutter/sky/engine/platform/fonts/Font.h"
#include "flutter/sky/engine/platform/text/TextBreakIterator.h"
#include "flutter/sky/engine/platform/text/TextRun.h"
#include "flutter/sky/engine/wtf/Assertions.h"
#include "flutter/sky/engine/wtf/unicode/CharacterNames.h"
namespace blink {
#define STRING_BUFFER_SIZE 2048
typedef unsigned TruncationFunction(const String&, unsigned length, unsigned keepCount, UChar* buffer);
static inline int textBreakAtOrPreceding(const NonSharedCharacterBreakIterator& it, int offset)
{
if (it.isBreak(offset))
return offset;
int result = it.preceding(offset);
return result == TextBreakDone ? 0 : result;
}
static inline int boundedTextBreakFollowing(const NonSharedCharacterBreakIterator& it, int offset, int length)
{
int result = it.following(offset);
return result == TextBreakDone ? length : result;
}
static unsigned centerTruncateToBuffer(const String& string, unsigned length, unsigned keepCount, UChar* buffer)
{
ASSERT(keepCount < length);
ASSERT(keepCount < STRING_BUFFER_SIZE);
unsigned omitStart = (keepCount + 1) / 2;
NonSharedCharacterBreakIterator it(string);
unsigned omitEnd = boundedTextBreakFollowing(it, omitStart + (length - keepCount) - 1, length);
omitStart = textBreakAtOrPreceding(it, omitStart);
unsigned truncatedLength = omitStart + 1 + (length - omitEnd);
ASSERT(truncatedLength <= length);
string.copyTo(buffer, 0, omitStart);
buffer[omitStart] = horizontalEllipsis;
string.copyTo(&buffer[omitStart + 1], omitEnd, length - omitEnd);
return truncatedLength;
}
static unsigned rightTruncateToBuffer(const String& string, unsigned length, unsigned keepCount, UChar* buffer)
{
ASSERT(keepCount < length);
ASSERT(keepCount < STRING_BUFFER_SIZE);
NonSharedCharacterBreakIterator it(string);
unsigned keepLength = textBreakAtOrPreceding(it, keepCount);
unsigned truncatedLength = keepLength + 1;
string.copyTo(buffer, 0, keepLength);
buffer[keepLength] = horizontalEllipsis;
return truncatedLength;
}
static float stringWidth(const Font& renderer, const String& string)
{
TextRun run(string);
return renderer.width(run);
}
static float stringWidth(const Font& renderer, const UChar* characters, unsigned length)
{
TextRun run(characters, length);
return renderer.width(run);
}
static String truncateString(const String& string, float maxWidth, const Font& font, TruncationFunction truncateToBuffer)
{
if (string.isEmpty())
return string;
ASSERT(maxWidth >= 0);
float currentEllipsisWidth = stringWidth(font, &horizontalEllipsis, 1);
UChar stringBuffer[STRING_BUFFER_SIZE];
unsigned truncatedLength;
unsigned keepCount;
unsigned length = string.length();
if (length > STRING_BUFFER_SIZE) {
keepCount = STRING_BUFFER_SIZE - 1; // need 1 character for the ellipsis
truncatedLength = centerTruncateToBuffer(string, length, keepCount, stringBuffer);
} else {
keepCount = length;
string.copyTo(stringBuffer, 0, length);
truncatedLength = length;
}
float width = stringWidth(font, stringBuffer, truncatedLength);
if (width <= maxWidth)
return string;
unsigned keepCountForLargestKnownToFit = 0;
float widthForLargestKnownToFit = currentEllipsisWidth;
unsigned keepCountForSmallestKnownToNotFit = keepCount;
float widthForSmallestKnownToNotFit = width;
if (currentEllipsisWidth >= maxWidth) {
keepCountForLargestKnownToFit = 1;
keepCountForSmallestKnownToNotFit = 2;
}
while (keepCountForLargestKnownToFit + 1 < keepCountForSmallestKnownToNotFit) {
ASSERT(widthForLargestKnownToFit <= maxWidth);
ASSERT(widthForSmallestKnownToNotFit > maxWidth);
float ratio = (keepCountForSmallestKnownToNotFit - keepCountForLargestKnownToFit)
/ (widthForSmallestKnownToNotFit - widthForLargestKnownToFit);
keepCount = static_cast<unsigned>(maxWidth * ratio);
if (keepCount <= keepCountForLargestKnownToFit) {
keepCount = keepCountForLargestKnownToFit + 1;
} else if (keepCount >= keepCountForSmallestKnownToNotFit) {
keepCount = keepCountForSmallestKnownToNotFit - 1;
}
ASSERT(keepCount < length);
ASSERT(keepCount > 0);
ASSERT(keepCount < keepCountForSmallestKnownToNotFit);
ASSERT(keepCount > keepCountForLargestKnownToFit);
truncatedLength = truncateToBuffer(string, length, keepCount, stringBuffer);
width = stringWidth(font, stringBuffer, truncatedLength);
if (width <= maxWidth) {
keepCountForLargestKnownToFit = keepCount;
widthForLargestKnownToFit = width;
} else {
keepCountForSmallestKnownToNotFit = keepCount;
widthForSmallestKnownToNotFit = width;
}
}
if (!keepCountForLargestKnownToFit)
keepCountForLargestKnownToFit = 1;
if (keepCount != keepCountForLargestKnownToFit) {
keepCount = keepCountForLargestKnownToFit;
truncatedLength = truncateToBuffer(string, length, keepCount, stringBuffer);
}
return String(stringBuffer, truncatedLength);
}
String StringTruncator::centerTruncate(const String& string, float maxWidth, const Font& font)
{
return truncateString(string, maxWidth, font, centerTruncateToBuffer);
}
String StringTruncator::rightTruncate(const String& string, float maxWidth, const Font& font)
{
return truncateString(string, maxWidth, font, rightTruncateToBuffer);
}
float StringTruncator::width(const String& string, const Font& font)
{
return stringWidth(font, string);
}
} // namespace blink
/*
* Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SKY_ENGINE_PLATFORM_TEXT_STRINGTRUNCATOR_H_
#define SKY_ENGINE_PLATFORM_TEXT_STRINGTRUNCATOR_H_
#include "flutter/sky/engine/platform/PlatformExport.h"
#include "flutter/sky/engine/wtf/Forward.h"
namespace blink {
class Font;
class PLATFORM_EXPORT StringTruncator {
public:
static String centerTruncate(const String&, float maxWidth, const Font&);
static String rightTruncate(const String&, float maxWidth, const Font&);
static float width(const String&, const Font&);
};
} // namespace blink
#endif // SKY_ENGINE_PLATFORM_TEXT_STRINGTRUNCATOR_H_
/*
* Copyright (C) 2010 Adam Barth. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SKY_ENGINE_PLATFORM_TEXT_SUFFIXTREE_H_
#define SKY_ENGINE_PLATFORM_TEXT_SUFFIXTREE_H_
#include "flutter/sky/engine/wtf/Vector.h"
#include "flutter/sky/engine/wtf/text/WTFString.h"
namespace blink {
class UnicodeCodebook {
public:
static int codeWord(UChar c) { return c; }
enum { codeSize = 1 << 8 * sizeof(UChar) };
};
class ASCIICodebook {
public:
static int codeWord(UChar c) { return c & (codeSize - 1); }
enum { codeSize = 1 << (8 * sizeof(char) - 1) };
};
template<typename Codebook>
class SuffixTree {
public:
SuffixTree(const String& text, unsigned depth)
: m_depth(depth)
, m_leaf(true)
{
build(text);
}
bool mightContain(const String& query)
{
Node* current = &m_root;
int limit = std::min(m_depth, query.length());
for (int i = 0; i < limit; ++i) {
current = current->at(Codebook::codeWord(query[i]));
if (!current)
return false;
}
return true;
}
private:
class Node {
public:
Node(bool isLeaf = false)
{
m_children.resize(Codebook::codeSize);
m_children.fill(0);
m_isLeaf = isLeaf;
}
~Node()
{
for (unsigned i = 0; i < m_children.size(); ++i) {
Node* child = m_children.at(i);
if (child && !child->m_isLeaf)
delete child;
}
}
Node*& at(int codeWord) { return m_children.at(codeWord); }
private:
typedef Vector<Node*, Codebook::codeSize> ChildrenVector;
ChildrenVector m_children;
bool m_isLeaf;
};
void build(const String& text)
{
for (unsigned base = 0; base < text.length(); ++base) {
Node* current = &m_root;
unsigned limit = std::min(base + m_depth, text.length());
for (unsigned offset = 0; base + offset < limit; ++offset) {
ASSERT(current != &m_leaf);
Node*& child = current->at(Codebook::codeWord(text[base + offset]));
if (!child)
child = base + offset + 1 == limit ? &m_leaf : new Node();
current = child;
}
}
}
Node m_root;
unsigned m_depth;
// Instead of allocating a fresh empty leaf node for ever leaf in the tree
// (there can be a lot of these), we alias all the leaves to this "static"
// leaf node.
Node m_leaf;
};
} // namespace blink
#endif // SKY_ENGINE_PLATFORM_TEXT_SUFFIXTREE_H_
/*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
* Copyright (C) 2010 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SKY_ENGINE_PLATFORM_TEXT_TEXTCHECKERCLIENT_H_
#define SKY_ENGINE_PLATFORM_TEXT_TEXTCHECKERCLIENT_H_
#include "flutter/sky/engine/platform/text/TextChecking.h"
#include "flutter/sky/engine/wtf/Forward.h"
#include "flutter/sky/engine/wtf/PassRefPtr.h"
#include "flutter/sky/engine/wtf/Vector.h"
#include "flutter/sky/engine/wtf/text/WTFString.h"
namespace blink {
class TextCheckerClient {
public:
virtual ~TextCheckerClient() { }
virtual bool shouldEraseMarkersAfterChangeSelection(TextCheckingType) const = 0;
virtual void checkSpellingOfString(const String&, int* misspellingLocation, int* misspellingLength) = 0;
virtual String getAutoCorrectSuggestionForMisspelledWord(const String& misspelledWord) = 0;
virtual void checkGrammarOfString(const String&, Vector<GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength) = 0;
virtual void requestCheckingOfString(PassRefPtr<TextCheckingRequest>) = 0;
};
}
#endif // SKY_ENGINE_PLATFORM_TEXT_TEXTCHECKERCLIENT_H_
/*
* Copyright (c) 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SKY_ENGINE_PLATFORM_TEXT_TEXTCHECKING_H_
#define SKY_ENGINE_PLATFORM_TEXT_TEXTCHECKING_H_
#include "flutter/sky/engine/platform/text/TextDecoration.h"
#include "flutter/sky/engine/wtf/RefCounted.h"
#include "flutter/sky/engine/wtf/Vector.h"
#include "flutter/sky/engine/wtf/text/WTFString.h"
namespace blink {
enum TextCheckingType {
TextCheckingTypeNone = 0,
TextCheckingTypeSpelling = 1 << 1,
TextCheckingTypeGrammar = 1 << 2,
};
typedef unsigned TextCheckingTypeMask;
enum TextCheckingProcessType {
TextCheckingProcessBatch,
TextCheckingProcessIncremental
};
struct GrammarDetail {
int location;
int length;
Vector<String> guesses;
String userDescription;
};
struct TextCheckingResult {
TextDecorationType decoration;
int location;
int length;
Vector<GrammarDetail> details;
String replacement;
uint32_t hash;
};
const int unrequestedTextCheckingSequence = -1;
class TextCheckingRequestData {
friend class SpellCheckRequest; // For access to m_sequence.
public:
TextCheckingRequestData()
: m_sequence(unrequestedTextCheckingSequence)
, m_mask(TextCheckingTypeNone)
, m_processType(TextCheckingProcessIncremental)
{ }
TextCheckingRequestData(int sequence, const String& text, TextCheckingTypeMask mask, TextCheckingProcessType processType, const Vector<uint32_t>& markers, const Vector<unsigned>& offsets)
: m_sequence(sequence)
, m_text(text)
, m_mask(mask)
, m_processType(processType)
, m_markers(markers)
, m_offsets(offsets)
{ }
int sequence() const { return m_sequence; }
String text() const { return m_text; }
TextCheckingTypeMask mask() const { return m_mask; }
bool maskContains(TextCheckingType type) const { return m_mask & type; }
TextCheckingProcessType processType() const { return m_processType; }
const Vector<uint32_t>& markers() const { return m_markers; }
const Vector<unsigned>& offsets() const { return m_offsets; }
private:
int m_sequence;
String m_text;
TextCheckingTypeMask m_mask;
TextCheckingProcessType m_processType;
Vector<uint32_t> m_markers;
Vector<unsigned> m_offsets;
};
class TextCheckingRequest : public RefCounted<TextCheckingRequest> {
public:
virtual ~TextCheckingRequest() { }
virtual const TextCheckingRequestData& data() const = 0;
virtual void didSucceed(const Vector<TextCheckingResult>&) = 0;
virtual void didCancel() = 0;
};
}
#endif // SKY_ENGINE_PLATFORM_TEXT_TEXTCHECKING_H_
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册