This source file includes following definitions.
- size_
- Clear
- Pop
- Validate
#include "chrome/renderer/net/predictor_queue.h"
#include "base/logging.h"
#include "base/metrics/stats_counters.h"
DnsQueue::DnsQueue(BufferSize size)
: buffer_(new char[size + 2]),
buffer_size_(size + 1),
buffer_sentinel_(size + 1),
size_(0) {
CHECK(0 < static_cast<BufferSize>(size + 3));
buffer_[buffer_sentinel_] = '\0';
readable_ = writeable_ = 0;
}
DnsQueue::~DnsQueue(void) {
}
void DnsQueue::Clear() {
size_ = 0;
readable_ = writeable_;
DCHECK(Validate());
}
DnsQueue::PushResult DnsQueue::Push(const char* source,
const size_t unsigned_length) {
BufferSize length = static_cast<BufferSize>(unsigned_length);
if (0 > length+1)
return OVERFLOW_PUSH;
if (0 < size_ && readable_ + length < buffer_sentinel_ &&
0 == strncmp(source, &buffer_[readable_], unsigned_length) &&
'\0' == buffer_[readable_ + unsigned_length]) {
SIMPLE_STATS_COUNTER("DNS.PrefetchDnsRedundantPush");
return REDUNDANT_PUSH;
}
DCHECK(!length || '\0' != source[length - 1]);
DCHECK(Validate());
BufferSize available_space = readable_ - writeable_;
if (0 >= available_space) {
available_space += buffer_size_;
}
if (length + 1 >= available_space) {
SIMPLE_STATS_COUNTER("DNS.PrefetchDnsQueueFull");
return OVERFLOW_PUSH;
}
BufferSize dest = writeable_;
BufferSize space_till_wrap = buffer_sentinel_ - dest;
if (space_till_wrap < length + 1) {
std::memcpy(&buffer_[dest], source, space_till_wrap);
DCHECK(static_cast<size_t>(space_till_wrap) == strlen(&buffer_[dest]));
length -= space_till_wrap;
source += space_till_wrap;
dest = 0;
}
std::memcpy(&buffer_[dest], source, length);
DCHECK(dest + length < buffer_sentinel_);
buffer_[dest + length] = '\0';
DCHECK(static_cast<size_t>(length) == strlen(&buffer_[dest]));
dest += length + 1;
if (dest == buffer_sentinel_)
dest = 0;
writeable_ = dest;
size_++;
DCHECK(Validate());
return SUCCESSFUL_PUSH;
}
bool DnsQueue::Pop(std::string* out_string) {
DCHECK(Validate());
DCHECK('\0' == buffer_[buffer_sentinel_]);
if (readable_ == writeable_) {
return false;
}
(*out_string) = &buffer_[readable_];
BufferSize first_fragment_size = static_cast<BufferSize> (out_string->size());
BufferSize terminal_null;
if (readable_ + first_fragment_size >= buffer_sentinel_) {
out_string->append(&buffer_[0]);
terminal_null = static_cast<BufferSize>(out_string->size())
- first_fragment_size;
} else {
terminal_null = readable_ + first_fragment_size;
}
DCHECK('\0' == buffer_[terminal_null]);
BufferSize new_readable = terminal_null + 1;
if (buffer_sentinel_ == new_readable)
new_readable = 0;
readable_ = new_readable;
size_--;
if (readable_ == writeable_ || 0 == size_) {
readable_ = writeable_ = 0;
}
DCHECK(Validate());
return true;
}
bool DnsQueue::Validate() {
return (readable_ >= 0) &&
readable_ < buffer_sentinel_ &&
writeable_ >= 0 &&
writeable_ < buffer_sentinel_ &&
'\0' == buffer_[buffer_sentinel_] &&
((0 == size_) == (readable_ == writeable_));
}