|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 // vim:cindent:ts=4:et:sw=4: |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifndef SpanningCellSorter_h |
|
8 #define SpanningCellSorter_h |
|
9 |
|
10 /* |
|
11 * Code to sort cells by their colspan, used by BasicTableLayoutStrategy. |
|
12 */ |
|
13 |
|
14 #include "pldhash.h" |
|
15 #include "nsDebug.h" |
|
16 #include "StackArena.h" |
|
17 |
|
18 class nsIPresShell; |
|
19 |
|
20 /** |
|
21 * The SpanningCellSorter is responsible for accumulating lists of cells |
|
22 * with colspans so that those cells can later be enumerated, sorted |
|
23 * from lowest number of columns spanned to highest. It does not use a |
|
24 * stable sort (in fact, it currently reverses). |
|
25 */ |
|
26 class MOZ_STACK_CLASS SpanningCellSorter { |
|
27 public: |
|
28 SpanningCellSorter(); |
|
29 ~SpanningCellSorter(); |
|
30 |
|
31 struct Item { |
|
32 int32_t row, col; |
|
33 Item *next; |
|
34 }; |
|
35 |
|
36 /** |
|
37 * Add a cell to the sorter. Returns false on out of memory. |
|
38 * aColSpan is the number of columns spanned, and aRow/aCol are the |
|
39 * position of the cell in the table (for GetCellInfoAt). |
|
40 */ |
|
41 bool AddCell(int32_t aColSpan, int32_t aRow, int32_t aCol); |
|
42 |
|
43 /** |
|
44 * Get the next *list* of cells. Each list contains all the cells |
|
45 * for a colspan value, and the lists are given in order from lowest |
|
46 * to highest colspan. The colspan value is filled in to *aColSpan. |
|
47 */ |
|
48 Item* GetNext(int32_t *aColSpan); |
|
49 private: |
|
50 |
|
51 enum State { ADDING, ENUMERATING_ARRAY, ENUMERATING_HASH, DONE }; |
|
52 State mState; |
|
53 |
|
54 // store small colspans in an array for fast sorting and |
|
55 // enumeration, and large colspans in a hash table |
|
56 |
|
57 enum { ARRAY_BASE = 2 }; |
|
58 enum { ARRAY_SIZE = 8 }; |
|
59 Item *mArray[ARRAY_SIZE]; |
|
60 int32_t SpanToIndex(int32_t aSpan) { return aSpan - ARRAY_BASE; } |
|
61 int32_t IndexToSpan(int32_t aIndex) { return aIndex + ARRAY_BASE; } |
|
62 bool UseArrayForSpan(int32_t aSpan) { |
|
63 NS_ASSERTION(SpanToIndex(aSpan) >= 0, "cell without colspan"); |
|
64 return SpanToIndex(aSpan) < ARRAY_SIZE; |
|
65 } |
|
66 |
|
67 PLDHashTable mHashTable; |
|
68 struct HashTableEntry : public PLDHashEntryHdr { |
|
69 int32_t mColSpan; |
|
70 Item *mItems; |
|
71 }; |
|
72 |
|
73 static const PLDHashTableOps HashTableOps; |
|
74 |
|
75 static PLDHashNumber |
|
76 HashTableHashKey(PLDHashTable *table, const void *key); |
|
77 static bool |
|
78 HashTableMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr, |
|
79 const void *key); |
|
80 |
|
81 static PLDHashOperator |
|
82 FillSortedArray(PLDHashTable *table, PLDHashEntryHdr *hdr, |
|
83 uint32_t number, void *arg); |
|
84 |
|
85 static int SortArray(const void *a, const void *b, void *closure); |
|
86 |
|
87 /* state used only during enumeration */ |
|
88 uint32_t mEnumerationIndex; // into mArray or mSortedHashTable |
|
89 HashTableEntry **mSortedHashTable; |
|
90 |
|
91 /* |
|
92 * operator new is forbidden since we use the pres shell's stack |
|
93 * memory, which much be pushed and popped at points matching a |
|
94 * push/pop on the C++ stack. |
|
95 */ |
|
96 void* operator new(size_t sz) CPP_THROW_NEW { return nullptr; } |
|
97 }; |
|
98 |
|
99 #endif |