diff options
Diffstat (limited to 'chromium/net/tools/balsa/balsa_headers_token_utils.cc')
-rw-r--r-- | chromium/net/tools/balsa/balsa_headers_token_utils.cc | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/chromium/net/tools/balsa/balsa_headers_token_utils.cc b/chromium/net/tools/balsa/balsa_headers_token_utils.cc new file mode 100644 index 00000000000..c807e05c9ab --- /dev/null +++ b/chromium/net/tools/balsa/balsa_headers_token_utils.cc @@ -0,0 +1,142 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/tools/balsa/balsa_headers_token_utils.h" +#include "net/tools/balsa/string_piece_utils.h" + +namespace net { + +inline void BalsaHeadersTokenUtils::TokenizeHeaderLine( + const BalsaHeaders& headers, + const BalsaHeaders::HeaderLineDescription& header_line, + BalsaHeaders::HeaderTokenList* tokens) { + CHECK(tokens); + + // Find where this line is stored + const char* stream_begin = headers.GetPtr(header_line.buffer_base_idx); + + // Determine the boundaries of the value + const char* value_begin = stream_begin + header_line.value_begin_idx; + const char* line_end = stream_begin + header_line.last_char_idx; + + // Tokenize + ParseTokenList(value_begin, line_end, tokens); +} + +void BalsaHeadersTokenUtils::RemoveLastTokenFromHeaderValue( + const base::StringPiece& key, BalsaHeaders* headers) { + BalsaHeaders::HeaderLines::iterator it = + headers->GetHeaderLinesIterator(key, headers->header_lines_.begin()); + if (it == headers->header_lines_.end()) { + DLOG(WARNING) << "Attempting to remove last token from a non-existent " + << "header \"" << key << "\""; + return; + } + + // Find the last line with that key. + BalsaHeaders::HeaderLines::iterator header_line; + do { + header_line = it; + it = headers->GetHeaderLinesIterator(key, it + 1); + } + while (it != headers->header_lines_.end()); + + // Tokenize just that line. + BalsaHeaders::HeaderTokenList tokens; + TokenizeHeaderLine(*headers, *header_line, &tokens); + + if (tokens.empty()) { + DLOG(WARNING) << "Attempting to remove a token from an empty header value " + << "for header \"" << key << "\""; + header_line->skip = true; // remove the whole line + } else if (tokens.size() == 1) { + header_line->skip = true; // remove the whole line + } else { + // Shrink the line size and leave the extra data in the buffer. + const base::StringPiece& new_last_token = tokens[tokens.size() - 2]; + const char* last_char_address = + new_last_token.data() + new_last_token.size() - 1; + const char* stream_begin = headers->GetPtr(header_line->buffer_base_idx); + + header_line->last_char_idx = last_char_address - stream_begin + 1; + } +} + +bool BalsaHeadersTokenUtils::CheckHeaderForLastToken( + const BalsaHeaders& headers, + const base::StringPiece& key, + const base::StringPiece& token) { + BalsaHeaders::const_header_lines_key_iterator it = + headers.GetIteratorForKey(key); + if (it == headers.header_lines_key_end()) + return false; + + // Find the last line + BalsaHeaders::const_header_lines_key_iterator header_line = it; + do { + header_line = it; + ++it; + } + while (it != headers.header_lines_key_end()); + + // Tokenize just that line + BalsaHeaders::HeaderTokenList tokens; + ParseTokenList(header_line->second.begin(), header_line->second.end(), + &tokens); + + return !tokens.empty() && + StringPieceUtils::StartsWithIgnoreCase(tokens.back(), token); +} + +void BalsaHeadersTokenUtils::TokenizeHeaderValue( + const BalsaHeaders& headers, + const base::StringPiece& key, + BalsaHeaders::HeaderTokenList* tokens) { + CHECK(tokens); + tokens->clear(); + + // We may have more then 1 line with the same header key. Tokenize them all + // and stick all the tokens into the same list. + for (BalsaHeaders::const_header_lines_key_iterator header_line = + headers.GetIteratorForKey(key); + header_line != headers.header_lines_key_end(); ++header_line) { + ParseTokenList(header_line->second.begin(), header_line->second.end(), + tokens); + } +} + +void BalsaHeadersTokenUtils::ParseTokenList( + const char* start, + const char* end, + BalsaHeaders::HeaderTokenList* tokens) { + if (start == end) { + return; + } + while (true) { + // search for first nonwhitespace, non separator char. + while (*start == ',' || *start <= ' ') { + ++start; + if (start == end) { + return; + } + } + // found. marked. + const char* nws = start; + + // search for next whitspace or separator char. + while (*start != ',' && *start > ' ') { + ++start; + if (start == end) { + if (nws != start) { + tokens->push_back(base::StringPiece(nws, start - nws)); + } + return; + } + } + tokens->push_back(base::StringPiece(nws, start - nws)); + } +} + +} // namespace net + |