Show Pages in chrome://md-settings
[chromium-blink-merge.git] / net / websockets / websocket_extension_parser.cc
blob28a2db16f2775e3410a47e35d51ea12792f63682
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"
9 namespace net {
11 WebSocketExtensionParser::WebSocketExtensionParser() {}
13 WebSocketExtensionParser::~WebSocketExtensionParser() {}
15 void WebSocketExtensionParser::Parse(const char* data, size_t size) {
16 current_ = data;
17 end_ = data + size;
18 has_error_ = false;
20 ConsumeExtension(&extension_);
21 if (has_error_) return;
22 ConsumeSpaces();
23 has_error_ = has_error_ || (current_ != end_);
26 void WebSocketExtensionParser::Consume(char c) {
27 DCHECK(!has_error_);
28 ConsumeSpaces();
29 DCHECK(!has_error_);
30 if (current_ == end_ || c != current_[0]) {
31 has_error_ = true;
32 return;
34 ++current_;
37 void WebSocketExtensionParser::ConsumeExtension(WebSocketExtension* extension) {
38 DCHECK(!has_error_);
39 base::StringPiece name;
40 ConsumeToken(&name);
41 if (has_error_) return;
42 *extension = WebSocketExtension(name.as_string());
44 while (ConsumeIfMatch(';')) {
45 WebSocketExtension::Parameter parameter((std::string()));
46 ConsumeExtensionParameter(&parameter);
47 if (has_error_) return;
48 extension->Add(parameter);
52 void WebSocketExtensionParser::ConsumeExtensionParameter(
53 WebSocketExtension::Parameter* parameter) {
54 DCHECK(!has_error_);
55 base::StringPiece name, value;
56 std::string value_string;
58 ConsumeToken(&name);
59 if (has_error_) return;
60 if (!ConsumeIfMatch('=')) {
61 *parameter = WebSocketExtension::Parameter(name.as_string());
62 return;
65 if (Lookahead('\"')) {
66 ConsumeQuotedToken(&value_string);
67 } else {
68 ConsumeToken(&value);
69 value_string = value.as_string();
71 if (has_error_) return;
72 *parameter = WebSocketExtension::Parameter(name.as_string(), value_string);
75 void WebSocketExtensionParser::ConsumeToken(base::StringPiece* token) {
76 DCHECK(!has_error_);
77 ConsumeSpaces();
78 DCHECK(!has_error_);
79 const char* head = current_;
80 while (current_ < end_ &&
81 !IsControl(current_[0]) && !IsSeparator(current_[0]))
82 ++current_;
83 if (current_ == head) {
84 has_error_ = true;
85 return;
87 *token = base::StringPiece(head, current_ - head);
90 void WebSocketExtensionParser::ConsumeQuotedToken(std::string* token) {
91 DCHECK(!has_error_);
92 Consume('"');
93 if (has_error_) return;
94 *token = "";
95 while (current_ < end_ && !IsControl(current_[0])) {
96 if (UnconsumedBytes() >= 2 && current_[0] == '\\') {
97 char next = current_[1];
98 if (IsControl(next) || IsSeparator(next)) break;
99 *token += next;
100 current_ += 2;
101 } else if (IsSeparator(current_[0])) {
102 break;
103 } else {
104 *token += current_[0];
105 ++current_;
108 // We can't use Consume here because we don't want to consume spaces.
109 if (current_ < end_ && current_[0] == '"')
110 ++current_;
111 else
112 has_error_ = true;
113 has_error_ = has_error_ || token->empty();
116 void WebSocketExtensionParser::ConsumeSpaces() {
117 DCHECK(!has_error_);
118 while (current_ < end_ && (current_[0] == ' ' || current_[0] == '\t'))
119 ++current_;
120 return;
123 bool WebSocketExtensionParser::Lookahead(char c) {
124 DCHECK(!has_error_);
125 const char* head = current_;
127 Consume(c);
128 bool result = !has_error_;
129 current_ = head;
130 has_error_ = false;
131 return result;
134 bool WebSocketExtensionParser::ConsumeIfMatch(char c) {
135 DCHECK(!has_error_);
136 const char* head = current_;
138 Consume(c);
139 if (has_error_) {
140 current_ = head;
141 has_error_ = false;
142 return false;
144 return true;
147 // static
148 bool WebSocketExtensionParser::IsControl(char c) {
149 return (0 <= c && c <= 31) || c == 127;
152 // static
153 bool WebSocketExtensionParser::IsSeparator(char c) {
154 const char separators[] = "()<>@,;:\\\"/[]?={} \t";
155 return strchr(separators, c) != NULL;
158 } // namespace net