1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/websockets/websocket_extension_parser.h"
7 #include "base/strings/string_util.h"
11 WebSocketExtensionParser::WebSocketExtensionParser() {}
13 WebSocketExtensionParser::~WebSocketExtensionParser() {}
15 void WebSocketExtensionParser::Parse(const char* data
, size_t size
) {
22 WebSocketExtension extension
;
23 ConsumeExtension(&extension
);
26 extensions_
.push_back(extension
);
31 if (!ConsumeIfMatch(',')) {
36 has_error_
= has_error_
|| current_
!= end_
;
41 void WebSocketExtensionParser::Consume(char c
) {
45 if (current_
== end_
|| c
!= current_
[0]) {
52 void WebSocketExtensionParser::ConsumeExtension(WebSocketExtension
* extension
) {
54 base::StringPiece name
;
56 if (has_error_
) return;
57 *extension
= WebSocketExtension(name
.as_string());
59 while (ConsumeIfMatch(';')) {
60 WebSocketExtension::Parameter
parameter((std::string()));
61 ConsumeExtensionParameter(¶meter
);
62 if (has_error_
) return;
63 extension
->Add(parameter
);
67 void WebSocketExtensionParser::ConsumeExtensionParameter(
68 WebSocketExtension::Parameter
* parameter
) {
70 base::StringPiece name
, value
;
71 std::string value_string
;
74 if (has_error_
) return;
75 if (!ConsumeIfMatch('=')) {
76 *parameter
= WebSocketExtension::Parameter(name
.as_string());
80 if (Lookahead('\"')) {
81 ConsumeQuotedToken(&value_string
);
84 value_string
= value
.as_string();
86 if (has_error_
) return;
87 *parameter
= WebSocketExtension::Parameter(name
.as_string(), value_string
);
90 void WebSocketExtensionParser::ConsumeToken(base::StringPiece
* token
) {
94 const char* head
= current_
;
95 while (current_
< end_
&&
96 !IsControl(current_
[0]) && !IsSeparator(current_
[0]))
98 if (current_
== head
) {
102 *token
= base::StringPiece(head
, current_
- head
);
105 void WebSocketExtensionParser::ConsumeQuotedToken(std::string
* token
) {
108 if (has_error_
) return;
110 while (current_
< end_
&& !IsControl(current_
[0])) {
111 if (UnconsumedBytes() >= 2 && current_
[0] == '\\') {
112 char next
= current_
[1];
113 if (IsControl(next
) || IsSeparator(next
)) break;
116 } else if (IsSeparator(current_
[0])) {
119 *token
+= current_
[0];
123 // We can't use Consume here because we don't want to consume spaces.
124 if (current_
< end_
&& current_
[0] == '"')
128 has_error_
= has_error_
|| token
->empty();
131 void WebSocketExtensionParser::ConsumeSpaces() {
133 while (current_
< end_
&& (current_
[0] == ' ' || current_
[0] == '\t'))
138 bool WebSocketExtensionParser::Lookahead(char c
) {
140 const char* head
= current_
;
143 bool result
= !has_error_
;
149 bool WebSocketExtensionParser::ConsumeIfMatch(char c
) {
151 const char* head
= current_
;
163 bool WebSocketExtensionParser::IsControl(char c
) {
164 return (0 <= c
&& c
<= 31) || c
== 127;
168 bool WebSocketExtensionParser::IsSeparator(char c
) {
169 const char separators
[] = "()<>@,;:\\\"/[]?={} \t";
170 return strchr(separators
, c
) != NULL
;