| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/tools/balsa/balsa_headers.h" | 5 #include "net/tools/balsa/balsa_headers.h" |
| 6 | 6 |
| 7 #include <stdio.h> | 7 #include <stdio.h> |
| 8 #include <algorithm> | 8 #include <algorithm> |
| 9 #include <ext/hash_set> | 9 #include <ext/hash_set> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 REGISTER_MODULE_INITIALIZER(multivalued_headers, InitMultivaluedHeaders()); | 61 REGISTER_MODULE_INITIALIZER(multivalued_headers, InitMultivaluedHeaders()); |
| 62 | 62 |
| 63 const int kFastToBufferSize = 32; // I think 22 is adequate, but anyway.. | 63 const int kFastToBufferSize = 32; // I think 22 is adequate, but anyway.. |
| 64 | 64 |
| 65 } // namespace | 65 } // namespace |
| 66 | 66 |
| 67 namespace net { | 67 namespace net { |
| 68 | 68 |
| 69 const size_t BalsaBuffer::kDefaultBlocksize; | 69 const size_t BalsaBuffer::kDefaultBlocksize; |
| 70 | 70 |
| 71 BalsaHeaders::iterator_base::iterator_base() : headers_(NULL), idx_(0) { } | 71 BalsaHeaders::iterator_base::iterator_base() : headers_(NULL), idx_(0) { |
| 72 } |
| 72 | 73 |
| 73 BalsaHeaders::iterator_base::iterator_base(const iterator_base& it) | 74 BalsaHeaders::iterator_base::iterator_base(const iterator_base& it) |
| 74 : headers_(it.headers_), | 75 : headers_(it.headers_), idx_(it.idx_) { |
| 75 idx_(it.idx_) { | |
| 76 } | 76 } |
| 77 | 77 |
| 78 std::ostream& BalsaHeaders::iterator_base::operator<<(std::ostream& os) const { | 78 std::ostream& BalsaHeaders::iterator_base::operator<<(std::ostream& os) const { |
| 79 os << "[" << this->headers_ << ", " << this->idx_ << "]"; | 79 os << "[" << this->headers_ << ", " << this->idx_ << "]"; |
| 80 return os; | 80 return os; |
| 81 } | 81 } |
| 82 | 82 |
| 83 BalsaHeaders::iterator_base::iterator_base(const BalsaHeaders* headers, | 83 BalsaHeaders::iterator_base::iterator_base(const BalsaHeaders* headers, |
| 84 HeaderLines::size_type index) | 84 HeaderLines::size_type index) |
| 85 : headers_(headers), | 85 : headers_(headers), idx_(index) { |
| 86 idx_(index) { | |
| 87 } | 86 } |
| 88 | 87 |
| 89 BalsaBuffer::~BalsaBuffer() { | 88 BalsaBuffer::~BalsaBuffer() { |
| 90 CleanupBlocksStartingFrom(0); | 89 CleanupBlocksStartingFrom(0); |
| 91 } | 90 } |
| 92 | 91 |
| 93 // Returns the total amount of memory used by the buffer blocks. | 92 // Returns the total amount of memory used by the buffer blocks. |
| 94 size_t BalsaBuffer::GetTotalBufferBlockSize() const { | 93 size_t BalsaBuffer::GetTotalBufferBlockSize() const { |
| 95 size_t buffer_size = 0; | 94 size_t buffer_size = 0; |
| 96 for (Blocks::const_iterator iter = blocks_.begin(); | 95 for (Blocks::const_iterator iter = blocks_.begin(); iter != blocks_.end(); |
| 97 iter != blocks_.end(); | |
| 98 ++iter) { | 96 ++iter) { |
| 99 buffer_size += iter->buffer_size; | 97 buffer_size += iter->buffer_size; |
| 100 } | 98 } |
| 101 return buffer_size; | 99 return buffer_size; |
| 102 } | 100 } |
| 103 | 101 |
| 104 void BalsaBuffer::WriteToContiguousBuffer(const base::StringPiece& sp) { | 102 void BalsaBuffer::WriteToContiguousBuffer(const base::StringPiece& sp) { |
| 105 if (sp.empty()) { | 103 if (sp.empty()) { |
| 106 return; | 104 return; |
| 107 } | 105 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 133 base::StringPiece BalsaBuffer::Write(const base::StringPiece& sp, | 131 base::StringPiece BalsaBuffer::Write(const base::StringPiece& sp, |
| 134 Blocks::size_type* block_buffer_idx) { | 132 Blocks::size_type* block_buffer_idx) { |
| 135 if (sp.empty()) { | 133 if (sp.empty()) { |
| 136 return sp; | 134 return sp; |
| 137 } | 135 } |
| 138 char* storage = Reserve(sp.size(), block_buffer_idx); | 136 char* storage = Reserve(sp.size(), block_buffer_idx); |
| 139 memcpy(storage, sp.data(), sp.size()); | 137 memcpy(storage, sp.data(), sp.size()); |
| 140 return base::StringPiece(storage, sp.size()); | 138 return base::StringPiece(storage, sp.size()); |
| 141 } | 139 } |
| 142 | 140 |
| 143 char* BalsaBuffer::Reserve(size_t size, | 141 char* BalsaBuffer::Reserve(size_t size, Blocks::size_type* block_buffer_idx) { |
| 144 Blocks::size_type* block_buffer_idx) { | |
| 145 // There should always be a 'first_block', even if it | 142 // There should always be a 'first_block', even if it |
| 146 // contains nothing. | 143 // contains nothing. |
| 147 DCHECK_GE(blocks_.size(), 1u); | 144 DCHECK_GE(blocks_.size(), 1u); |
| 148 BufferBlock* block = NULL; | 145 BufferBlock* block = NULL; |
| 149 Blocks::size_type block_idx = can_write_to_contiguous_buffer_ ? 1 : 0; | 146 Blocks::size_type block_idx = can_write_to_contiguous_buffer_ ? 1 : 0; |
| 150 for (; block_idx < blocks_.size(); ++block_idx) { | 147 for (; block_idx < blocks_.size(); ++block_idx) { |
| 151 if (blocks_[block_idx].bytes_free >= size) { | 148 if (blocks_[block_idx].bytes_free >= size) { |
| 152 block = &blocks_[block_idx]; | 149 block = &blocks_[block_idx]; |
| 153 break; | 150 break; |
| 154 } | 151 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 } | 195 } |
| 199 blocksize_ = b.blocksize_; | 196 blocksize_ = b.blocksize_; |
| 200 can_write_to_contiguous_buffer_ = b.can_write_to_contiguous_buffer_; | 197 can_write_to_contiguous_buffer_ = b.can_write_to_contiguous_buffer_; |
| 201 } | 198 } |
| 202 | 199 |
| 203 BalsaBuffer::BalsaBuffer() | 200 BalsaBuffer::BalsaBuffer() |
| 204 : blocksize_(kDefaultBlocksize), can_write_to_contiguous_buffer_(true) { | 201 : blocksize_(kDefaultBlocksize), can_write_to_contiguous_buffer_(true) { |
| 205 blocks_.push_back(AllocBlock()); | 202 blocks_.push_back(AllocBlock()); |
| 206 } | 203 } |
| 207 | 204 |
| 208 BalsaBuffer::BalsaBuffer(size_t blocksize) : | 205 BalsaBuffer::BalsaBuffer(size_t blocksize) |
| 209 blocksize_(blocksize), can_write_to_contiguous_buffer_(true) { | 206 : blocksize_(blocksize), can_write_to_contiguous_buffer_(true) { |
| 210 blocks_.push_back(AllocBlock()); | 207 blocks_.push_back(AllocBlock()); |
| 211 } | 208 } |
| 212 | 209 |
| 213 BalsaBuffer::BufferBlock BalsaBuffer::AllocBlock() { | 210 BalsaBuffer::BufferBlock BalsaBuffer::AllocBlock() { |
| 214 return AllocCustomBlock(blocksize_); | 211 return AllocCustomBlock(blocksize_); |
| 215 } | 212 } |
| 216 | 213 |
| 217 BalsaBuffer::BufferBlock BalsaBuffer::AllocCustomBlock(size_t blocksize) { | 214 BalsaBuffer::BufferBlock BalsaBuffer::AllocCustomBlock(size_t blocksize) { |
| 218 return BufferBlock(new char[blocksize], blocksize, blocksize); | 215 return BufferBlock(new char[blocksize], blocksize, blocksize); |
| 219 } | 216 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 231 | 228 |
| 232 void BalsaBuffer::CleanupBlocksStartingFrom(Blocks::size_type start_idx) { | 229 void BalsaBuffer::CleanupBlocksStartingFrom(Blocks::size_type start_idx) { |
| 233 for (Blocks::size_type i = start_idx; i < blocks_.size(); ++i) { | 230 for (Blocks::size_type i = start_idx; i < blocks_.size(); ++i) { |
| 234 delete[] blocks_[i].buffer; | 231 delete[] blocks_[i].buffer; |
| 235 } | 232 } |
| 236 blocks_.resize(start_idx); | 233 blocks_.resize(start_idx); |
| 237 } | 234 } |
| 238 | 235 |
| 239 BalsaHeaders::const_header_lines_key_iterator::const_header_lines_key_iterator( | 236 BalsaHeaders::const_header_lines_key_iterator::const_header_lines_key_iterator( |
| 240 const const_header_lines_key_iterator& other) | 237 const const_header_lines_key_iterator& other) |
| 241 : iterator_base(other), | 238 : iterator_base(other), key_(other.key_) { |
| 242 key_(other.key_) { | |
| 243 } | 239 } |
| 244 | 240 |
| 245 BalsaHeaders::const_header_lines_key_iterator::const_header_lines_key_iterator( | 241 BalsaHeaders::const_header_lines_key_iterator::const_header_lines_key_iterator( |
| 246 const BalsaHeaders* headers, | 242 const BalsaHeaders* headers, |
| 247 HeaderLines::size_type index, | 243 HeaderLines::size_type index, |
| 248 const base::StringPiece& key) | 244 const base::StringPiece& key) |
| 249 : iterator_base(headers, index), | 245 : iterator_base(headers, index), key_(key) { |
| 250 key_(key) { | |
| 251 } | 246 } |
| 252 | 247 |
| 253 BalsaHeaders::const_header_lines_key_iterator::const_header_lines_key_iterator( | 248 BalsaHeaders::const_header_lines_key_iterator::const_header_lines_key_iterator( |
| 254 const BalsaHeaders* headers, | 249 const BalsaHeaders* headers, |
| 255 HeaderLines::size_type index) | 250 HeaderLines::size_type index) |
| 256 : iterator_base(headers, index) { | 251 : iterator_base(headers, index) { |
| 257 } | 252 } |
| 258 | 253 |
| 259 BalsaHeaders::BalsaHeaders() | 254 BalsaHeaders::BalsaHeaders() |
| 260 : balsa_buffer_(4096), | 255 : balsa_buffer_(4096), |
| 261 content_length_(0), | 256 content_length_(0), |
| 262 content_length_status_(BalsaHeadersEnums::NO_CONTENT_LENGTH), | 257 content_length_status_(BalsaHeadersEnums::NO_CONTENT_LENGTH), |
| 263 parsed_response_code_(0), | 258 parsed_response_code_(0), |
| 264 firstline_buffer_base_idx_(0), | 259 firstline_buffer_base_idx_(0), |
| 265 whitespace_1_idx_(0), | 260 whitespace_1_idx_(0), |
| 266 non_whitespace_1_idx_(0), | 261 non_whitespace_1_idx_(0), |
| 267 whitespace_2_idx_(0), | 262 whitespace_2_idx_(0), |
| 268 non_whitespace_2_idx_(0), | 263 non_whitespace_2_idx_(0), |
| 269 whitespace_3_idx_(0), | 264 whitespace_3_idx_(0), |
| 270 non_whitespace_3_idx_(0), | 265 non_whitespace_3_idx_(0), |
| 271 whitespace_4_idx_(0), | 266 whitespace_4_idx_(0), |
| 272 end_of_firstline_idx_(0), | 267 end_of_firstline_idx_(0), |
| 273 transfer_encoding_is_chunked_(false) { | 268 transfer_encoding_is_chunked_(false) { |
| 274 } | 269 } |
| 275 | 270 |
| 276 BalsaHeaders::~BalsaHeaders() {} | 271 BalsaHeaders::~BalsaHeaders() { |
| 272 } |
| 277 | 273 |
| 278 void BalsaHeaders::Clear() { | 274 void BalsaHeaders::Clear() { |
| 279 balsa_buffer_.Clear(); | 275 balsa_buffer_.Clear(); |
| 280 transfer_encoding_is_chunked_ = false; | 276 transfer_encoding_is_chunked_ = false; |
| 281 content_length_ = 0; | 277 content_length_ = 0; |
| 282 content_length_status_ = BalsaHeadersEnums::NO_CONTENT_LENGTH; | 278 content_length_status_ = BalsaHeadersEnums::NO_CONTENT_LENGTH; |
| 283 parsed_response_code_ = 0; | 279 parsed_response_code_ = 0; |
| 284 firstline_buffer_base_idx_ = 0; | 280 firstline_buffer_base_idx_ = 0; |
| 285 whitespace_1_idx_ = 0; | 281 whitespace_1_idx_ = 0; |
| 286 non_whitespace_1_idx_ = 0; | 282 non_whitespace_1_idx_ = 0; |
| 287 whitespace_2_idx_ = 0; | 283 whitespace_2_idx_ = 0; |
| 288 non_whitespace_2_idx_ = 0; | 284 non_whitespace_2_idx_ = 0; |
| 289 whitespace_3_idx_ = 0; | 285 whitespace_3_idx_ = 0; |
| 290 non_whitespace_3_idx_ = 0; | 286 non_whitespace_3_idx_ = 0; |
| 291 whitespace_4_idx_ = 0; | 287 whitespace_4_idx_ = 0; |
| 292 end_of_firstline_idx_ = 0; | 288 end_of_firstline_idx_ = 0; |
| 293 header_lines_.clear(); | 289 header_lines_.clear(); |
| 294 } | 290 } |
| 295 | 291 |
| 296 void BalsaHeaders::Swap(BalsaHeaders* other) { | 292 void BalsaHeaders::Swap(BalsaHeaders* other) { |
| 297 // Protect against swapping with self. | 293 // Protect against swapping with self. |
| 298 if (this == other) return; | 294 if (this == other) |
| 295 return; |
| 299 | 296 |
| 300 balsa_buffer_.Swap(&other->balsa_buffer_); | 297 balsa_buffer_.Swap(&other->balsa_buffer_); |
| 301 | 298 |
| 302 bool tmp_bool = transfer_encoding_is_chunked_; | 299 bool tmp_bool = transfer_encoding_is_chunked_; |
| 303 transfer_encoding_is_chunked_ = other->transfer_encoding_is_chunked_; | 300 transfer_encoding_is_chunked_ = other->transfer_encoding_is_chunked_; |
| 304 other->transfer_encoding_is_chunked_ = tmp_bool; | 301 other->transfer_encoding_is_chunked_ = tmp_bool; |
| 305 | 302 |
| 306 size_t tmp_size_t = content_length_; | 303 size_t tmp_size_t = content_length_; |
| 307 content_length_ = other->content_length_; | 304 content_length_ = other->content_length_; |
| 308 other->content_length_ = tmp_size_t; | 305 other->content_length_ = tmp_size_t; |
| 309 | 306 |
| 310 BalsaHeadersEnums::ContentLengthStatus tmp_status = | 307 BalsaHeadersEnums::ContentLengthStatus tmp_status = content_length_status_; |
| 311 content_length_status_; | |
| 312 content_length_status_ = other->content_length_status_; | 308 content_length_status_ = other->content_length_status_; |
| 313 other->content_length_status_ = tmp_status; | 309 other->content_length_status_ = tmp_status; |
| 314 | 310 |
| 315 tmp_size_t = parsed_response_code_; | 311 tmp_size_t = parsed_response_code_; |
| 316 parsed_response_code_ = other->parsed_response_code_; | 312 parsed_response_code_ = other->parsed_response_code_; |
| 317 other->parsed_response_code_ = tmp_size_t; | 313 other->parsed_response_code_ = tmp_size_t; |
| 318 | 314 |
| 319 BalsaBuffer::Blocks::size_type tmp_blk_idx = firstline_buffer_base_idx_; | 315 BalsaBuffer::Blocks::size_type tmp_blk_idx = firstline_buffer_base_idx_; |
| 320 firstline_buffer_base_idx_ = other->firstline_buffer_base_idx_; | 316 firstline_buffer_base_idx_ = other->firstline_buffer_base_idx_; |
| 321 other->firstline_buffer_base_idx_ = tmp_blk_idx; | 317 other->firstline_buffer_base_idx_ = tmp_blk_idx; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 350 | 346 |
| 351 tmp_size_t = end_of_firstline_idx_; | 347 tmp_size_t = end_of_firstline_idx_; |
| 352 end_of_firstline_idx_ = other->end_of_firstline_idx_; | 348 end_of_firstline_idx_ = other->end_of_firstline_idx_; |
| 353 other->end_of_firstline_idx_ = tmp_size_t; | 349 other->end_of_firstline_idx_ = tmp_size_t; |
| 354 | 350 |
| 355 swap(header_lines_, other->header_lines_); | 351 swap(header_lines_, other->header_lines_); |
| 356 } | 352 } |
| 357 | 353 |
| 358 void BalsaHeaders::CopyFrom(const BalsaHeaders& other) { | 354 void BalsaHeaders::CopyFrom(const BalsaHeaders& other) { |
| 359 // Protect against copying with self. | 355 // Protect against copying with self. |
| 360 if (this == &other) return; | 356 if (this == &other) |
| 357 return; |
| 361 | 358 |
| 362 balsa_buffer_.CopyFrom(other.balsa_buffer_); | 359 balsa_buffer_.CopyFrom(other.balsa_buffer_); |
| 363 transfer_encoding_is_chunked_ = other.transfer_encoding_is_chunked_; | 360 transfer_encoding_is_chunked_ = other.transfer_encoding_is_chunked_; |
| 364 content_length_ = other.content_length_; | 361 content_length_ = other.content_length_; |
| 365 content_length_status_ = other.content_length_status_; | 362 content_length_status_ = other.content_length_status_; |
| 366 parsed_response_code_ = other.parsed_response_code_; | 363 parsed_response_code_ = other.parsed_response_code_; |
| 367 firstline_buffer_base_idx_ = other.firstline_buffer_base_idx_; | 364 firstline_buffer_base_idx_ = other.firstline_buffer_base_idx_; |
| 368 whitespace_1_idx_ = other.whitespace_1_idx_; | 365 whitespace_1_idx_ = other.whitespace_1_idx_; |
| 369 non_whitespace_1_idx_ = other.non_whitespace_1_idx_; | 366 non_whitespace_1_idx_ = other.non_whitespace_1_idx_; |
| 370 whitespace_2_idx_ = other.whitespace_2_idx_; | 367 whitespace_2_idx_ = other.whitespace_2_idx_; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 const base::StringPiece& value, | 403 const base::StringPiece& value, |
| 407 bool append, | 404 bool append, |
| 408 HeaderLineDescription* d) { | 405 HeaderLineDescription* d) { |
| 409 // Figure out how much space we need to reserve for the new header size. | 406 // Figure out how much space we need to reserve for the new header size. |
| 410 size_t old_value_size = d->last_char_idx - d->value_begin_idx; | 407 size_t old_value_size = d->last_char_idx - d->value_begin_idx; |
| 411 if (old_value_size == 0) { | 408 if (old_value_size == 0) { |
| 412 AddAndMakeDescription(key, value, d); | 409 AddAndMakeDescription(key, value, d); |
| 413 return; | 410 return; |
| 414 } | 411 } |
| 415 base::StringPiece old_value(GetPtr(d->buffer_base_idx) + d->value_begin_idx, | 412 base::StringPiece old_value(GetPtr(d->buffer_base_idx) + d->value_begin_idx, |
| 416 old_value_size); | 413 old_value_size); |
| 417 | 414 |
| 418 BalsaBuffer::Blocks::size_type block_buffer_idx = 0; | 415 BalsaBuffer::Blocks::size_type block_buffer_idx = 0; |
| 419 // + 3 because we potentially need to add ": ", and "," to the line. | 416 // + 3 because we potentially need to add ": ", and "," to the line. |
| 420 size_t new_size = key.size() + 3 + old_value_size + value.size(); | 417 size_t new_size = key.size() + 3 + old_value_size + value.size(); |
| 421 char* storage = balsa_buffer_.Reserve(new_size, &block_buffer_idx); | 418 char* storage = balsa_buffer_.Reserve(new_size, &block_buffer_idx); |
| 422 size_t base_idx = storage - GetPtr(block_buffer_idx); | 419 size_t base_idx = storage - GetPtr(block_buffer_idx); |
| 423 | 420 |
| 424 base::StringPiece first_value = old_value; | 421 base::StringPiece first_value = old_value; |
| 425 base::StringPiece second_value = value; | 422 base::StringPiece second_value = value; |
| 426 if (!append) { // !append == prepend | 423 if (!append) { // !append == prepend |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 | 519 |
| 523 void BalsaHeaders::PrependToHeader(const base::StringPiece& key, | 520 void BalsaHeaders::PrependToHeader(const base::StringPiece& key, |
| 524 const base::StringPiece& value) { | 521 const base::StringPiece& value) { |
| 525 AppendOrPrependToHeader(key, value, false); | 522 AppendOrPrependToHeader(key, value, false); |
| 526 } | 523 } |
| 527 | 524 |
| 528 base::StringPiece BalsaHeaders::GetValueFromHeaderLineDescription( | 525 base::StringPiece BalsaHeaders::GetValueFromHeaderLineDescription( |
| 529 const HeaderLineDescription& line) const { | 526 const HeaderLineDescription& line) const { |
| 530 DCHECK_GE(line.last_char_idx, line.value_begin_idx); | 527 DCHECK_GE(line.last_char_idx, line.value_begin_idx); |
| 531 return base::StringPiece(GetPtr(line.buffer_base_idx) + line.value_begin_idx, | 528 return base::StringPiece(GetPtr(line.buffer_base_idx) + line.value_begin_idx, |
| 532 line.last_char_idx - line.value_begin_idx); | 529 line.last_char_idx - line.value_begin_idx); |
| 533 } | 530 } |
| 534 | 531 |
| 535 const base::StringPiece BalsaHeaders::GetHeader( | 532 const base::StringPiece BalsaHeaders::GetHeader( |
| 536 const base::StringPiece& key) const { | 533 const base::StringPiece& key) const { |
| 537 DCHECK(!IsMultivaluedHeader(key)) | 534 DCHECK(!IsMultivaluedHeader(key)) |
| 538 << "Header '" << key << "' may consist of multiple lines. Do not " | 535 << "Header '" << key << "' may consist of multiple lines. Do not " |
| 539 << "use BalsaHeaders::GetHeader() or you may be missing some of its " | 536 << "use BalsaHeaders::GetHeader() or you may be missing some of its " |
| 540 << "values."; | 537 << "values."; |
| 541 const HeaderLines::const_iterator end = header_lines_.end(); | 538 const HeaderLines::const_iterator end = header_lines_.end(); |
| 542 const HeaderLines::const_iterator begin = header_lines_.begin(); | 539 const HeaderLines::const_iterator begin = header_lines_.begin(); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 599 const HeaderLineDescription& line = *i; | 596 const HeaderLineDescription& line = *i; |
| 600 if (line.skip) { | 597 if (line.skip) { |
| 601 continue; | 598 continue; |
| 602 } | 599 } |
| 603 const size_t key_len = line.key_end_idx - line.first_char_idx; | 600 const size_t key_len = line.key_end_idx - line.first_char_idx; |
| 604 | 601 |
| 605 if (key_len != key.size()) { | 602 if (key_len != key.size()) { |
| 606 continue; | 603 continue; |
| 607 } | 604 } |
| 608 if (strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx, | 605 if (strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx, |
| 609 key.data(), key_len) == 0) { | 606 key.data(), |
| 607 key_len) == 0) { |
| 610 DCHECK_GE(line.last_char_idx, line.value_begin_idx); | 608 DCHECK_GE(line.last_char_idx, line.value_begin_idx); |
| 611 return i; | 609 return i; |
| 612 } | 610 } |
| 613 } | 611 } |
| 614 return end; | 612 return end; |
| 615 } | 613 } |
| 616 | 614 |
| 617 BalsaHeaders::HeaderLines::iterator BalsaHeaders::GetHeaderLinesIteratorNoSkip( | 615 BalsaHeaders::HeaderLines::iterator BalsaHeaders::GetHeaderLinesIteratorNoSkip( |
| 618 const base::StringPiece& key, | 616 const base::StringPiece& key, |
| 619 BalsaHeaders::HeaderLines::iterator start) { | 617 BalsaHeaders::HeaderLines::iterator start) { |
| 620 const HeaderLines::iterator end = header_lines_.end(); | 618 const HeaderLines::iterator end = header_lines_.end(); |
| 621 for (HeaderLines::iterator i = start; i != end; ++i) { | 619 for (HeaderLines::iterator i = start; i != end; ++i) { |
| 622 const HeaderLineDescription& line = *i; | 620 const HeaderLineDescription& line = *i; |
| 623 const size_t key_len = line.key_end_idx - line.first_char_idx; | 621 const size_t key_len = line.key_end_idx - line.first_char_idx; |
| 624 | 622 |
| 625 if (key_len != key.size()) { | 623 if (key_len != key.size()) { |
| 626 continue; | 624 continue; |
| 627 } | 625 } |
| 628 if (strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx, | 626 if (strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx, |
| 629 key.data(), key_len) == 0) { | 627 key.data(), |
| 628 key_len) == 0) { |
| 630 DCHECK_GE(line.last_char_idx, line.value_begin_idx); | 629 DCHECK_GE(line.last_char_idx, line.value_begin_idx); |
| 631 return i; | 630 return i; |
| 632 } | 631 } |
| 633 } | 632 } |
| 634 return end; | 633 return end; |
| 635 } | 634 } |
| 636 | 635 |
| 637 BalsaHeaders::HeaderLines::iterator BalsaHeaders::GetHeaderLinesIterator( | 636 BalsaHeaders::HeaderLines::iterator BalsaHeaders::GetHeaderLinesIterator( |
| 638 const base::StringPiece& key, | 637 const base::StringPiece& key, |
| 639 BalsaHeaders::HeaderLines::iterator start) { | 638 BalsaHeaders::HeaderLines::iterator start) { |
| 640 const HeaderLines::iterator end = header_lines_.end(); | 639 const HeaderLines::iterator end = header_lines_.end(); |
| 641 for (HeaderLines::iterator i = start; i != end; ++i) { | 640 for (HeaderLines::iterator i = start; i != end; ++i) { |
| 642 const HeaderLineDescription& line = *i; | 641 const HeaderLineDescription& line = *i; |
| 643 if (line.skip) { | 642 if (line.skip) { |
| 644 continue; | 643 continue; |
| 645 } | 644 } |
| 646 const size_t key_len = line.key_end_idx - line.first_char_idx; | 645 const size_t key_len = line.key_end_idx - line.first_char_idx; |
| 647 | 646 |
| 648 if (key_len != key.size()) { | 647 if (key_len != key.size()) { |
| 649 continue; | 648 continue; |
| 650 } | 649 } |
| 651 if (strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx, | 650 if (strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx, |
| 652 key.data(), key_len) == 0) { | 651 key.data(), |
| 652 key_len) == 0) { |
| 653 DCHECK_GE(line.last_char_idx, line.value_begin_idx); | 653 DCHECK_GE(line.last_char_idx, line.value_begin_idx); |
| 654 return i; | 654 return i; |
| 655 } | 655 } |
| 656 } | 656 } |
| 657 return end; | 657 return end; |
| 658 } | 658 } |
| 659 | 659 |
| 660 void BalsaHeaders::GetAllOfHeader( | 660 void BalsaHeaders::GetAllOfHeader(const base::StringPiece& key, |
| 661 const base::StringPiece& key, std::vector<base::StringPiece>* out) const { | 661 std::vector<base::StringPiece>* out) const { |
| 662 for (const_header_lines_key_iterator it = GetIteratorForKey(key); | 662 for (const_header_lines_key_iterator it = GetIteratorForKey(key); |
| 663 it != header_lines_end(); ++it) { | 663 it != header_lines_end(); |
| 664 ++it) { |
| 664 out->push_back(it->second); | 665 out->push_back(it->second); |
| 665 } | 666 } |
| 666 } | 667 } |
| 667 | 668 |
| 668 bool BalsaHeaders::HasNonEmptyHeader(const base::StringPiece& key) const { | 669 bool BalsaHeaders::HasNonEmptyHeader(const base::StringPiece& key) const { |
| 669 for (const_header_lines_key_iterator it = GetIteratorForKey(key); | 670 for (const_header_lines_key_iterator it = GetIteratorForKey(key); |
| 670 it != header_lines_key_end(); ++it) { | 671 it != header_lines_key_end(); |
| 672 ++it) { |
| 671 if (!it->second.empty()) | 673 if (!it->second.empty()) |
| 672 return true; | 674 return true; |
| 673 } | 675 } |
| 674 return false; | 676 return false; |
| 675 } | 677 } |
| 676 | 678 |
| 677 void BalsaHeaders::GetAllOfHeaderAsString(const base::StringPiece& key, | 679 void BalsaHeaders::GetAllOfHeaderAsString(const base::StringPiece& key, |
| 678 std::string* out) const { | 680 std::string* out) const { |
| 679 const_header_lines_iterator it = header_lines_begin(); | 681 const_header_lines_iterator it = header_lines_begin(); |
| 680 const_header_lines_iterator end = header_lines_end(); | 682 const_header_lines_iterator end = header_lines_end(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 704 if (header_lines_[i].skip) { | 706 if (header_lines_[i].skip) { |
| 705 continue; | 707 continue; |
| 706 } | 708 } |
| 707 HeaderLineDescription& line = header_lines_[i]; | 709 HeaderLineDescription& line = header_lines_[i]; |
| 708 const size_t key_len = line.key_end_idx - line.first_char_idx; | 710 const size_t key_len = line.key_end_idx - line.first_char_idx; |
| 709 if (key_len < key.size()) { | 711 if (key_len < key.size()) { |
| 710 // If the key given to us is longer than this header, don't consider it. | 712 // If the key given to us is longer than this header, don't consider it. |
| 711 continue; | 713 continue; |
| 712 } | 714 } |
| 713 if (!strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx, | 715 if (!strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx, |
| 714 key.data(), key.size())) { | 716 key.data(), |
| 717 key.size())) { |
| 715 line.skip = true; | 718 line.skip = true; |
| 716 } | 719 } |
| 717 } | 720 } |
| 718 } | 721 } |
| 719 | 722 |
| 720 size_t BalsaHeaders::GetMemoryUsedLowerBound() const { | 723 size_t BalsaHeaders::GetMemoryUsedLowerBound() const { |
| 721 return (sizeof(*this) + | 724 return (sizeof(*this) + balsa_buffer_.GetTotalBufferBlockSize() + |
| 722 balsa_buffer_.GetTotalBufferBlockSize() + | |
| 723 header_lines_.capacity() * sizeof(HeaderLineDescription)); | 725 header_lines_.capacity() * sizeof(HeaderLineDescription)); |
| 724 } | 726 } |
| 725 | 727 |
| 726 size_t BalsaHeaders::GetSizeForWriteBuffer() const { | 728 size_t BalsaHeaders::GetSizeForWriteBuffer() const { |
| 727 // First add the space required for the first line + CRLF | 729 // First add the space required for the first line + CRLF |
| 728 size_t write_buf_size = whitespace_4_idx_ - non_whitespace_1_idx_ + 2; | 730 size_t write_buf_size = whitespace_4_idx_ - non_whitespace_1_idx_ + 2; |
| 729 // Then add the space needed for each header line to write out + CRLF. | 731 // Then add the space needed for each header line to write out + CRLF. |
| 730 const HeaderLines::size_type end = header_lines_.size(); | 732 const HeaderLines::size_type end = header_lines_.size(); |
| 731 for (HeaderLines::size_type i = 0; i < end; ++i) { | 733 for (HeaderLines::size_type i = 0; i < end; ++i) { |
| 732 const HeaderLineDescription& line = header_lines_[i]; | 734 const HeaderLineDescription& line = header_lines_[i]; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 747 OriginalHeaderStreamEnd() - OriginalHeaderStreamBegin(); | 749 OriginalHeaderStreamEnd() - OriginalHeaderStreamBegin(); |
| 748 // First check whether the header object is empty. | 750 // First check whether the header object is empty. |
| 749 if (firstline.empty() && buffer_length == 0) { | 751 if (firstline.empty() && buffer_length == 0) { |
| 750 str->append("\n<empty header>\n"); | 752 str->append("\n<empty header>\n"); |
| 751 return; | 753 return; |
| 752 } | 754 } |
| 753 | 755 |
| 754 // Then check whether the header is in a partially parsed state. If so, just | 756 // Then check whether the header is in a partially parsed state. If so, just |
| 755 // dump the raw data. | 757 // dump the raw data. |
| 756 if (balsa_buffer_.can_write_to_contiguous_buffer()) { | 758 if (balsa_buffer_.can_write_to_contiguous_buffer()) { |
| 757 base::StringAppendF(str, "\n<incomplete header len: %d>\n%.*s\n", | 759 base::StringAppendF(str, |
| 758 buffer_length, buffer_length, | 760 "\n<incomplete header len: %d>\n%.*s\n", |
| 761 buffer_length, |
| 762 buffer_length, |
| 759 OriginalHeaderStreamBegin()); | 763 OriginalHeaderStreamBegin()); |
| 760 return; | 764 return; |
| 761 } | 765 } |
| 762 | 766 |
| 763 // If the header is complete, then just dump them with the logical key value | 767 // If the header is complete, then just dump them with the logical key value |
| 764 // pair. | 768 // pair. |
| 765 str->reserve(str->size() + GetSizeForWriteBuffer()); | 769 str->reserve(str->size() + GetSizeForWriteBuffer()); |
| 766 base::StringAppendF(str, "\n %.*s\n", | 770 base::StringAppendF( |
| 767 static_cast<int>(firstline.size()), | 771 str, "\n %.*s\n", static_cast<int>(firstline.size()), firstline.data()); |
| 768 firstline.data()); | |
| 769 BalsaHeaders::const_header_lines_iterator i = header_lines_begin(); | 772 BalsaHeaders::const_header_lines_iterator i = header_lines_begin(); |
| 770 for (; i != header_lines_end(); ++i) { | 773 for (; i != header_lines_end(); ++i) { |
| 771 base::StringAppendF(str, " %.*s: %.*s\n", | 774 base::StringAppendF(str, |
| 772 static_cast<int>(i->first.size()), i->first.data(), | 775 " %.*s: %.*s\n", |
| 773 static_cast<int>(i->second.size()), i->second.data()); | 776 static_cast<int>(i->first.size()), |
| 777 i->first.data(), |
| 778 static_cast<int>(i->second.size()), |
| 779 i->second.data()); |
| 774 } | 780 } |
| 775 } | 781 } |
| 776 | 782 |
| 777 void BalsaHeaders::SetFirstLine(const base::StringPiece& line) { | 783 void BalsaHeaders::SetFirstLine(const base::StringPiece& line) { |
| 778 base::StringPiece new_line = balsa_buffer_.Write(line, | 784 base::StringPiece new_line = |
| 779 &firstline_buffer_base_idx_); | 785 balsa_buffer_.Write(line, &firstline_buffer_base_idx_); |
| 780 whitespace_1_idx_ = new_line.data() - GetPtr(firstline_buffer_base_idx_); | 786 whitespace_1_idx_ = new_line.data() - GetPtr(firstline_buffer_base_idx_); |
| 781 non_whitespace_1_idx_ = whitespace_1_idx_; | 787 non_whitespace_1_idx_ = whitespace_1_idx_; |
| 782 whitespace_4_idx_ = whitespace_1_idx_ + line.size(); | 788 whitespace_4_idx_ = whitespace_1_idx_ + line.size(); |
| 783 whitespace_2_idx_ = whitespace_4_idx_; | 789 whitespace_2_idx_ = whitespace_4_idx_; |
| 784 non_whitespace_2_idx_ = whitespace_4_idx_; | 790 non_whitespace_2_idx_ = whitespace_4_idx_; |
| 785 whitespace_3_idx_ = whitespace_4_idx_; | 791 whitespace_3_idx_ = whitespace_4_idx_; |
| 786 non_whitespace_3_idx_ = whitespace_4_idx_; | 792 non_whitespace_3_idx_ = whitespace_4_idx_; |
| 787 end_of_firstline_idx_ = whitespace_4_idx_; | 793 end_of_firstline_idx_ = whitespace_4_idx_; |
| 788 } | 794 } |
| 789 | 795 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 800 // length. There is always the possibility that client can manually add | 806 // length. There is always the possibility that client can manually add |
| 801 // either header directly and cause content_length_status_ or | 807 // either header directly and cause content_length_status_ or |
| 802 // transfer_encoding_is_chunked_ to be inconsistent with the actual header. | 808 // transfer_encoding_is_chunked_ to be inconsistent with the actual header. |
| 803 // In the interest of efficiency, however, we will assume that clients will | 809 // In the interest of efficiency, however, we will assume that clients will |
| 804 // use the header object correctly and thus we will not scan the all headers | 810 // use the header object correctly and thus we will not scan the all headers |
| 805 // each time this function is called. | 811 // each time this function is called. |
| 806 if (content_length_status_ != BalsaHeadersEnums::NO_CONTENT_LENGTH) { | 812 if (content_length_status_ != BalsaHeadersEnums::NO_CONTENT_LENGTH) { |
| 807 RemoveAllOfHeader(content_length); | 813 RemoveAllOfHeader(content_length); |
| 808 } else if (transfer_encoding_is_chunked_) { | 814 } else if (transfer_encoding_is_chunked_) { |
| 809 const base::StringPiece transfer_encoding(kTransferEncoding, | 815 const base::StringPiece transfer_encoding(kTransferEncoding, |
| 810 sizeof(kTransferEncoding) - 1); | 816 sizeof(kTransferEncoding) - 1); |
| 811 RemoveAllOfHeader(transfer_encoding); | 817 RemoveAllOfHeader(transfer_encoding); |
| 812 transfer_encoding_is_chunked_ = false; | 818 transfer_encoding_is_chunked_ = false; |
| 813 } | 819 } |
| 814 content_length_status_ = BalsaHeadersEnums::VALID_CONTENT_LENGTH; | 820 content_length_status_ = BalsaHeadersEnums::VALID_CONTENT_LENGTH; |
| 815 content_length_ = length; | 821 content_length_ = length; |
| 816 // FastUInt64ToBuffer is supposed to use a maximum of kFastToBufferSize bytes. | 822 // FastUInt64ToBuffer is supposed to use a maximum of kFastToBufferSize bytes. |
| 817 char buffer[kFastToBufferSize]; | 823 char buffer[kFastToBufferSize]; |
| 818 int len_converted = snprintf(buffer, sizeof(buffer), "%zd", length); | 824 int len_converted = snprintf(buffer, sizeof(buffer), "%zd", length); |
| 819 CHECK_GT(len_converted, 0); | 825 CHECK_GT(len_converted, 0); |
| 820 const base::StringPiece length_str(buffer, len_converted); | 826 const base::StringPiece length_str(buffer, len_converted); |
| 821 AppendHeader(content_length, length_str); | 827 AppendHeader(content_length, length_str); |
| 822 } | 828 } |
| 823 | 829 |
| 824 void BalsaHeaders::SetChunkEncoding(bool chunk_encode) { | 830 void BalsaHeaders::SetChunkEncoding(bool chunk_encode) { |
| 825 if (transfer_encoding_is_chunked_ == chunk_encode) { | 831 if (transfer_encoding_is_chunked_ == chunk_encode) { |
| 826 return; | 832 return; |
| 827 } | 833 } |
| 828 if (content_length_status_ != BalsaHeadersEnums::NO_CONTENT_LENGTH && | 834 if (content_length_status_ != BalsaHeadersEnums::NO_CONTENT_LENGTH && |
| 829 chunk_encode) { | 835 chunk_encode) { |
| 830 // Want to change to chunk encoding, but have content length. Arguably we | 836 // Want to change to chunk encoding, but have content length. Arguably we |
| 831 // can leave this step out, since transfer-encoding overrides | 837 // can leave this step out, since transfer-encoding overrides |
| 832 // content-length. | 838 // content-length. |
| 833 const base::StringPiece content_length(kContentLength, | 839 const base::StringPiece content_length(kContentLength, |
| 834 sizeof(kContentLength) - 1); | 840 sizeof(kContentLength) - 1); |
| 835 RemoveAllOfHeader(content_length); | 841 RemoveAllOfHeader(content_length); |
| 836 content_length_status_ = BalsaHeadersEnums::NO_CONTENT_LENGTH; | 842 content_length_status_ = BalsaHeadersEnums::NO_CONTENT_LENGTH; |
| 837 content_length_ = 0; | 843 content_length_ = 0; |
| 838 } | 844 } |
| 839 const base::StringPiece transfer_encoding(kTransferEncoding, | 845 const base::StringPiece transfer_encoding(kTransferEncoding, |
| 840 sizeof(kTransferEncoding) - 1); | 846 sizeof(kTransferEncoding) - 1); |
| 841 if (chunk_encode) { | 847 if (chunk_encode) { |
| 842 const char kChunked[] = "chunked"; | 848 const char kChunked[] = "chunked"; |
| 843 const base::StringPiece chunked(kChunked, sizeof(kChunked) - 1); | 849 const base::StringPiece chunked(kChunked, sizeof(kChunked) - 1); |
| 844 AppendHeader(transfer_encoding, chunked); | 850 AppendHeader(transfer_encoding, chunked); |
| 845 } else { | 851 } else { |
| 846 RemoveAllOfHeader(transfer_encoding); | 852 RemoveAllOfHeader(transfer_encoding); |
| 847 } | 853 } |
| 848 transfer_encoding_is_chunked_ = chunk_encode; | 854 transfer_encoding_is_chunked_ = chunk_encode; |
| 849 } | 855 } |
| 850 | 856 |
| 851 // See the comment about this function in the header file for a | 857 // See the comment about this function in the header file for a |
| 852 // warning about its usage. | 858 // warning about its usage. |
| 853 void BalsaHeaders::SetFirstlineFromStringPieces( | 859 void BalsaHeaders::SetFirstlineFromStringPieces( |
| 854 const base::StringPiece& firstline_a, | 860 const base::StringPiece& firstline_a, |
| 855 const base::StringPiece& firstline_b, | 861 const base::StringPiece& firstline_b, |
| 856 const base::StringPiece& firstline_c) { | 862 const base::StringPiece& firstline_c) { |
| 857 size_t line_size = (firstline_a.size() + | 863 size_t line_size = |
| 858 firstline_b.size() + | 864 (firstline_a.size() + firstline_b.size() + firstline_c.size() + 2); |
| 859 firstline_c.size() + | |
| 860 2); | |
| 861 char* storage = balsa_buffer_.Reserve(line_size, &firstline_buffer_base_idx_); | 865 char* storage = balsa_buffer_.Reserve(line_size, &firstline_buffer_base_idx_); |
| 862 char* cur_loc = storage; | 866 char* cur_loc = storage; |
| 863 | 867 |
| 864 memcpy(cur_loc, firstline_a.data(), firstline_a.size()); | 868 memcpy(cur_loc, firstline_a.data(), firstline_a.size()); |
| 865 cur_loc += firstline_a.size(); | 869 cur_loc += firstline_a.size(); |
| 866 | 870 |
| 867 *cur_loc = ' '; | 871 *cur_loc = ' '; |
| 868 ++cur_loc; | 872 ++cur_loc; |
| 869 | 873 |
| 870 memcpy(cur_loc, firstline_b.data(), firstline_b.size()); | 874 memcpy(cur_loc, firstline_b.data(), firstline_b.size()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 883 non_whitespace_3_idx_ = whitespace_3_idx_ + 1; | 887 non_whitespace_3_idx_ = whitespace_3_idx_ + 1; |
| 884 whitespace_4_idx_ = non_whitespace_3_idx_ + firstline_c.size(); | 888 whitespace_4_idx_ = non_whitespace_3_idx_ + firstline_c.size(); |
| 885 end_of_firstline_idx_ = whitespace_4_idx_; | 889 end_of_firstline_idx_ = whitespace_4_idx_; |
| 886 } | 890 } |
| 887 | 891 |
| 888 void BalsaHeaders::SetRequestMethod(const base::StringPiece& method) { | 892 void BalsaHeaders::SetRequestMethod(const base::StringPiece& method) { |
| 889 // This is the first of the three parts of the firstline. | 893 // This is the first of the three parts of the firstline. |
| 890 if (method.size() <= (whitespace_2_idx_ - non_whitespace_1_idx_)) { | 894 if (method.size() <= (whitespace_2_idx_ - non_whitespace_1_idx_)) { |
| 891 non_whitespace_1_idx_ = whitespace_2_idx_ - method.size(); | 895 non_whitespace_1_idx_ = whitespace_2_idx_ - method.size(); |
| 892 char* stream_begin = GetPtr(firstline_buffer_base_idx_); | 896 char* stream_begin = GetPtr(firstline_buffer_base_idx_); |
| 893 memcpy(stream_begin + non_whitespace_1_idx_, | 897 memcpy(stream_begin + non_whitespace_1_idx_, method.data(), method.size()); |
| 894 method.data(), | |
| 895 method.size()); | |
| 896 } else { | 898 } else { |
| 897 // The new method is too large to fit in the space available for the old | 899 // The new method is too large to fit in the space available for the old |
| 898 // one, so we have to reformat the firstline. | 900 // one, so we have to reformat the firstline. |
| 899 SetFirstlineFromStringPieces(method, request_uri(), request_version()); | 901 SetFirstlineFromStringPieces(method, request_uri(), request_version()); |
| 900 } | 902 } |
| 901 } | 903 } |
| 902 | 904 |
| 903 void BalsaHeaders::SetResponseVersion(const base::StringPiece& version) { | 905 void BalsaHeaders::SetResponseVersion(const base::StringPiece& version) { |
| 904 // Note: There is no difference between request_method() and | 906 // Note: There is no difference between request_method() and |
| 905 // response_Version(). Thus, a function to set one is equivalent to a | 907 // response_Version(). Thus, a function to set one is equivalent to a |
| (...skipping 10 matching lines...) Expand all Loading... |
| 916 // Note: There is no difference between request_uri() and response_code(). | 918 // Note: There is no difference between request_uri() and response_code(). |
| 917 // Thus, a function to set one is equivalent to a function to set the other. | 919 // Thus, a function to set one is equivalent to a function to set the other. |
| 918 // We maintain two functions for this as it is much more descriptive, and | 920 // We maintain two functions for this as it is much more descriptive, and |
| 919 // makes code more understandable. | 921 // makes code more understandable. |
| 920 SetRequestUri(code); | 922 SetRequestUri(code); |
| 921 } | 923 } |
| 922 | 924 |
| 923 void BalsaHeaders::SetParsedResponseCodeAndUpdateFirstline( | 925 void BalsaHeaders::SetParsedResponseCodeAndUpdateFirstline( |
| 924 size_t parsed_response_code) { | 926 size_t parsed_response_code) { |
| 925 char buffer[kFastToBufferSize]; | 927 char buffer[kFastToBufferSize]; |
| 926 int len_converted = snprintf(buffer, sizeof(buffer), | 928 int len_converted = |
| 927 "%zd", parsed_response_code); | 929 snprintf(buffer, sizeof(buffer), "%zd", parsed_response_code); |
| 928 CHECK_GT(len_converted, 0); | 930 CHECK_GT(len_converted, 0); |
| 929 SetResponseCode(base::StringPiece(buffer, len_converted)); | 931 SetResponseCode(base::StringPiece(buffer, len_converted)); |
| 930 } | 932 } |
| 931 | 933 |
| 932 void BalsaHeaders::SetRequestVersion(const base::StringPiece& version) { | 934 void BalsaHeaders::SetRequestVersion(const base::StringPiece& version) { |
| 933 // This is the last of the three parts of the firstline. | 935 // This is the last of the three parts of the firstline. |
| 934 // Since whitespace_3_idx and non_whitespace_3_idx may point to the same | 936 // Since whitespace_3_idx and non_whitespace_3_idx may point to the same |
| 935 // place, we ensure below that any available space includes space for a | 937 // place, we ensure below that any available space includes space for a |
| 936 // litteral space (' ') character between the second component and the third | 938 // litteral space (' ') character between the second component and the third |
| 937 // component. If the space between whitespace_3_idx_ and | 939 // component. If the space between whitespace_3_idx_ and |
| 938 // end_of_firstline_idx_ is >= to version.size() + 1 (for the space), then we | 940 // end_of_firstline_idx_ is >= to version.size() + 1 (for the space), then we |
| 939 // can update the firstline in-place. | 941 // can update the firstline in-place. |
| 940 char* stream_begin = GetPtr(firstline_buffer_base_idx_); | 942 char* stream_begin = GetPtr(firstline_buffer_base_idx_); |
| 941 if (version.size() + 1 <= end_of_firstline_idx_ - whitespace_3_idx_) { | 943 if (version.size() + 1 <= end_of_firstline_idx_ - whitespace_3_idx_) { |
| 942 *(stream_begin + whitespace_3_idx_) = kSpaceChar; | 944 *(stream_begin + whitespace_3_idx_) = kSpaceChar; |
| 943 non_whitespace_3_idx_ = whitespace_3_idx_ + 1; | 945 non_whitespace_3_idx_ = whitespace_3_idx_ + 1; |
| 944 whitespace_4_idx_ = non_whitespace_3_idx_ + version.size(); | 946 whitespace_4_idx_ = non_whitespace_3_idx_ + version.size(); |
| 945 memcpy(stream_begin + non_whitespace_3_idx_, | 947 memcpy( |
| 946 version.data(), | 948 stream_begin + non_whitespace_3_idx_, version.data(), version.size()); |
| 947 version.size()); | |
| 948 } else { | 949 } else { |
| 949 // The new version is to large to fit in the space available for the old | 950 // The new version is to large to fit in the space available for the old |
| 950 // one, so we have to reformat the firstline. | 951 // one, so we have to reformat the firstline. |
| 951 SetFirstlineFromStringPieces(request_method(), request_uri(), version); | 952 SetFirstlineFromStringPieces(request_method(), request_uri(), version); |
| 952 } | 953 } |
| 953 } | 954 } |
| 954 | 955 |
| 955 void BalsaHeaders::SetResponseReasonPhrase(const base::StringPiece& reason) { | 956 void BalsaHeaders::SetResponseReasonPhrase(const base::StringPiece& reason) { |
| 956 // Note: There is no difference between request_version() and | 957 // Note: There is no difference between request_version() and |
| 957 // response_reason_phrase(). Thus, a function to set one is equivalent to a | 958 // response_reason_phrase(). Thus, a function to set one is equivalent to a |
| 958 // function to set the other. We maintain two functions for this as it is | 959 // function to set the other. We maintain two functions for this as it is |
| 959 // much more descriptive, and makes code more understandable. | 960 // much more descriptive, and makes code more understandable. |
| 960 SetRequestVersion(reason); | 961 SetRequestVersion(reason); |
| 961 } | 962 } |
| 962 | 963 |
| 963 } // namespace net | 964 } // namespace net |
| OLD | NEW |