michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: // vim:cindent:ts=4:et:sw=4: michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef SpanningCellSorter_h michael@0: #define SpanningCellSorter_h michael@0: michael@0: /* michael@0: * Code to sort cells by their colspan, used by BasicTableLayoutStrategy. michael@0: */ michael@0: michael@0: #include "pldhash.h" michael@0: #include "nsDebug.h" michael@0: #include "StackArena.h" michael@0: michael@0: class nsIPresShell; michael@0: michael@0: /** michael@0: * The SpanningCellSorter is responsible for accumulating lists of cells michael@0: * with colspans so that those cells can later be enumerated, sorted michael@0: * from lowest number of columns spanned to highest. It does not use a michael@0: * stable sort (in fact, it currently reverses). michael@0: */ michael@0: class MOZ_STACK_CLASS SpanningCellSorter { michael@0: public: michael@0: SpanningCellSorter(); michael@0: ~SpanningCellSorter(); michael@0: michael@0: struct Item { michael@0: int32_t row, col; michael@0: Item *next; michael@0: }; michael@0: michael@0: /** michael@0: * Add a cell to the sorter. Returns false on out of memory. michael@0: * aColSpan is the number of columns spanned, and aRow/aCol are the michael@0: * position of the cell in the table (for GetCellInfoAt). michael@0: */ michael@0: bool AddCell(int32_t aColSpan, int32_t aRow, int32_t aCol); michael@0: michael@0: /** michael@0: * Get the next *list* of cells. Each list contains all the cells michael@0: * for a colspan value, and the lists are given in order from lowest michael@0: * to highest colspan. The colspan value is filled in to *aColSpan. michael@0: */ michael@0: Item* GetNext(int32_t *aColSpan); michael@0: private: michael@0: michael@0: enum State { ADDING, ENUMERATING_ARRAY, ENUMERATING_HASH, DONE }; michael@0: State mState; michael@0: michael@0: // store small colspans in an array for fast sorting and michael@0: // enumeration, and large colspans in a hash table michael@0: michael@0: enum { ARRAY_BASE = 2 }; michael@0: enum { ARRAY_SIZE = 8 }; michael@0: Item *mArray[ARRAY_SIZE]; michael@0: int32_t SpanToIndex(int32_t aSpan) { return aSpan - ARRAY_BASE; } michael@0: int32_t IndexToSpan(int32_t aIndex) { return aIndex + ARRAY_BASE; } michael@0: bool UseArrayForSpan(int32_t aSpan) { michael@0: NS_ASSERTION(SpanToIndex(aSpan) >= 0, "cell without colspan"); michael@0: return SpanToIndex(aSpan) < ARRAY_SIZE; michael@0: } michael@0: michael@0: PLDHashTable mHashTable; michael@0: struct HashTableEntry : public PLDHashEntryHdr { michael@0: int32_t mColSpan; michael@0: Item *mItems; michael@0: }; michael@0: michael@0: static const PLDHashTableOps HashTableOps; michael@0: michael@0: static PLDHashNumber michael@0: HashTableHashKey(PLDHashTable *table, const void *key); michael@0: static bool michael@0: HashTableMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr, michael@0: const void *key); michael@0: michael@0: static PLDHashOperator michael@0: FillSortedArray(PLDHashTable *table, PLDHashEntryHdr *hdr, michael@0: uint32_t number, void *arg); michael@0: michael@0: static int SortArray(const void *a, const void *b, void *closure); michael@0: michael@0: /* state used only during enumeration */ michael@0: uint32_t mEnumerationIndex; // into mArray or mSortedHashTable michael@0: HashTableEntry **mSortedHashTable; michael@0: michael@0: /* michael@0: * operator new is forbidden since we use the pres shell's stack michael@0: * memory, which much be pushed and popped at points matching a michael@0: * push/pop on the C++ stack. michael@0: */ michael@0: void* operator new(size_t sz) CPP_THROW_NEW { return nullptr; } michael@0: }; michael@0: michael@0: #endif