I need a class representing a parsed Range
HTTP header value. I've done it like this:
namespace net {
namespace http {
class DataRange {
public:
static const uint64_t UnspecifiedBytePos;
static const DataRange Full;
explicit DataRange(uint64_t firstBytePos, uint64_t lastBytePos);
DataRange(const DataRange& other);
uint64_t FirstBytePos() const;
uint64_t LastBytePos() const;
uint64_t Size() const;
bool HasUnspecifiedBytePos() const;
bool operator==(const DataRange& other) const;
bool operator!=(const DataRange& other) const;
private:
uint64_t firstBytePos_;
uint64_t lastBytePos_;
};
typedef std::list<DataRange> DataRanges;
DataRange SpecifyDataRangeBytePos(const DataRange& dataRange, uint64_t dataSize);
} // namespace http
} // namespace net
I don't show the implementation here since it's quite simple. In this implementation, DataRange
may have unspecified borders, representing Range
headers like this one:
Range: -1234
To turn DataRange
to one with specified borders, I've made a function SpecifyDataRangeBytePos
:
DataRange SpecifyDataRangeBytePos(const DataRange& dataRange, uint64_t dataSize) {
uint64_t specifiedFirstBytePos = dataRange.FirstBytePos();
if ((dataRange.FirstBytePos() == DataRange::UnspecifiedBytePos) &&
(dataRange.LastBytePos() != DataRange::UnspecifiedBytePos)) {
uint64_t rangeUpperBorder = std::min(dataSize, dataRange.LastBytePos());
specifiedFirstBytePos = dataSize - rangeUpperBorder;
}
if ((dataRange.FirstBytePos() == DataRange::UnspecifiedBytePos) &&
(dataRange.LastBytePos() == DataRange::UnspecifiedBytePos)) {
specifiedFirstBytePos = 0;
}
uint64_t specifiedLastBytePos = dataRange.LastBytePos();
if ((dataRange.LastBytePos() != DataRange::UnspecifiedBytePos) &&
(dataRange.FirstBytePos() == DataRange::UnspecifiedBytePos)) {
specifiedLastBytePos = (dataSize > 0) ? (dataSize - 1) : dataSize;
}
if ((dataRange.LastBytePos() == DataRange::UnspecifiedBytePos) &&
(dataRange.FirstBytePos() != DataRange::UnspecifiedBytePos)) {
specifiedLastBytePos = (dataSize > 0) ? (dataSize - 1) : dataSize;
}
if ((dataRange.LastBytePos() == DataRange::UnspecifiedBytePos) &&
(dataRange.FirstBytePos() == DataRange::UnspecifiedBytePos)) {
specifiedLastBytePos = (dataSize > 0) ? (dataSize - 1) : dataSize;
}
DataRange result(specifiedFirstBytePos, specifiedLastBytePos);
assert(!result.HasUnspecifiedBytePos());
return result;
}
There are plenty of if
s, which seems very awkward, but I cannot do better. Any suggestions?