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 bool WebSocketExtensionParser::Parse(const char* data
, size_t size
) {
23 WebSocketExtension extension
;
24 if (!ConsumeExtension(&extension
)) {
28 extensions_
.push_back(extension
);
32 if (!ConsumeIfMatch(',')) {
37 if (!failed
&& current_
== end_
)
44 bool WebSocketExtensionParser::Consume(char c
) {
46 if (current_
== end_
|| c
!= current_
[0]) {
53 bool WebSocketExtensionParser::ConsumeExtension(WebSocketExtension
* extension
) {
54 base::StringPiece name
;
55 if (!ConsumeToken(&name
))
57 *extension
= WebSocketExtension(name
.as_string());
59 while (ConsumeIfMatch(';')) {
60 WebSocketExtension::Parameter
parameter((std::string()));
61 if (!ConsumeExtensionParameter(¶meter
))
63 extension
->Add(parameter
);
69 bool WebSocketExtensionParser::ConsumeExtensionParameter(
70 WebSocketExtension::Parameter
* parameter
) {
71 base::StringPiece name
, value
;
72 std::string value_string
;
74 if (!ConsumeToken(&name
))
77 if (!ConsumeIfMatch('=')) {
78 *parameter
= WebSocketExtension::Parameter(name
.as_string());
82 if (Lookahead('\"')) {
83 if (!ConsumeQuotedToken(&value_string
))
86 if (!ConsumeToken(&value
))
88 value_string
= value
.as_string();
90 *parameter
= WebSocketExtension::Parameter(name
.as_string(), value_string
);
94 bool WebSocketExtensionParser::ConsumeToken(base::StringPiece
* token
) {
96 const char* head
= current_
;
97 while (current_
< end_
&&
98 !IsControl(current_
[0]) && !IsSeparator(current_
[0]))
100 if (current_
== head
) {
103 *token
= base::StringPiece(head
, current_
- head
);
107 bool WebSocketExtensionParser::ConsumeQuotedToken(std::string
* token
) {
112 while (current_
< end_
&& !IsControl(current_
[0])) {
113 if (UnconsumedBytes() >= 2 && current_
[0] == '\\') {
114 char next
= current_
[1];
115 if (IsControl(next
) || IsSeparator(next
)) break;
118 } else if (IsSeparator(current_
[0])) {
121 *token
+= current_
[0];
125 // We can't use Consume here because we don't want to consume spaces.
126 if (current_
>= end_
|| current_
[0] != '"')
131 return !token
->empty();
134 void WebSocketExtensionParser::ConsumeSpaces() {
135 while (current_
< end_
&& (current_
[0] == ' ' || current_
[0] == '\t'))
140 bool WebSocketExtensionParser::Lookahead(char c
) {
141 const char* head
= current_
;
142 bool result
= Consume(c
);
147 bool WebSocketExtensionParser::ConsumeIfMatch(char c
) {
148 const char* head
= current_
;
158 bool WebSocketExtensionParser::IsControl(char c
) {
159 return (0 <= c
&& c
<= 31) || c
== 127;
163 bool WebSocketExtensionParser::IsSeparator(char c
) {
164 const char separators
[] = "()<>@,;:\\\"/[]?={} \t";
165 return strchr(separators
, c
) != NULL
;