Commit cf0ff19c authored by Milo Yip's avatar Milo Yip

Add Pointer default/copy constructor, assignment operator. Test constructor with tokens

parent c11547eb
...@@ -33,6 +33,16 @@ public: ...@@ -33,6 +33,16 @@ public:
static const SizeType kInvalidIndex = ~SizeType(0); static const SizeType kInvalidIndex = ~SizeType(0);
GenericPointer()
: allocator_(),
ownAllocator_(),
nameBuffer_(),
tokens_(),
tokenCount_(),
valid_(true)
{
}
GenericPointer(const Ch* source, Allocator* allocator = 0) GenericPointer(const Ch* source, Allocator* allocator = 0)
: allocator_(allocator), : allocator_(allocator),
ownAllocator_(), ownAllocator_(),
...@@ -55,16 +65,27 @@ public: ...@@ -55,16 +65,27 @@ public:
Parse(source, length); Parse(source, length);
} }
GenericPointer(const Token* tokens, size_t tokenCount) : GenericPointer(const Token* tokens, size_t tokenCount)
: allocator_(), : allocator_(),
ownAllocator_(), ownAllocator_(),
nameBuffer_(), nameBuffer_(),
tokens_(tokens), tokens_(const_cast<Token*>(tokens)),
tokenCount_(tokenCount), tokenCount_(tokenCount),
valid_(true) valid_(true)
{ {
} }
GenericPointer(const GenericPointer& rhs)
: allocator_(),
ownAllocator_(),
nameBuffer_(),
tokens_(),
tokenCount_(),
valid_()
{
*this = rhs;
}
~GenericPointer() { ~GenericPointer() {
if (nameBuffer_) { if (nameBuffer_) {
Allocator::Free(nameBuffer_); Allocator::Free(nameBuffer_);
...@@ -73,6 +94,36 @@ public: ...@@ -73,6 +94,36 @@ public:
RAPIDJSON_DELETE(ownAllocator_); RAPIDJSON_DELETE(ownAllocator_);
} }
GenericPointer& operator=(const GenericPointer& rhs) {
this->~GenericPointer();
tokenCount_ = rhs.tokenCount_;
valid_ = rhs.valid_;
if (rhs.nameBuffer_) {
if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
size_t nameBufferSize = tokenCount_; // null terminators
for (Token *t = rhs.tokens_; t != rhs.tokens_ + tokenCount_; ++t)
nameBufferSize += t->length;
nameBuffer_ = (Ch*)allocator_->Malloc(nameBufferSize * sizeof(Ch));
std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize);
tokens_ = (Token*)allocator_->Malloc(tokenCount_ * sizeof(Token));
std::memcpy(tokens_, rhs.tokens_, tokenCount_ * sizeof(Token));
// Adjust pointers to name buffer
std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
for (Token *t = rhs.tokens_; t != rhs.tokens_ + tokenCount_; ++t)
t->name += diff;
}
else
tokens_ = rhs.tokens_;
return *this;
}
bool IsValid() const { return valid_; } bool IsValid() const { return valid_; }
const Token* GetTokens() const { return tokens_; } const Token* GetTokens() const { return tokens_; }
...@@ -192,7 +243,7 @@ private: ...@@ -192,7 +243,7 @@ private:
// Create a buffer as same size of source // Create a buffer as same size of source
RAPIDJSON_ASSERT(nameBuffer_ == 0); RAPIDJSON_ASSERT(nameBuffer_ == 0);
nameBuffer_ = (Ch*)allocator_->Malloc(length); nameBuffer_ = (Ch*)allocator_->Malloc(length * sizeof(Ch));
RAPIDJSON_ASSERT(tokens_ == 0); RAPIDJSON_ASSERT(tokens_ == 0);
tokens_ = (Token*)allocator_->Malloc(length * sizeof(Token)); // Maximum possible tokens in the source tokens_ = (Token*)allocator_->Malloc(length * sizeof(Token)); // Maximum possible tokens in the source
...@@ -266,9 +317,6 @@ private: ...@@ -266,9 +317,6 @@ private:
return; return;
} }
GenericPointer(const GenericPointer& rhs);
GenericPointer& operator=(const GenericPointer& rhs);
Allocator* allocator_; Allocator* allocator_;
Allocator* ownAllocator_; Allocator* ownAllocator_;
Ch* nameBuffer_; Ch* nameBuffer_;
......
...@@ -166,6 +166,82 @@ TEST(Pointer, Stringify) { ...@@ -166,6 +166,82 @@ TEST(Pointer, Stringify) {
} }
} }
// Construct a Pointer with static tokens, no dynamic allocation involved.
#define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, Pointer::kInvalidIndex }
#define INDEX(i) { #i, sizeof(#i) - 1, i }
static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(0) }; // equivalent to "/foo/0"
#undef NAME
#undef INDEX
TEST(Pointer, ConstructorWithToken) {
Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
EXPECT_TRUE(p.IsValid());
EXPECT_EQ(2, p.GetTokenCount());
EXPECT_EQ(3, p.GetTokens()[0].length);
EXPECT_STREQ("foo", p.GetTokens()[0].name);
EXPECT_EQ(1, p.GetTokens()[1].length);
EXPECT_STREQ("0", p.GetTokens()[1].name);
EXPECT_EQ(0, p.GetTokens()[1].index);
}
TEST(Pointer, CopyConstructor) {
{
Pointer p("/foo/0");
Pointer q(p);
EXPECT_TRUE(q.IsValid());
EXPECT_EQ(2, q.GetTokenCount());
EXPECT_EQ(3, q.GetTokens()[0].length);
EXPECT_STREQ("foo", q.GetTokens()[0].name);
EXPECT_EQ(1, q.GetTokens()[1].length);
EXPECT_STREQ("0", q.GetTokens()[1].name);
EXPECT_EQ(0, q.GetTokens()[1].index);
}
// Static tokens
{
Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
Pointer q(p);
EXPECT_TRUE(q.IsValid());
EXPECT_EQ(2, q.GetTokenCount());
EXPECT_EQ(3, q.GetTokens()[0].length);
EXPECT_STREQ("foo", q.GetTokens()[0].name);
EXPECT_EQ(1, q.GetTokens()[1].length);
EXPECT_STREQ("0", q.GetTokens()[1].name);
EXPECT_EQ(0, q.GetTokens()[1].index);
}
}
TEST(Pointer, Assignment) {
{
Pointer p("/foo/0");
Pointer q;
q = p;
EXPECT_TRUE(q.IsValid());
EXPECT_EQ(2, q.GetTokenCount());
EXPECT_EQ(3, q.GetTokens()[0].length);
EXPECT_STREQ("foo", q.GetTokens()[0].name);
EXPECT_EQ(1, q.GetTokens()[1].length);
EXPECT_STREQ("0", q.GetTokens()[1].name);
EXPECT_EQ(0, q.GetTokens()[1].index);
}
// Static tokens
{
Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
Pointer q;
q = p;
EXPECT_TRUE(q.IsValid());
EXPECT_EQ(2, q.GetTokenCount());
EXPECT_EQ(3, q.GetTokens()[0].length);
EXPECT_STREQ("foo", q.GetTokens()[0].name);
EXPECT_EQ(1, q.GetTokens()[1].length);
EXPECT_STREQ("0", q.GetTokens()[1].name);
EXPECT_EQ(0, q.GetTokens()[1].index);
}
}
TEST(Pointer, Create) { TEST(Pointer, Create) {
Document d; Document d;
EXPECT_EQ(&d, &Pointer("").Create(d, d.GetAllocator())); EXPECT_EQ(&d, &Pointer("").Create(d, d.GetAllocator()));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment