Commit 941aa93f authored by Milo Yip's avatar Milo Yip

Separate Document's value and stack allocator.

Use CrtAllocator for stack.
ShrinkToFit stack after parsing.
parent 37140198
......@@ -1259,7 +1259,7 @@ int z = a[0u].GetInt(); // This works too.
}
private:
template <typename, typename>
template <typename, typename, typename>
friend class GenericDocument;
enum {
......@@ -1406,11 +1406,12 @@ typedef GenericValue<UTF8<> > Value;
//! A document for parsing JSON text as DOM.
/*!
\note implements Handler concept
\tparam Encoding encoding for both parsing and string storage.
\tparam Allocator allocator for allocating memory for the DOM, and the stack during parsing.
\warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructors. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue.
\tparam Encoding Encoding for both parsing and string storage.
\tparam Allocator Allocator for allocating memory for the DOM
\tparam StackAllocator Allocator for allocating memory for stack during parsing.
\warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue.
*/
template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator>
class GenericDocument : public GenericValue<Encoding, Allocator> {
public:
typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
......@@ -1418,10 +1419,20 @@ public:
typedef Allocator AllocatorType; //!< Allocator type from template parameter.
//! Constructor
/*! \param allocator Optional allocator for allocating stack memory.
\param stackCapacity Initial capacity of stack in bytes.
/*! \param allocator Optional allocator for allocating memory.
\param stackCapacity Optional initial capacity of stack in bytes.
\param stackAllocator Optional allocator for allocating memory for stack.
*/
GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseResult_() {}
GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
{
if (!allocator_)
ownAllocator_ = allocator_ = new Allocator();
}
~GenericDocument() {
delete ownAllocator_;
}
//!@name Parse from stream
//!@{
......@@ -1549,7 +1560,7 @@ public:
//!@}
//! Get the allocator of this document.
Allocator& GetAllocator() { return stack_.GetAllocator(); }
Allocator& GetAllocator() { return *allocator_; }
//! Get the capacity of stack in bytes.
size_t GetStackCapacity() const { return stack_.GetCapacity(); }
......@@ -1612,10 +1623,13 @@ private:
(stack_.template Pop<ValueType>(1))->~ValueType();
else
stack_.Clear();
stack_.ShrinkToFit();
}
static const size_t kDefaultStackCapacity = 1024;
internal::Stack<Allocator> stack_;
Allocator* allocator_;
Allocator* ownAllocator_;
internal::Stack<StackAllocator> stack_;
ParseResult parseResult_;
};
......
......@@ -28,48 +28,58 @@
using namespace rapidjson;
TEST(Document, Parse) {
Document doc;
template <typename Allocator, typename StackAllocator>
void ParseTest() {
typedef GenericDocument<UTF8<>, Allocator, StackAllocator> DocumentType;
typedef DocumentType::ValueType ValueType;
DocumentType doc;
doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ");
EXPECT_TRUE(doc.IsObject());
EXPECT_TRUE(doc.HasMember("hello"));
Value& hello = doc["hello"];
const ValueType& hello = doc["hello"];
EXPECT_TRUE(hello.IsString());
EXPECT_STREQ("world", hello.GetString());
EXPECT_TRUE(doc.HasMember("t"));
Value& t = doc["t"];
const ValueType& t = doc["t"];
EXPECT_TRUE(t.IsTrue());
EXPECT_TRUE(doc.HasMember("f"));
Value& f = doc["f"];
const ValueType& f = doc["f"];
EXPECT_TRUE(f.IsFalse());
EXPECT_TRUE(doc.HasMember("n"));
Value& n = doc["n"];
const ValueType& n = doc["n"];
EXPECT_TRUE(n.IsNull());
EXPECT_TRUE(doc.HasMember("i"));
Value& i = doc["i"];
const ValueType& i = doc["i"];
EXPECT_TRUE(i.IsNumber());
EXPECT_EQ(123, i.GetInt());
EXPECT_TRUE(doc.HasMember("pi"));
Value& pi = doc["pi"];
const ValueType& pi = doc["pi"];
EXPECT_TRUE(pi.IsNumber());
EXPECT_EQ(3.1416, pi.GetDouble());
EXPECT_TRUE(doc.HasMember("a"));
Value& a = doc["a"];
const ValueType& a = doc["a"];
EXPECT_TRUE(a.IsArray());
EXPECT_EQ(4u, a.Size());
for (SizeType i = 0; i < 4; i++)
EXPECT_EQ(i + 1, a[i].GetUint());
}
TEST(Document, Parse) {
ParseTest<MemoryPoolAllocator<>, CrtAllocator>();
ParseTest<MemoryPoolAllocator<>, MemoryPoolAllocator<> >();
ParseTest<CrtAllocator, MemoryPoolAllocator<> >();
ParseTest<CrtAllocator, CrtAllocator>();
}
static FILE* OpenEncodedFile(const char* filename) {
char buffer[1024];
sprintf(buffer, "encodings/%s", filename);
......
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