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/tools/balsa/balsa_headers_token_utils.h"
9 inline void BalsaHeadersTokenUtils::TokenizeHeaderLine(
10 const BalsaHeaders
& headers
,
11 const BalsaHeaders::HeaderLineDescription
& header_line
,
12 BalsaHeaders::HeaderTokenList
* tokens
) {
15 // Find where this line is stored
16 const char* stream_begin
= headers
.GetPtr(header_line
.buffer_base_idx
);
18 // Determine the boundaries of the value
19 const char* value_begin
= stream_begin
+ header_line
.value_begin_idx
;
20 const char* line_end
= stream_begin
+ header_line
.last_char_idx
;
23 ParseTokenList(value_begin
, line_end
, tokens
);
26 void BalsaHeadersTokenUtils::RemoveLastTokenFromHeaderValue(
27 const base::StringPiece
& key
, BalsaHeaders
* headers
) {
28 BalsaHeaders::HeaderLines::iterator it
=
29 headers
->GetHeaderLinesIterator(key
, headers
->header_lines_
.begin());
30 if (it
== headers
->header_lines_
.end()) {
31 DLOG(WARNING
) << "Attempting to remove last token from a non-existent "
32 << "header \"" << key
<< "\"";
36 // Find the last line with that key.
37 BalsaHeaders::HeaderLines::iterator header_line
;
40 it
= headers
->GetHeaderLinesIterator(key
, it
+ 1);
42 while (it
!= headers
->header_lines_
.end());
44 // Tokenize just that line.
45 BalsaHeaders::HeaderTokenList tokens
;
46 TokenizeHeaderLine(*headers
, *header_line
, &tokens
);
49 DLOG(WARNING
) << "Attempting to remove a token from an empty header value "
50 << "for header \"" << key
<< "\"";
51 header_line
->skip
= true; // remove the whole line
52 } else if (tokens
.size() == 1) {
53 header_line
->skip
= true; // remove the whole line
55 // Shrink the line size and leave the extra data in the buffer.
56 const base::StringPiece
& new_last_token
= tokens
[tokens
.size() - 2];
57 const char* last_char_address
=
58 new_last_token
.data() + new_last_token
.size() - 1;
59 const char* stream_begin
= headers
->GetPtr(header_line
->buffer_base_idx
);
61 header_line
->last_char_idx
= last_char_address
- stream_begin
+ 1;
65 bool BalsaHeadersTokenUtils::CheckHeaderForLastToken(
66 const BalsaHeaders
& headers
,
67 const base::StringPiece
& key
,
68 const base::StringPiece
& token
) {
69 BalsaHeaders::const_header_lines_key_iterator it
=
70 headers
.GetIteratorForKey(key
);
71 if (it
== headers
.header_lines_key_end())
75 BalsaHeaders::const_header_lines_key_iterator header_line
= it
;
80 while (it
!= headers
.header_lines_key_end());
82 // Tokenize just that line
83 BalsaHeaders::HeaderTokenList tokens
;
84 ParseTokenList(header_line
->second
.begin(), header_line
->second
.end(),
87 return !tokens
.empty() &&
88 base::StartsWith(tokens
.back(), token
,
89 base::CompareCase::INSENSITIVE_ASCII
);
92 void BalsaHeadersTokenUtils::TokenizeHeaderValue(
93 const BalsaHeaders
& headers
,
94 const base::StringPiece
& key
,
95 BalsaHeaders::HeaderTokenList
* tokens
) {
99 // We may have more then 1 line with the same header key. Tokenize them all
100 // and stick all the tokens into the same list.
101 for (BalsaHeaders::const_header_lines_key_iterator header_line
=
102 headers
.GetIteratorForKey(key
);
103 header_line
!= headers
.header_lines_key_end(); ++header_line
) {
104 ParseTokenList(header_line
->second
.begin(), header_line
->second
.end(),
109 void BalsaHeadersTokenUtils::ParseTokenList(
112 BalsaHeaders::HeaderTokenList
* tokens
) {
117 // search for first nonwhitespace, non separator char.
118 while (*start
== ',' || *start
<= ' ') {
125 const char* nws
= start
;
127 // search for next whitspace or separator char.
128 while (*start
!= ',' && *start
> ' ') {
132 tokens
->push_back(base::StringPiece(nws
, start
- nws
));
137 tokens
->push_back(base::StringPiece(nws
, start
- nws
));