OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "net/tools/balsa/balsa_headers_token_utils.h" | |
6 | |
7 namespace net { | |
8 | |
9 inline void BalsaHeadersTokenUtils::TokenizeHeaderLine( | |
10 const BalsaHeaders& headers, | |
11 const BalsaHeaders::HeaderLineDescription& header_line, | |
12 BalsaHeaders::HeaderTokenList* tokens) { | |
13 CHECK(tokens); | |
14 | |
15 // Find where this line is stored | |
16 const char* stream_begin = headers.GetPtr(header_line.buffer_base_idx); | |
17 | |
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; | |
21 | |
22 // Tokenize | |
23 ParseTokenList(value_begin, line_end, tokens); | |
24 } | |
25 | |
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 << "\""; | |
33 return; | |
34 } | |
35 | |
36 // Find the last line with that key. | |
37 BalsaHeaders::HeaderLines::iterator header_line; | |
38 do { | |
39 header_line = it; | |
40 it = headers->GetHeaderLinesIterator(key, it + 1); | |
41 } | |
42 while (it != headers->header_lines_.end()); | |
43 | |
44 // Tokenize just that line. | |
45 BalsaHeaders::HeaderTokenList tokens; | |
46 TokenizeHeaderLine(*headers, *header_line, &tokens); | |
47 | |
48 if (tokens.empty()) { | |
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 | |
54 } else { | |
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); | |
60 | |
61 header_line->last_char_idx = last_char_address - stream_begin + 1; | |
62 } | |
63 } | |
64 | |
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()) | |
72 return false; | |
73 | |
74 // Find the last line | |
75 BalsaHeaders::const_header_lines_key_iterator header_line = it; | |
76 do { | |
77 header_line = it; | |
78 ++it; | |
79 } | |
80 while (it != headers.header_lines_key_end()); | |
81 | |
82 // Tokenize just that line | |
83 BalsaHeaders::HeaderTokenList tokens; | |
84 ParseTokenList(header_line->second.begin(), header_line->second.end(), | |
85 &tokens); | |
86 | |
87 return !tokens.empty() && | |
88 base::StartsWith(tokens.back(), token, | |
89 base::CompareCase::INSENSITIVE_ASCII); | |
90 } | |
91 | |
92 void BalsaHeadersTokenUtils::TokenizeHeaderValue( | |
93 const BalsaHeaders& headers, | |
94 const base::StringPiece& key, | |
95 BalsaHeaders::HeaderTokenList* tokens) { | |
96 CHECK(tokens); | |
97 tokens->clear(); | |
98 | |
99 // We may have more than 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(), | |
105 tokens); | |
106 } | |
107 } | |
108 | |
109 void BalsaHeadersTokenUtils::ParseTokenList( | |
110 const char* start, | |
111 const char* end, | |
112 BalsaHeaders::HeaderTokenList* tokens) { | |
113 if (start == end) { | |
114 return; | |
115 } | |
116 while (true) { | |
117 // search for first nonwhitespace, non separator char. | |
118 while (*start == ',' || *start <= ' ') { | |
119 ++start; | |
120 if (start == end) { | |
121 return; | |
122 } | |
123 } | |
124 // found. marked. | |
125 const char* nws = start; | |
126 | |
127 // search for next whitspace or separator char. | |
128 while (*start != ',' && *start > ' ') { | |
129 ++start; | |
130 if (start == end) { | |
131 if (nws != start) { | |
132 tokens->push_back(base::StringPiece(nws, start - nws)); | |
133 } | |
134 return; | |
135 } | |
136 } | |
137 tokens->push_back(base::StringPiece(nws, start - nws)); | |
138 } | |
139 } | |
140 | |
141 } // namespace net | |
142 | |
OLD | NEW |