Home | History | Annotate | Download | only in http
      1 // Copyright (c) 2009 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 <algorithm>
      6 
      7 #include "base/format_macros.h"
      8 #include "base/logging.h"
      9 #include "base/strings/stringprintf.h"
     10 #include "net/http/http_byte_range.h"
     11 
     12 namespace {
     13 
     14 const int64 kPositionNotSpecified = -1;
     15 
     16 }  // namespace
     17 
     18 namespace net {
     19 
     20 HttpByteRange::HttpByteRange()
     21     : first_byte_position_(kPositionNotSpecified),
     22       last_byte_position_(kPositionNotSpecified),
     23       suffix_length_(kPositionNotSpecified),
     24       has_computed_bounds_(false) {
     25 }
     26 
     27 // static
     28 HttpByteRange HttpByteRange::Bounded(int64 first_byte_position,
     29                                      int64 last_byte_position) {
     30   HttpByteRange range;
     31   range.set_first_byte_position(first_byte_position);
     32   range.set_last_byte_position(last_byte_position);
     33   return range;
     34 }
     35 
     36 // static
     37 HttpByteRange HttpByteRange::RightUnbounded(int64 first_byte_position) {
     38   HttpByteRange range;
     39   range.set_first_byte_position(first_byte_position);
     40   return range;
     41 }
     42 
     43 // static
     44 HttpByteRange HttpByteRange::Suffix(int64 suffix_length) {
     45   HttpByteRange range;
     46   range.set_suffix_length(suffix_length);
     47   return range;
     48 }
     49 
     50 bool HttpByteRange::IsSuffixByteRange() const {
     51   return suffix_length_ != kPositionNotSpecified;
     52 }
     53 
     54 bool HttpByteRange::HasFirstBytePosition() const {
     55   return first_byte_position_ != kPositionNotSpecified;
     56 }
     57 
     58 bool HttpByteRange::HasLastBytePosition() const {
     59   return last_byte_position_ != kPositionNotSpecified;
     60 }
     61 
     62 bool HttpByteRange::IsValid() const {
     63   if (suffix_length_ > 0)
     64     return true;
     65   return (first_byte_position_ >= 0 &&
     66           (last_byte_position_ == kPositionNotSpecified ||
     67            last_byte_position_ >= first_byte_position_));
     68 }
     69 
     70 std::string HttpByteRange::GetHeaderValue() const {
     71   DCHECK(IsValid());
     72 
     73   if (IsSuffixByteRange())
     74     return base::StringPrintf("bytes=-%" PRId64, suffix_length());
     75 
     76   DCHECK(HasFirstBytePosition());
     77 
     78   if (!HasLastBytePosition())
     79     return base::StringPrintf("bytes=%" PRId64 "-", first_byte_position());
     80 
     81   return base::StringPrintf("bytes=%" PRId64 "-%" PRId64,
     82                             first_byte_position(), last_byte_position());
     83 }
     84 
     85 bool HttpByteRange::ComputeBounds(int64 size) {
     86   if (size < 0)
     87     return false;
     88   if (has_computed_bounds_)
     89     return false;
     90   has_computed_bounds_ = true;
     91 
     92   // Empty values.
     93   if (!HasFirstBytePosition() &&
     94       !HasLastBytePosition() &&
     95       !IsSuffixByteRange()) {
     96     first_byte_position_ = 0;
     97     last_byte_position_ = size - 1;
     98     return true;
     99   }
    100   if (!IsValid())
    101     return false;
    102   if (IsSuffixByteRange()) {
    103     first_byte_position_ = size - std::min(size, suffix_length_);
    104     last_byte_position_ = size - 1;
    105     return true;
    106   }
    107   if (first_byte_position_ < size) {
    108     if (HasLastBytePosition())
    109       last_byte_position_ = std::min(size - 1, last_byte_position_);
    110     else
    111       last_byte_position_ = size - 1;
    112     return true;
    113   }
    114   return false;
    115 }
    116 
    117 }  // namespace net
    118