Backout a74bd5095902, Bug 959405 - Please update the Buri Moz-central, 1.3, 1.2 with...
[gecko.git] / layout / tables / SpanningCellSorter.cpp
blobacb2cee2505bb6dc02f9769ac166f1a6ded898d7
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/. */
7 /*
8 * Code to sort cells by their colspan, used by BasicTableLayoutStrategy.
9 */
11 #include "SpanningCellSorter.h"
12 #include "nsQuickSort.h"
13 #include "nsIPresShell.h"
15 //#define DEBUG_SPANNING_CELL_SORTER
17 SpanningCellSorter::SpanningCellSorter()
18 : mState(ADDING)
19 , mSortedHashTable(nullptr)
21 memset(mArray, 0, sizeof(mArray));
22 mHashTable.entryCount = 0;
25 SpanningCellSorter::~SpanningCellSorter()
27 if (mHashTable.entryCount) {
28 PL_DHashTableFinish(&mHashTable);
29 mHashTable.entryCount = 0;
31 delete [] mSortedHashTable;
34 /* static */ const PLDHashTableOps
35 SpanningCellSorter::HashTableOps = {
36 PL_DHashAllocTable,
37 PL_DHashFreeTable,
38 HashTableHashKey,
39 HashTableMatchEntry,
40 PL_DHashMoveEntryStub,
41 PL_DHashClearEntryStub,
42 PL_DHashFinalizeStub,
43 nullptr
46 /* static */ PLDHashNumber
47 SpanningCellSorter::HashTableHashKey(PLDHashTable *table, const void *key)
49 return NS_PTR_TO_INT32(key);
52 /* static */ bool
53 SpanningCellSorter::HashTableMatchEntry(PLDHashTable *table,
54 const PLDHashEntryHdr *hdr,
55 const void *key)
57 const HashTableEntry *entry = static_cast<const HashTableEntry*>(hdr);
58 return NS_PTR_TO_INT32(key) == entry->mColSpan;
61 bool
62 SpanningCellSorter::AddCell(int32_t aColSpan, int32_t aRow, int32_t aCol)
64 NS_ASSERTION(mState == ADDING, "cannot call AddCell after GetNext");
65 NS_ASSERTION(aColSpan >= ARRAY_BASE, "cannot add cells with colspan<2");
67 Item *i = (Item*) mozilla::AutoStackArena::Allocate(sizeof(Item));
68 NS_ENSURE_TRUE(i != nullptr, false);
70 i->row = aRow;
71 i->col = aCol;
73 if (UseArrayForSpan(aColSpan)) {
74 int32_t index = SpanToIndex(aColSpan);
75 i->next = mArray[index];
76 mArray[index] = i;
77 } else {
78 if (!mHashTable.entryCount &&
79 !PL_DHashTableInit(&mHashTable, &HashTableOps, nullptr,
80 sizeof(HashTableEntry), PL_DHASH_MIN_SIZE)) {
81 NS_NOTREACHED("table init failed");
82 mHashTable.entryCount = 0;
83 return false;
85 HashTableEntry *entry = static_cast<HashTableEntry*>
86 (PL_DHashTableOperate(&mHashTable, NS_INT32_TO_PTR(aColSpan),
87 PL_DHASH_ADD));
88 NS_ENSURE_TRUE(entry, false);
90 NS_ASSERTION(entry->mColSpan == 0 || entry->mColSpan == aColSpan,
91 "wrong entry");
92 NS_ASSERTION((entry->mColSpan == 0) == (entry->mItems == nullptr),
93 "entry should be either new or properly initialized");
94 entry->mColSpan = aColSpan;
96 i->next = entry->mItems;
97 entry->mItems = i;
100 return true;
103 /* static */ PLDHashOperator
104 SpanningCellSorter::FillSortedArray(PLDHashTable *table, PLDHashEntryHdr *hdr,
105 uint32_t number, void *arg)
107 HashTableEntry *entry = static_cast<HashTableEntry*>(hdr);
108 HashTableEntry **sh = static_cast<HashTableEntry**>(arg);
110 sh[number] = entry;
112 return PL_DHASH_NEXT;
115 /* static */ int
116 SpanningCellSorter::SortArray(const void *a, const void *b, void *closure)
118 int32_t spanA = (*static_cast<HashTableEntry*const*>(a))->mColSpan;
119 int32_t spanB = (*static_cast<HashTableEntry*const*>(b))->mColSpan;
121 if (spanA < spanB)
122 return -1;
123 if (spanA == spanB)
124 return 0;
125 return 1;
128 SpanningCellSorter::Item*
129 SpanningCellSorter::GetNext(int32_t *aColSpan)
131 NS_ASSERTION(mState != DONE, "done enumerating, stop calling");
133 switch (mState) {
134 case ADDING:
135 /* prepare to enumerate the array */
136 mState = ENUMERATING_ARRAY;
137 mEnumerationIndex = 0;
138 /* fall through */
139 case ENUMERATING_ARRAY:
140 while (mEnumerationIndex < ARRAY_SIZE && !mArray[mEnumerationIndex])
141 ++mEnumerationIndex;
142 if (mEnumerationIndex < ARRAY_SIZE) {
143 Item *result = mArray[mEnumerationIndex];
144 *aColSpan = IndexToSpan(mEnumerationIndex);
145 NS_ASSERTION(result, "logic error");
146 #ifdef DEBUG_SPANNING_CELL_SORTER
147 printf("SpanningCellSorter[%p]:"
148 " returning list for colspan=%d from array\n",
149 static_cast<void*>(this), *aColSpan);
150 #endif
151 ++mEnumerationIndex;
152 return result;
154 /* prepare to enumerate the hash */
155 mState = ENUMERATING_HASH;
156 mEnumerationIndex = 0;
157 if (mHashTable.entryCount) {
158 HashTableEntry **sh =
159 new HashTableEntry*[mHashTable.entryCount];
160 if (!sh) {
161 // give up
162 mState = DONE;
163 return nullptr;
165 PL_DHashTableEnumerate(&mHashTable, FillSortedArray, sh);
166 NS_QuickSort(sh, mHashTable.entryCount, sizeof(sh[0]),
167 SortArray, nullptr);
168 mSortedHashTable = sh;
170 /* fall through */
171 case ENUMERATING_HASH:
172 if (mEnumerationIndex < mHashTable.entryCount) {
173 Item *result = mSortedHashTable[mEnumerationIndex]->mItems;
174 *aColSpan = mSortedHashTable[mEnumerationIndex]->mColSpan;
175 NS_ASSERTION(result, "holes in hash table");
176 #ifdef DEBUG_SPANNING_CELL_SORTER
177 printf("SpanningCellSorter[%p]:"
178 " returning list for colspan=%d from hash\n",
179 static_cast<void*>(this), *aColSpan);
180 #endif
181 ++mEnumerationIndex;
182 return result;
184 mState = DONE;
185 /* fall through */
186 case DONE:
189 return nullptr;