1/*
2 * Copyright 2017 The Chromium Authors. All rights reserved.
3 * Copyright (C) 2018 Akamai Technologies Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "HeaderFieldTokenizer.h"
29
30#include "HTTPHeaderField.h"
31#include <wtf/text/StringBuilder.h>
32
33namespace WebCore {
34
35HeaderFieldTokenizer::HeaderFieldTokenizer(const String& headerField)
36 : m_input(headerField)
37{
38 skipSpaces();
39}
40
41bool HeaderFieldTokenizer::consume(UChar c)
42{
43 ASSERT(c != ' ' && c != '\t');
44
45 if (isConsumed() || m_input[m_index] != c)
46 return false;
47
48 ++m_index;
49 skipSpaces();
50 return true;
51}
52
53String HeaderFieldTokenizer::consumeQuotedString()
54{
55 StringBuilder builder;
56
57 ASSERT(m_input[m_index] == '"');
58 ++m_index;
59
60 while (!isConsumed()) {
61 if (m_input[m_index] == '"') {
62 String output = builder.toString();
63 ++m_index;
64 skipSpaces();
65 return output;
66 }
67 if (m_input[m_index] == '\\') {
68 ++m_index;
69 if (isConsumed())
70 return String();
71 }
72 builder.append(m_input[m_index]);
73 ++m_index;
74 }
75 return String();
76}
77
78String HeaderFieldTokenizer::consumeToken()
79{
80 auto start = m_index;
81 while (!isConsumed() && RFC7230::isTokenCharacter(m_input[m_index]))
82 ++m_index;
83
84 if (start == m_index)
85 return String();
86
87 String output = m_input.substring(start, m_index - start);
88 skipSpaces();
89 return output;
90}
91
92String HeaderFieldTokenizer::consumeTokenOrQuotedString()
93{
94 if (isConsumed())
95 return String();
96
97 if (m_input[m_index] == '"')
98 return consumeQuotedString();
99
100 return consumeToken();
101}
102
103void HeaderFieldTokenizer::skipSpaces()
104{
105 while (!isConsumed() && RFC7230::isWhitespace(m_input[m_index]))
106 ++m_index;
107}
108
109void HeaderFieldTokenizer::consumeBeforeAnyCharMatch(const Vector<UChar>& chars)
110{
111 ASSERT(chars.size() > 0U && chars.size() < 3U);
112
113 while (!isConsumed()) {
114 for (const auto& c : chars) {
115 if (c == m_input[m_index])
116 return;
117 }
118
119 ++m_index;
120 }
121}
122
123} // namespace WebCore
124