Separate Document's value and stack allocator.
Use CrtAllocator for stack. ShrinkToFit stack after parsing.
This commit is contained in:
parent
3714019819
commit
941aa93f45
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user