Remove back() and Take(); add GrowBuffer().

This commit is contained in:
Victor Zverovich 2012-12-10 18:08:04 -08:00
parent 198ebe9cf6
commit 14e0f87d50
2 changed files with 43 additions and 61 deletions

View File

@ -113,8 +113,7 @@ void fmt::Formatter::FormatInt(T value, unsigned flags, int width, char type) {
++size;
} while ((n /= 10) != 0);
width = std::max(width, size);
buffer_.resize(buffer_.size() + width);
p = &buffer_.back();
p = GrowBuffer(width) + width - 1;
n = abs_value;
do {
*p-- = '0' + (n % 10);
@ -129,8 +128,7 @@ void fmt::Formatter::FormatInt(T value, unsigned flags, int width, char type) {
++size;
} while ((n >>= 4) != 0);
width = std::max(width, size);
buffer_.resize(buffer_.size() + width);
p = &buffer_.back();
p = GrowBuffer(width) + width - 1;
n = abs_value;
const char *digits = type == 'x' ? "0123456789abcdef" : "0123456789ABCDEF";
do {
@ -148,8 +146,7 @@ void fmt::Formatter::FormatInt(T value, unsigned flags, int width, char type) {
++size;
} while ((n >>= 3) != 0);
width = std::max(width, size);
buffer_.resize(buffer_.size() + width);
p = &buffer_.back();
p = GrowBuffer(width) + width - 1;
n = abs_value;
do {
*p-- = '0' + (n & 7);
@ -219,7 +216,7 @@ void fmt::Formatter::FormatDouble(
snprintf(&buffer_[offset], size, format, width, precision, value);
}
if (n >= 0 && offset + n < buffer_.capacity()) {
buffer_.resize(offset + n);
GrowBuffer(n);
return;
}
buffer_.reserve(n >= 0 ? offset + n + 1 : 2 * buffer_.capacity());
@ -330,9 +327,7 @@ void fmt::Formatter::Format() {
case CHAR: {
if (type && type != 'c')
ReportUnknownType(type, "char");
std::size_t offset = buffer_.size();
buffer_.resize(offset + std::max(width, 1));
char *out = &buffer_[offset];
char *out = GrowBuffer(std::max(width, 1));
*out++ = arg.int_value;
if (width > 1)
std::fill_n(out, width - 1, ' ');
@ -345,12 +340,10 @@ void fmt::Formatter::Format() {
size_t size = arg.size;
if (size == 0 && *str)
size = std::strlen(str);
size_t offset = buffer_.size();
buffer_.resize(offset + std::max<size_t>(width, size));
char *out = &buffer_[offset];
std::copy(str, str + size, out);
char *out = GrowBuffer(std::max<size_t>(width, size));
out = std::copy(str, str + size, out);
if (width > size)
std::fill_n(out + size, width - size, ' ');
std::fill_n(out, width - size, ' ');
break;
}
case POINTER:

View File

@ -34,14 +34,7 @@ class Buffer {
T *ptr_;
T data_[SIZE];
void Grow(std::size_t size) {
capacity_ = std::max(size, capacity_ + capacity_ / 2);
T *p = new T[capacity_];
std::copy(ptr_, ptr_ + size_, p);
if (ptr_ != data_)
delete [] ptr_;
ptr_ = p;
}
void Grow(std::size_t size);
// Do not implement!
Buffer(const Buffer &);
@ -56,15 +49,15 @@ class Buffer {
std::size_t size() const { return size_; }
std::size_t capacity() const { return capacity_; }
void resize(std::size_t size) {
if (size > capacity_)
Grow(size);
size_ = size;
void resize(std::size_t new_size) {
if (new_size > capacity_)
Grow(new_size);
size_ = new_size;
}
void reserve(std::size_t capacity) {
if (capacity < capacity_)
Grow(capacity - capacity_);
if (capacity > capacity_)
Grow(capacity);
}
void push_back(const T &value) {
@ -73,36 +66,33 @@ class Buffer {
ptr_[size_++] = value;
}
void append(const T *begin, const T *end) {
std::ptrdiff_t size = end - begin;
if (size_ + size > capacity_)
Grow(size);
std::copy(begin, end, ptr_ + size_);
size_ += size;
}
void append(const T *begin, const T *end);
T &operator[](std::size_t index) { return ptr_[index]; }
const T &operator[](std::size_t index) const { return ptr_[index]; }
const T &back() const { return ptr_[size_ - 1]; }
T &back() { return ptr_[size_ - 1]; }
void clear() { size_ = 0; }
void Take(Buffer &other) {
if (ptr_ != data_)
delete [] ptr_;
size_ = other.size_;
if (other.ptr_ != data_) {
ptr_ = other.ptr_;
other.ptr_ = 0;
} else {
ptr_ = data_;
std::copy(other.ptr_, other.ptr_ + size_, data_);
}
}
};
template <typename T, std::size_t SIZE>
void Buffer<T, SIZE>::Grow(std::size_t size) {
capacity_ = std::max(size, capacity_ + capacity_ / 2);
T *p = new T[capacity_];
std::copy(ptr_, ptr_ + size_, p);
if (ptr_ != data_)
delete [] ptr_;
ptr_ = p;
}
template <typename T, std::size_t SIZE>
void Buffer<T, SIZE>::append(const T *begin, const T *end) {
std::ptrdiff_t num_elements = end - begin;
if (size_ + num_elements > capacity_)
Grow(num_elements);
std::copy(begin, end, ptr_ + size_);
size_ += num_elements;
}
// A sprintf-like formatter that automatically allocates enough storage to
// fit all the output.
class Formatter {
@ -181,9 +171,12 @@ class Formatter {
void Format();
void Take(Formatter &f) {
buffer_.Take(f.buffer_);
args_.Take(f.args_);
// Grows the buffer by n characters and returns a pointer to the newly
// allocated area.
char *GrowBuffer(std::size_t n) {
std::size_t size = buffer_.size();
buffer_.resize(size + n);
return &buffer_[size];
}
public:
@ -332,9 +325,7 @@ void Formatter::FormatCustomArg(const void *arg, int width) {
std::ostringstream os;
os << value;
std::string str(os.str());
std::size_t offset = buffer_.size();
buffer_.resize(offset + std::max<std::size_t>(width, str.size()));
char *out = &buffer_[offset];
char *out = GrowBuffer(std::max<std::size_t>(width, str.size()));
std::copy(str.begin(), str.end(), out);
if (width > str.size())
std::fill_n(out + str.size(), width - str.size(), ' ');
@ -366,9 +357,7 @@ class FullFormat : public ArgFormatter {
ArgFormatter::operator=(formatter_(format));
}
FullFormat(const FullFormat& other) : ArgFormatter(other) {
formatter_.Take(other.formatter_);
}
FullFormat(const FullFormat& other) : ArgFormatter(other) {}
~FullFormat() {
FinishFormatting();