Rename Buffer to Array and test it.
This commit is contained in:
parent
4db5a66455
commit
57dbd2c3fe
@ -223,8 +223,9 @@ void fmt::Formatter::FormatDouble(
|
||||
}
|
||||
}
|
||||
|
||||
void fmt::Formatter::Format() {
|
||||
void fmt::Formatter::DoFormat() {
|
||||
const char *start = format_;
|
||||
format_ = 0;
|
||||
const char *s = start;
|
||||
while (*s) {
|
||||
char c = *s++;
|
||||
|
45
format.h
45
format.h
@ -15,9 +15,10 @@
|
||||
|
||||
namespace format {
|
||||
|
||||
// A buffer with the first SIZE elements stored in the object itself.
|
||||
// A simple array for POD types with the first SIZE elements stored in
|
||||
// the object itself. It supports a subset of std::vector's operations.
|
||||
template <typename T, std::size_t SIZE>
|
||||
class Buffer {
|
||||
class Array {
|
||||
private:
|
||||
std::size_t size_;
|
||||
std::size_t capacity_;
|
||||
@ -27,22 +28,22 @@ class Buffer {
|
||||
void Grow(std::size_t size);
|
||||
|
||||
// Do not implement!
|
||||
Buffer(const Buffer &);
|
||||
void operator=(const Buffer &);
|
||||
Array(const Array &);
|
||||
void operator=(const Array &);
|
||||
|
||||
public:
|
||||
Buffer() : size_(0), capacity_(SIZE), ptr_(data_) {}
|
||||
~Buffer() {
|
||||
Array() : size_(0), capacity_(SIZE), ptr_(data_) {}
|
||||
~Array() {
|
||||
if (ptr_ != data_) delete [] ptr_;
|
||||
}
|
||||
|
||||
// Returns the size of this buffer.
|
||||
// Returns the size of this array.
|
||||
std::size_t size() const { return size_; }
|
||||
|
||||
// Returns the capacity of this buffer.
|
||||
// Returns the capacity of this array.
|
||||
std::size_t capacity() const { return capacity_; }
|
||||
|
||||
// Resizes the buffer. If T is a POD type new elements are not initialized.
|
||||
// Resizes the array. If T is a POD type new elements are not initialized.
|
||||
void resize(std::size_t new_size) {
|
||||
if (new_size > capacity_)
|
||||
Grow(new_size);
|
||||
@ -62,7 +63,7 @@ class Buffer {
|
||||
ptr_[size_++] = value;
|
||||
}
|
||||
|
||||
// Appends data to the end of the buffer.
|
||||
// Appends data to the end of the array.
|
||||
void append(const T *begin, const T *end);
|
||||
|
||||
T &operator[](std::size_t index) { return ptr_[index]; }
|
||||
@ -70,7 +71,7 @@ class Buffer {
|
||||
};
|
||||
|
||||
template <typename T, std::size_t SIZE>
|
||||
void Buffer<T, SIZE>::Grow(std::size_t size) {
|
||||
void Array<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);
|
||||
@ -80,7 +81,7 @@ void Buffer<T, SIZE>::Grow(std::size_t size) {
|
||||
}
|
||||
|
||||
template <typename T, std::size_t SIZE>
|
||||
void Buffer<T, SIZE>::append(const T *begin, const T *end) {
|
||||
void Array<T, SIZE>::append(const T *begin, const T *end) {
|
||||
std::ptrdiff_t num_elements = end - begin;
|
||||
if (size_ + num_elements > capacity_)
|
||||
Grow(num_elements);
|
||||
@ -112,7 +113,7 @@ class BasicArgFormatter;
|
||||
class Formatter {
|
||||
private:
|
||||
enum { INLINE_BUFFER_SIZE = 500 };
|
||||
Buffer<char, INLINE_BUFFER_SIZE> buffer_; // Output buffer.
|
||||
Array<char, INLINE_BUFFER_SIZE> buffer_; // Output buffer.
|
||||
|
||||
enum Type {
|
||||
// Numeric types should go first.
|
||||
@ -160,7 +161,7 @@ class Formatter {
|
||||
FormatFunc format;
|
||||
};
|
||||
};
|
||||
mutable Formatter **formatter;
|
||||
mutable Formatter *formatter;
|
||||
|
||||
Arg(int value) : type(INT), int_value(value) {}
|
||||
Arg(unsigned value) : type(UINT), uint_value(value) {}
|
||||
@ -193,15 +194,12 @@ class Formatter {
|
||||
// so it will be alive in the Arg's destructor when Format is called.
|
||||
// Note that the string object will not necessarily be alive when
|
||||
// the destructor of BasicArgFormatter is called.
|
||||
if (*formatter) {
|
||||
(*formatter)->Format();
|
||||
*formatter = 0;
|
||||
}
|
||||
formatter->Format();
|
||||
}
|
||||
};
|
||||
|
||||
enum { NUM_INLINE_ARGS = 10 };
|
||||
Buffer<const Arg*, NUM_INLINE_ARGS> args_; // Format arguments.
|
||||
Array<const Arg*, NUM_INLINE_ARGS> args_; // Format arguments.
|
||||
|
||||
const char *format_; // Format string.
|
||||
|
||||
@ -224,7 +222,12 @@ class Formatter {
|
||||
template <typename T>
|
||||
void FormatCustomArg(const void *arg, int width);
|
||||
|
||||
void Format();
|
||||
void DoFormat();
|
||||
|
||||
void Format() {
|
||||
if (!format_) return;
|
||||
DoFormat();
|
||||
}
|
||||
|
||||
// Grows the buffer by n characters and returns a pointer to the newly
|
||||
// allocated area.
|
||||
@ -284,7 +287,7 @@ class BasicArgFormatter {
|
||||
~BasicArgFormatter();
|
||||
|
||||
BasicArgFormatter &operator<<(const Formatter::Arg &arg) {
|
||||
arg.formatter = &formatter_;
|
||||
arg.formatter = formatter_;
|
||||
formatter_->Add(arg);
|
||||
return *this;
|
||||
}
|
||||
|
@ -66,6 +66,82 @@ class TestString {
|
||||
}
|
||||
};
|
||||
|
||||
TEST(ArrayTest, Ctor) {
|
||||
fmt::Array<char, 123> array;
|
||||
EXPECT_EQ(0, array.size());
|
||||
EXPECT_EQ(123, array.capacity());
|
||||
}
|
||||
|
||||
TEST(ArrayTest, Access) {
|
||||
fmt::Array<char, 10> array;
|
||||
array[0] = 11;
|
||||
EXPECT_EQ(11, array[0]);
|
||||
array[3] = 42;
|
||||
EXPECT_EQ(42, *(&array[0] + 3));
|
||||
const fmt::Array<char, 10> &carray = array;
|
||||
EXPECT_EQ(42, carray[3]);
|
||||
}
|
||||
|
||||
TEST(ArrayTest, Resize) {
|
||||
fmt::Array<char, 123> array;
|
||||
array[10] = 42;
|
||||
EXPECT_EQ(42, array[10]);
|
||||
array.resize(20);
|
||||
EXPECT_EQ(20, array.size());
|
||||
EXPECT_EQ(123, array.capacity());
|
||||
EXPECT_EQ(42, array[10]);
|
||||
array.resize(5);
|
||||
EXPECT_EQ(5, array.size());
|
||||
EXPECT_EQ(123, array.capacity());
|
||||
EXPECT_EQ(42, array[10]);
|
||||
}
|
||||
|
||||
TEST(ArrayTest, Grow) {
|
||||
fmt::Array<int, 10> array;
|
||||
array.resize(10);
|
||||
for (int i = 0; i < 10; ++i)
|
||||
array[i] = i * i;
|
||||
array.resize(20);
|
||||
EXPECT_EQ(20, array.size());
|
||||
EXPECT_EQ(20, array.capacity());
|
||||
for (int i = 0; i < 10; ++i)
|
||||
EXPECT_EQ(i * i, array[i]);
|
||||
}
|
||||
|
||||
TEST(ArrayTest, Clear) {
|
||||
fmt::Array<char, 10> array;
|
||||
array.resize(20);
|
||||
array.clear();
|
||||
EXPECT_EQ(0, array.size());
|
||||
EXPECT_EQ(20, array.capacity());
|
||||
}
|
||||
|
||||
TEST(ArrayTest, PushBack) {
|
||||
fmt::Array<int, 10> array;
|
||||
array.push_back(11);
|
||||
EXPECT_EQ(11, array[0]);
|
||||
EXPECT_EQ(1, array.size());
|
||||
array.resize(10);
|
||||
array.push_back(22);
|
||||
EXPECT_EQ(22, array[10]);
|
||||
EXPECT_EQ(11, array.size());
|
||||
EXPECT_EQ(15, array.capacity());
|
||||
}
|
||||
|
||||
TEST(ArrayTest, Append) {
|
||||
fmt::Array<char, 10> array;
|
||||
const char *test = "test";
|
||||
array.append(test, test + 5);
|
||||
EXPECT_STREQ("test", &array[0]);
|
||||
EXPECT_EQ(5, array.size());
|
||||
array.resize(10);
|
||||
array.append(test, test + 2);
|
||||
EXPECT_EQ('t', array[10]);
|
||||
EXPECT_EQ('e', array[11]);
|
||||
EXPECT_EQ(12, array.size());
|
||||
EXPECT_EQ(15, array.capacity());
|
||||
}
|
||||
|
||||
TEST(FormatterTest, Escape) {
|
||||
EXPECT_EQ("{", str(Format("{{")));
|
||||
EXPECT_EQ("before {", str(Format("before {{")));
|
||||
@ -446,6 +522,16 @@ TEST(FormatterTest, FormatStringFromSpeedTest) {
|
||||
<< reinterpret_cast<void*>(1000) << 'X'));
|
||||
}
|
||||
|
||||
TEST(FormatterTest, ArgLifetime) {
|
||||
// The following code is for testing purposes only. It is a definite abuse
|
||||
// of the API and shouldn't be used in real applications.
|
||||
const fmt::BasicArgFormatter &af = fmt::Format("{0}");
|
||||
const_cast<fmt::BasicArgFormatter&>(af) << std::string("test");
|
||||
// String object passed as an argument to Print has been destroyed,
|
||||
// but BasicArgFormatter dtor hasn't been called yet.
|
||||
EXPECT_EQ("test", str(af));
|
||||
}
|
||||
|
||||
TEST(FormatterTest, Formatter) {
|
||||
Formatter format;
|
||||
format("Current point:\n");
|
||||
@ -453,4 +539,4 @@ TEST(FormatterTest, Formatter) {
|
||||
EXPECT_STREQ("Current point:\n(-3.140000, +3.140000)\n", format.c_str());
|
||||
}
|
||||
|
||||
// TODO: test Buffer
|
||||
// TODO: test API
|
||||
|
Loading…
Reference in New Issue
Block a user