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"
6 #include "net/tools/balsa/string_piece_utils.h"
10 inline void BalsaHeadersTokenUtils::TokenizeHeaderLine(
11 const BalsaHeaders& headers,
12 const BalsaHeaders::HeaderLineDescription& header_line,
13 BalsaHeaders::HeaderTokenList* tokens) {
16 // Find where this line is stored
17 const char* stream_begin = headers.GetPtr(header_line.buffer_base_idx);
19 // Determine the boundaries of the value
20 const char* value_begin = stream_begin + header_line.value_begin_idx;
21 const char* line_end = stream_begin + header_line.last_char_idx;
24 ParseTokenList(value_begin, line_end, tokens);
27 void BalsaHeadersTokenUtils::RemoveLastTokenFromHeaderValue(
28 const base::StringPiece& key, BalsaHeaders* headers) {
29 BalsaHeaders::HeaderLines::iterator it =
30 headers->GetHeaderLinesIterator(key, headers->header_lines_.begin());
31 if (it == headers->header_lines_.end()) {
32 DLOG(WARNING) << "Attempting to remove last token from a non-existent "
33 << "header \"" << key << "\"";
37 // Find the last line with that key.
38 BalsaHeaders::HeaderLines::iterator header_line;
41 it = headers->GetHeaderLinesIterator(key, it + 1);
43 while (it != headers->header_lines_.end());
45 // Tokenize just that line.
46 BalsaHeaders::HeaderTokenList tokens;
47 TokenizeHeaderLine(*headers, *header_line, &tokens);
50 DLOG(WARNING) << "Attempting to remove a token from an empty header value "
51 << "for header \"" << key << "\"";
52 header_line->skip = true; // remove the whole line
53 } else if (tokens.size() == 1) {
54 header_line->skip = true; // remove the whole line
56 // Shrink the line size and leave the extra data in the buffer.
57 const base::StringPiece& new_last_token = tokens[tokens.size() - 2];
58 const char* last_char_address =
59 new_last_token.data() + new_last_token.size() - 1;
60 const char* stream_begin = headers->GetPtr(header_line->buffer_base_idx);
62 header_line->last_char_idx = last_char_address - stream_begin + 1;
66 bool BalsaHeadersTokenUtils::CheckHeaderForLastToken(
67 const BalsaHeaders& headers,
68 const base::StringPiece& key,
69 const base::StringPiece& token) {
70 BalsaHeaders::const_header_lines_key_iterator it =
71 headers.GetIteratorForKey(key);
72 if (it == headers.header_lines_key_end())
76 BalsaHeaders::const_header_lines_key_iterator header_line = it;
81 while (it != headers.header_lines_key_end());
83 // Tokenize just that line
84 BalsaHeaders::HeaderTokenList tokens;
85 ParseTokenList(header_line->second.begin(), header_line->second.end(),
88 return !tokens.empty() &&
89 StringPieceUtils::StartsWithIgnoreCase(tokens.back(), token);
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));