blob: 1303dce39753dcff6bff85e84563df3593f162c6 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "public/platform/WebIconSizesParser.h"
#include "public/platform/WebSize.h"
#include "public/platform/WebString.h"
#include "wtf/text/StringToNumber.h"
#include "wtf/text/WTFString.h"
#include <algorithm>
namespace blink {
namespace {
static inline bool isIntegerStart(UChar c) {
return c > '0' && c <= '9';
}
static bool isWhitespace(UChar c) {
// Sizes space characters are U+0020 SPACE, U+0009 CHARACTER TABULATION (tab),
// U+000A LINE FEED (LF), U+000C FORM FEED (FF),
// and U+000D CARRIAGE RETURN (CR).
return c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r';
}
static bool isNotWhitespace(UChar c) {
return !isWhitespace(c);
}
static bool isNonDigit(UChar c) {
return !isASCIIDigit(c);
}
static inline size_t findEndOfWord(const String& string, size_t start) {
return std::min(string.find(isWhitespace, start),
static_cast<size_t>(string.length()));
}
static inline int partialStringToInt(const String& string,
size_t start,
size_t end) {
if (string.is8Bit())
return charactersToInt(string.characters8() + start, end - start);
return charactersToInt(string.characters16() + start, end - start);
}
} // namespace
WebVector<WebSize> WebIconSizesParser::parseIconSizes(
const WebString& webSizesString) {
String sizesString = webSizesString;
Vector<WebSize> iconSizes;
if (sizesString.isEmpty())
return iconSizes;
unsigned length = sizesString.length();
for (unsigned i = 0; i < length; ++i) {
// Skip whitespaces.
i = std::min(sizesString.find(isNotWhitespace, i),
static_cast<size_t>(length));
if (i >= length)
break;
// See if the current size is "any".
if (sizesString.findIgnoringCase("any", i) == i &&
(i + 3 == length || isWhitespace(sizesString[i + 3]))) {
iconSizes.append(WebSize(0, 0));
i = i + 3;
continue;
}
// Parse the width.
if (!isIntegerStart(sizesString[i])) {
i = findEndOfWord(sizesString, i);
continue;
}
unsigned widthStart = i;
i = std::min(sizesString.find(isNonDigit, i), static_cast<size_t>(length));
if (i >= length || (sizesString[i] != 'x' && sizesString[i] != 'X')) {
i = findEndOfWord(sizesString, i);
continue;
}
unsigned widthEnd = i++;
// Parse the height.
if (i >= length || !isIntegerStart(sizesString[i])) {
i = findEndOfWord(sizesString, i);
continue;
}
unsigned heightStart = i;
i = std::min(sizesString.find(isNonDigit, i), static_cast<size_t>(length));
if (i < length && !isWhitespace(sizesString[i])) {
i = findEndOfWord(sizesString, i);
continue;
}
unsigned heightEnd = i;
// Append the parsed size to iconSizes.
iconSizes.append(
WebSize(partialStringToInt(sizesString, widthStart, widthEnd),
partialStringToInt(sizesString, heightStart, heightEnd)));
}
return iconSizes;
}
} // namespace blink