Merge pull request #1426 from ylavic/pointer_less_than
Add "less than" operator to Pointer.
This commit is contained in:
commit
bfdcf49110
@ -386,6 +386,33 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
|
bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
|
||||||
|
|
||||||
|
//! Less than operator.
|
||||||
|
/*!
|
||||||
|
\note Invalid pointers are always greater than valid ones.
|
||||||
|
*/
|
||||||
|
bool operator<(const GenericPointer& rhs) const {
|
||||||
|
if (!IsValid())
|
||||||
|
return false;
|
||||||
|
if (!rhs.IsValid())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (tokenCount_ != rhs.tokenCount_)
|
||||||
|
return tokenCount_ < rhs.tokenCount_;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < tokenCount_; i++) {
|
||||||
|
if (tokens_[i].index != rhs.tokens_[i].index)
|
||||||
|
return tokens_[i].index < rhs.tokens_[i].index;
|
||||||
|
|
||||||
|
if (tokens_[i].length != rhs.tokens_[i].length)
|
||||||
|
return tokens_[i].length < rhs.tokens_[i].length;
|
||||||
|
|
||||||
|
if (int cmp = std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length))
|
||||||
|
return cmp < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
//!@name Stringify
|
//!@name Stringify
|
||||||
|
@ -15,7 +15,9 @@
|
|||||||
#include "unittest.h"
|
#include "unittest.h"
|
||||||
#include "rapidjson/pointer.h"
|
#include "rapidjson/pointer.h"
|
||||||
#include "rapidjson/stringbuffer.h"
|
#include "rapidjson/stringbuffer.h"
|
||||||
|
#include "rapidjson/ostreamwrapper.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <map>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
using namespace rapidjson;
|
using namespace rapidjson;
|
||||||
@ -1524,6 +1526,79 @@ TEST(Pointer, Ambiguity) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Pointer, LessThan) {
|
||||||
|
static const struct {
|
||||||
|
const char *str;
|
||||||
|
bool valid;
|
||||||
|
} pointers[] = {
|
||||||
|
{ "/a/b", true },
|
||||||
|
{ "/a", true },
|
||||||
|
{ "/d/1", true },
|
||||||
|
{ "/d/2/z", true },
|
||||||
|
{ "/d/2/3", true },
|
||||||
|
{ "/d/2", true },
|
||||||
|
{ "/a/c", true },
|
||||||
|
{ "/e/f~g", false },
|
||||||
|
{ "/d/2/zz", true },
|
||||||
|
{ "/d/1", true },
|
||||||
|
{ "/d/2/z", true },
|
||||||
|
{ "/e/f~~g", false },
|
||||||
|
{ "/e/f~0g", true },
|
||||||
|
{ "/e/f~1g", true },
|
||||||
|
{ "/e/f.g", true },
|
||||||
|
{ "", true }
|
||||||
|
};
|
||||||
|
static const char *ordered_pointers[] = {
|
||||||
|
"",
|
||||||
|
"/a",
|
||||||
|
"/a/b",
|
||||||
|
"/a/c",
|
||||||
|
"/d/1",
|
||||||
|
"/d/1",
|
||||||
|
"/d/2",
|
||||||
|
"/e/f.g",
|
||||||
|
"/e/f~1g",
|
||||||
|
"/e/f~0g",
|
||||||
|
"/d/2/3",
|
||||||
|
"/d/2/z",
|
||||||
|
"/d/2/z",
|
||||||
|
"/d/2/zz",
|
||||||
|
NULL, // was invalid "/e/f~g"
|
||||||
|
NULL // was invalid "/e/f~~g"
|
||||||
|
};
|
||||||
|
typedef MemoryPoolAllocator<> AllocatorType;
|
||||||
|
typedef GenericPointer<Value, AllocatorType> PointerType;
|
||||||
|
typedef std::multimap<PointerType, size_t> PointerMap;
|
||||||
|
PointerMap map;
|
||||||
|
PointerMap::iterator it;
|
||||||
|
AllocatorType allocator;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
EXPECT_EQ(sizeof(pointers) / sizeof(pointers[0]),
|
||||||
|
sizeof(ordered_pointers) / sizeof(ordered_pointers[0]));
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(pointers) / sizeof(pointers[0]); ++i) {
|
||||||
|
it = map.insert(PointerMap::value_type(PointerType(pointers[i].str, &allocator), i));
|
||||||
|
if (!it->first.IsValid()) {
|
||||||
|
EXPECT_EQ(++it, map.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0, it = map.begin(); it != map.end(); ++it, ++i) {
|
||||||
|
EXPECT_TRUE(it->second < sizeof(pointers) / sizeof(pointers[0]));
|
||||||
|
EXPECT_EQ(it->first.IsValid(), pointers[it->second].valid);
|
||||||
|
EXPECT_TRUE(i < sizeof(ordered_pointers) / sizeof(ordered_pointers[0]));
|
||||||
|
EXPECT_EQ(it->first.IsValid(), !!ordered_pointers[i]);
|
||||||
|
if (it->first.IsValid()) {
|
||||||
|
std::stringstream ss;
|
||||||
|
OStreamWrapper os(ss);
|
||||||
|
EXPECT_TRUE(it->first.Stringify(os));
|
||||||
|
EXPECT_EQ(ss.str(), pointers[it->second].str);
|
||||||
|
EXPECT_EQ(ss.str(), ordered_pointers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// https://github.com/Tencent/rapidjson/issues/483
|
// https://github.com/Tencent/rapidjson/issues/483
|
||||||
namespace myjson {
|
namespace myjson {
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user