summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/web_icon_sizes_parser.cc
blob: 9784162d598e63032a39fa7aa7a8bdd682802822 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// 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 "third_party/blink/public/platform/web_icon_sizes_parser.h"

#include <algorithm>
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/renderer/platform/wtf/text/string_to_number.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"

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,
                           WTF::NumberParsingOptions::kNone, nullptr);
  }
  return CharactersToInt(string.Characters16() + start, end - start,
                         WTF::NumberParsingOptions::kNone, nullptr);
}

}  // namespace

WebVector<WebSize> WebIconSizesParser::ParseIconSizes(
    const WebString& web_sizes_string) {
  String sizes_string = web_sizes_string;
  Vector<WebSize> icon_sizes;
  if (sizes_string.IsEmpty())
    return icon_sizes;

  unsigned length = sizes_string.length();
  for (unsigned i = 0; i < length; ++i) {
    // Skip whitespaces.
    i = std::min(sizes_string.Find(IsNotWhitespace, i),
                 static_cast<size_t>(length));
    if (i >= length)
      break;

    // See if the current size is "any".
    if (sizes_string.FindIgnoringCase("any", i) == i &&
        (i + 3 == length || IsWhitespace(sizes_string[i + 3]))) {
      icon_sizes.push_back(WebSize(0, 0));
      i = i + 3;
      continue;
    }

    // Parse the width.
    if (!IsIntegerStart(sizes_string[i])) {
      i = FindEndOfWord(sizes_string, i);
      continue;
    }
    unsigned width_start = i;
    i = std::min(sizes_string.Find(IsNonDigit, i), static_cast<size_t>(length));
    if (i >= length || (sizes_string[i] != 'x' && sizes_string[i] != 'X')) {
      i = FindEndOfWord(sizes_string, i);
      continue;
    }
    unsigned width_end = i++;

    // Parse the height.
    if (i >= length || !IsIntegerStart(sizes_string[i])) {
      i = FindEndOfWord(sizes_string, i);
      continue;
    }
    unsigned height_start = i;
    i = std::min(sizes_string.Find(IsNonDigit, i), static_cast<size_t>(length));
    if (i < length && !IsWhitespace(sizes_string[i])) {
      i = FindEndOfWord(sizes_string, i);
      continue;
    }
    unsigned height_end = i;

    // Append the parsed size to iconSizes.
    icon_sizes.push_back(
        WebSize(PartialStringToInt(sizes_string, width_start, width_end),
                PartialStringToInt(sizes_string, height_start, height_end)));
  }
  return icon_sizes;
}

}  // namespace blink