simplify insertion methods for SkTLList
Review URL: https://codereview.chromium.org/1459663002
This commit is contained in:
parent
f9b1577d76
commit
5aaef1ff1a
@ -10,6 +10,7 @@
|
||||
|
||||
#include "SkTInternalLList.h"
|
||||
#include "SkTypes.h"
|
||||
#include <utility>
|
||||
|
||||
template <typename T> class SkTLList;
|
||||
template <typename T>
|
||||
@ -66,52 +67,42 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
T* addToHead(const T& t) {
|
||||
/** Adds a new element to the list at the head. */
|
||||
template <typename... Args> T* addToHead(Args&&... args) {
|
||||
this->validate();
|
||||
Node* node = this->createNode();
|
||||
fList.addToHead(node);
|
||||
new (node->fObj) T(t);
|
||||
this->validate();
|
||||
return reinterpret_cast<T*>(node->fObj);
|
||||
return new (node->fObj) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
T* addToHead() {
|
||||
this->validate();
|
||||
Node* node = this->createNode();
|
||||
fList.addToHead(node);
|
||||
new (node->fObj) T;
|
||||
this->validate();
|
||||
return reinterpret_cast<T*>(node->fObj);
|
||||
}
|
||||
|
||||
T* addToTail(const T& t) {
|
||||
/** Adds a new element to the list at the tail. */
|
||||
template <typename... Args> T* addToTail(Args&&... args) {
|
||||
this->validate();
|
||||
Node* node = this->createNode();
|
||||
fList.addToTail(node);
|
||||
new (node->fObj) T(t);
|
||||
this->validate();
|
||||
return reinterpret_cast<T*>(node->fObj);
|
||||
}
|
||||
|
||||
T* addToTail() {
|
||||
this->validate();
|
||||
Node* node = this->createNode();
|
||||
fList.addToTail(node);
|
||||
new (node->fObj) T;
|
||||
this->validate();
|
||||
return reinterpret_cast<T*>(node->fObj);
|
||||
return new (node->fObj) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/** Adds a new element to the list before the location indicated by the iterator. If the
|
||||
iterator refers to a nullptr location then the new element is added at the tail */
|
||||
T* addBefore(const T& t, const Iter& location) {
|
||||
return new (this->internalAddBefore(location)) T(t);
|
||||
template <typename... Args> T* addBefore(Iter location, Args&&... args) {
|
||||
this->validate();
|
||||
Node* node = this->createNode();
|
||||
fList.addBefore(node, location.getNode());
|
||||
this->validate();
|
||||
return new (node->fObj) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/** Adds a new element to the list after the location indicated by the iterator. If the
|
||||
iterator refers to a nullptr location then the new element is added at the head */
|
||||
T* addAfter(const T& t, const Iter& location) {
|
||||
return new (this->internalAddAfter(location)) T(t);
|
||||
template <typename... Args> T* addAfter(Iter location, Args&&... args) {
|
||||
this->validate();
|
||||
Node* node = this->createNode();
|
||||
fList.addAfter(node, location.getNode());
|
||||
this->validate();
|
||||
return new (node->fObj) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/** Convenience methods for getting an iterator initialized to the head/tail of the list. */
|
||||
@ -227,12 +218,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// For use with operator new
|
||||
enum Placement {
|
||||
kBefore_Placement,
|
||||
kAfter_Placement,
|
||||
};
|
||||
|
||||
private:
|
||||
struct Block {
|
||||
int fNodesInUse;
|
||||
@ -333,30 +318,6 @@ private:
|
||||
#endif
|
||||
}
|
||||
|
||||
// Support in-place initializing of objects inserted into the list via operator new.
|
||||
friend void* operator new<T>(size_t,
|
||||
SkTLList* list,
|
||||
Placement placement,
|
||||
const Iter& location);
|
||||
|
||||
|
||||
// Helpers that insert the node and returns a pointer to where the new object should be init'ed.
|
||||
void* internalAddBefore(Iter location) {
|
||||
this->validate();
|
||||
Node* node = this->createNode();
|
||||
fList.addBefore(node, location.getNode());
|
||||
this->validate();
|
||||
return node->fObj;
|
||||
}
|
||||
|
||||
void* internalAddAfter(Iter location) {
|
||||
this->validate();
|
||||
Node* node = this->createNode();
|
||||
fList.addAfter(node, location.getNode());
|
||||
this->validate();
|
||||
return node->fObj;
|
||||
}
|
||||
|
||||
NodeList fList;
|
||||
NodeList fFreeList;
|
||||
int fCount;
|
||||
@ -364,40 +325,4 @@ private:
|
||||
|
||||
};
|
||||
|
||||
// Use the below macros rather than calling this directly
|
||||
template <typename T>
|
||||
void *operator new(size_t, SkTLList<T>* list,
|
||||
typename SkTLList<T>::Placement placement,
|
||||
const typename SkTLList<T>::Iter& location) {
|
||||
SkASSERT(list);
|
||||
if (SkTLList<T>::kBefore_Placement == placement) {
|
||||
return list->internalAddBefore(location);
|
||||
} else {
|
||||
return list->internalAddAfter(location);
|
||||
}
|
||||
}
|
||||
|
||||
// Skia doesn't use C++ exceptions but it may be compiled with them enabled. Having an op delete
|
||||
// to match the op new silences warnings about missing op delete when a constructor throws an
|
||||
// exception.
|
||||
template <typename T>
|
||||
void operator delete(void*,
|
||||
SkTLList<T>*,
|
||||
typename SkTLList<T>::Placement,
|
||||
const typename SkTLList<T>::Iter&) {
|
||||
SK_CRASH();
|
||||
}
|
||||
|
||||
#define SkNEW_INSERT_IN_LLIST_BEFORE(list, location, type_name, args) \
|
||||
(new ((list), SkTLList< type_name >::kBefore_Placement, (location)) type_name args)
|
||||
|
||||
#define SkNEW_INSERT_IN_LLIST_AFTER(list, location, type_name, args) \
|
||||
(new ((list), SkTLList< type_name >::kAfter_Placement, (location)) type_name args)
|
||||
|
||||
#define SkNEW_INSERT_AT_LLIST_HEAD(list, type_name, args) \
|
||||
SkNEW_INSERT_IN_LLIST_BEFORE((list), (list)->headIter(), type_name, args)
|
||||
|
||||
#define SkNEW_INSERT_AT_LLIST_TAIL(list, type_name, args) \
|
||||
SkNEW_INSERT_IN_LLIST_AFTER((list), (list)->tailIter(), type_name, args)
|
||||
|
||||
#endif
|
||||
|
@ -206,9 +206,7 @@ static void reduced_stack_walker(const SkClipStack& stack,
|
||||
if (isFlip) {
|
||||
SkASSERT(SkRegion::kXOR_Op == element->getOp() ||
|
||||
SkRegion::kReverseDifference_Op == element->getOp());
|
||||
SkNEW_INSERT_AT_LLIST_HEAD(result,
|
||||
Element,
|
||||
(queryBounds, SkRegion::kReverseDifference_Op, false));
|
||||
result->addToHead(queryBounds, SkRegion::kReverseDifference_Op, false);
|
||||
} else {
|
||||
Element* newElement = result->addToHead(*element);
|
||||
if (newElement->isAA()) {
|
||||
@ -386,7 +384,7 @@ void GrReducedClip::ReduceClipStack(const SkClipStack& stack,
|
||||
// iior should only be true if aa/non-aa status matches among all elements.
|
||||
SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
|
||||
bool doAA = iter.prev()->isAA();
|
||||
SkNEW_INSERT_AT_LLIST_HEAD(result, Element, (isectRect, SkRegion::kReplace_Op, doAA));
|
||||
result->addToHead(isectRect, SkRegion::kReplace_Op, doAA);
|
||||
if (requiresAA) {
|
||||
*requiresAA = doAA;
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ void GrStencilAndCoverTextContext::TextBlob::init(const SkTextBlob* skBlob,
|
||||
SkPaint runPaint(skPaint);
|
||||
for (SkTextBlobRunIterator iter(skBlob); !iter.done(); iter.next()) {
|
||||
iter.applyFontToPaint(&runPaint); // No need to re-seed the paint.
|
||||
TextRun* run = SkNEW_INSERT_AT_LLIST_TAIL(this, TextRun, (runPaint));
|
||||
TextRun* run = this->addToTail(runPaint);
|
||||
|
||||
const char* text = reinterpret_cast<const char*>(iter.glyphs());
|
||||
size_t byteLength = sizeof(uint16_t) * iter.glyphCount();
|
||||
|
@ -152,11 +152,11 @@ static void TestTLList(skiatest::Reporter* reporter) {
|
||||
list2.reset();
|
||||
|
||||
// use both before/after in-place construction on an empty list
|
||||
SkNEW_INSERT_IN_LLIST_BEFORE(&list2, list2.headIter(), ListElement, (1));
|
||||
list2.addBefore(list2.headIter(), 1);
|
||||
REPORTER_ASSERT(reporter, list2 == list1);
|
||||
list2.reset();
|
||||
|
||||
SkNEW_INSERT_IN_LLIST_AFTER(&list2, list2.tailIter(), ListElement, (1));
|
||||
list2.addAfter(list2.tailIter(), 1);
|
||||
REPORTER_ASSERT(reporter, list2 == list1);
|
||||
|
||||
// add an element to the second list, check that iters are still valid
|
||||
@ -210,7 +210,7 @@ static void TestTLList(skiatest::Reporter* reporter) {
|
||||
// insert either before or after the iterator, then check that the
|
||||
// surrounding sequence is correct.
|
||||
if (2 == insertionMethod) {
|
||||
SkNEW_INSERT_IN_LLIST_BEFORE(&list1, iter, ListElement, (id));
|
||||
list1.addBefore(iter, id);
|
||||
Iter newItem(iter);
|
||||
newItem.prev();
|
||||
REPORTER_ASSERT(reporter, newItem.get()->fID == id);
|
||||
@ -222,7 +222,7 @@ static void TestTLList(skiatest::Reporter* reporter) {
|
||||
REPORTER_ASSERT(reporter, prev.next()->fID == id);
|
||||
}
|
||||
} else {
|
||||
SkNEW_INSERT_IN_LLIST_AFTER(&list1, iter, ListElement, (id));
|
||||
list1.addAfter(iter, id);
|
||||
Iter newItem(iter);
|
||||
newItem.next();
|
||||
REPORTER_ASSERT(reporter, newItem.get()->fID == id);
|
||||
|
Loading…
Reference in New Issue
Block a user