Tab< T > Class Template Reference

Tab< T > Class Template Reference
+ Related help topics:

#include <tab.h>

Class Description

template<class T>
class Tab< T >

Generic container class.

This is a type-safe variable length array class which also supports list-like operations of insertion, appending and deleting. Two instance variables are maintained: nalloc is the number items allocated in the array; count is the number actual used (count<=nalloc). Allocation is performed automatically when Insert or Append operations are performed. It can also be done manually by calling Resize() or Shrink().

Note
Delete does not resize the storage: to do this call Shrink(). If you are going to do a sequence of Appends, its more efficient to first call Resize() to make room for them. Beware of using the Addr() function: it returns a pointer which may be invalid after subsequent Insert(), Append(), Delete(), Resize(), or Shrink() operations.
In 3ds max 1.x, the method SetCount(n) will set the count to n, but will not assure that only n items are allocated. To do that you should call Resize(n). This sets the number allocated. It will also make sure that count<=numAlloc. To make sure that exactly n are allocated and that count = n, call both Resize(n) and SetCount(n). In 3ds max 2.x and later using SetCount() will also effectively call Resize().
This structure is not meant to support more than 2G items; if you need to have more items, consider using an STL container which does not have the 2G barrier and is most likely more optimized than this version.

The implementation minimizes the storage of empty Tables: they are represented by a single NULL pointer. Also, the major part of the code is generic, shared by different Tabs for different types of items.

Tabs may be used on the stack, i.e. they may be declared as a local variable of a function or method. You can set the number of items in the table, work with them, and then when the function returns, the destructor of the Tab is called, and the memory will be deallocated.

Tabs are only appropriate for use with classes that don't allocate memory. For example, Tab<float> is fine while Tab<MSTR> is problematic (MSTR is the class used for strings in 3ds max). In this case, the MSTR class itself allocates memory for the string. It relies on its constructor or destructor to allocate and free the memory. The problem is the Tab class will not call the constructors and destructors for all the items in the table, nor will it call the copy operator. As an example of this, when you assign a string to another string, the MSTR class does not just copy the pointer to the string buffer (which would result in two items pointing to the same block of memory). Rather it will allocate new memory and copy the contents of the source buffer. In this way you have two individual pointers pointing at two individual buffers. When each of the MSTR destructors is called it will free each piece of memory. So, the problem with using a Tab<MSTR> is that when you assign a Tab to another Tab, the Tab copy constructor will copy all the items in the table, but it will not call the copy operator on the individual items. Thus, if you had a Tab<MSTR> and you assigned it to another Tab<MSTR>, you'd have two MSTRs pointing to the same memory. Then when the second one gets deleted it will be trying to double free that memory.

So again, you should only put things in a Tab that don't allocate and deallocate memory in their destructors. Thus, this class should not be used with classes that implement an assignment operator and or destructor because neither are guaranteed to be called. The way around this is to use a table of pointers to the items. For example, instead of Tab<MSTR> use Tab <MSTR *>. As another example, Tab<int> is OK, while Tab<BitArray> would be no good. In the BitArray case one should use class pointers, i.e. Tab<BitArray *>.

All methods of this class are implemented by the system except the compare function used in sorting (see Sort()).

See also
class BitArray, class MaxSDK::Array
+ Inheritance diagram for Tab< T >:

Public Member Functions

 Tab ()
 Default constructor. More...
 
 Tab (const Tab &tb)
 Copy constructor. More...
 
virtual ~Tab ()
 Destructor. More...
 
void Init ()
 Initializes a Tab instance. More...
 
int Count () const
 Retrieves the number of items in the Tab. More...
 
void ZeroCount ()
 Resets the number of used items to zero. More...
 
void SetCount (int n, BOOL resize=TRUE)
 Sets the number of used items. More...
 
T * Addr (const INT_PTR i) const
 Returns the address of the i-th item. More...
 
int Insert (int at, int num, T *el)
 Inserts items in the Tab at a specified position. More...
 
int Append (int num, T *el, int allocExtra=0)
 Appends items at the end of the Tab. More...
 
int Delete (int start, int num)
 Deletes items from the Tab. More...
 
int Resize (int num)
 Changes the number of items allocated in memory. More...
 
void Shrink ()
 Frees unused Tab items to reduce memory footprint. More...
 
void Sort (CompareFnc cmp)
 Sorts the array using the compare function. More...
 
Taboperator= (const Tab &tb)
 Assignment operator. More...
 
T & operator[] (const INT_PTR i) const
 Accesses the i-th Tab item. More...
 

Additional Inherited Members

- Static Public Member Functions inherited from MaxHeapOperators
static UtilExport voidoperator new (size_t size)
 Standard new operator used to allocate objects If there is insufficient memory, an exception will be thrown. More...
 
static UtilExport voidoperator new (size_t size, const std::nothrow_t &e)
 Standard new operator used to allocate objects if there is insufficient memory, NULL will be returned. More...
 
static UtilExport voidoperator new (size_t size, const char *filename, int line)
 New operator used to allocate objects that takes the filename and line number where the new was called If there is insufficient memory, an exception will be thrown. More...
 
static UtilExport voidoperator new (size_t size, int block_type, const char *filename, int line)
 New operator used to allocate objects that takes the type of memory, filename and line number where the new was called If there is insufficient memory, an exception will be thrown. More...
 
static UtilExport voidoperator new (size_t size, const std::nothrow_t &e, const char *filename, int line)
 New operator used to allocate objects that takes the filename and line number where the new was called If there is insufficient memory, NULL will be returned. More...
 
static UtilExport voidoperator new (size_t size, unsigned long flags)
 New operator used to allocate objects that takes extra flags to specify special operations If there is insufficient memory, an exception will be thrown. More...
 
static UtilExport voidoperator new (size_t size, const std::nothrow_t &e, unsigned long flags)
 New operator used to allocate objects that takes extra flags to specify special operations If there is insufficient memory, NULL will be returned. More...
 
static UtilExport voidoperator new[] (size_t size)
 New operator used to allocate arrays of objects If there is insufficient memory, an exception will be thrown. More...
 
static UtilExport voidoperator new[] (size_t size, const std::nothrow_t &e)
 New operator used to allocate arrays of objects If there is insufficient memory, NULL will be returned. More...
 
static UtilExport voidoperator new[] (size_t size, const char *filename, int line)
 New operator used to allocate arrays of objects If there is insufficient memory, an exception will be thrown. More...
 
static UtilExport voidoperator new[] (size_t size, int block_type, const char *filename, int line)
 New operator used to allocate arrays of objects. More...
 
static UtilExport voidoperator new[] (size_t size, const std::nothrow_t &e, const char *filename, int line)
 New operator used to allocate arrays of objects If there is insufficient memory, NULL will be returned. More...
 
static UtilExport voidoperator new[] (size_t size, unsigned long flags)
 New operator used to allocate arrays of objects If there is insufficient memory, an exception will be thrown. More...
 
static UtilExport voidoperator new[] (size_t size, const std::nothrow_t &e, unsigned long flags)
 New operator used to allocate arrays of objects If there is insufficient memory, NULL will be returned. More...
 
static UtilExport void operator delete (void *ptr)
 Standard delete operator used to deallocate an object If the pointer is invalid, an exception will be thrown. More...
 
static UtilExport void operator delete (void *ptr, const std::nothrow_t &e)
 Standard delete operator used to deallocate an object If the pointer is invalid, nothing will happen. More...
 
static UtilExport void operator delete (void *ptr, const char *filename, int line)
 Delete operator used to deallocate an object that takes the filename and line number where the delete was called If the pointer is invalid, an exception will be thrown. More...
 
static UtilExport void operator delete (void *ptr, int block_type, const char *filename, int line)
 Delete operator used to deallocate an object that takes the type of memory, filename and line number where the delete was called If the pointer is invalid, an exception will be thrown. More...
 
static UtilExport void operator delete (void *ptr, const std::nothrow_t &e, const char *filename, int line)
 Delete operator used to deallocate an object that takes the filename and line number where the delete was called If the pointer is invalid, nothing will happen. More...
 
static UtilExport void operator delete (void *ptr, unsigned long flags)
 Delete operator used to deallocate an object that takes extra flags to specify special operations If the pointer is invalid, an exception will be thrown. More...
 
static UtilExport void operator delete (void *ptr, const std::nothrow_t &e, unsigned long flags)
 Delete operator used to deallocate an object that takes extra flags to specify special operations If the pointer is invalid, nothing will happen. More...
 
static UtilExport void operator delete[] (void *ptr)
 Standard delete operator used to deallocate an array of objects If the pointer is invalid, an exception will be thrown. More...
 
static UtilExport void operator delete[] (void *ptr, const std::nothrow_t &e)
 Standard delete operator used to deallocate an array of objects If the pointer is invalid, nothing will happen. More...
 
static UtilExport void operator delete[] (void *ptr, const char *filename, int line)
 Delete operator used to deallocate an array of objects that takes the filename and line number where the delete was called If the pointer is invalid, an exception will be thrown. More...
 
static UtilExport void operator delete[] (void *ptr, int block_type, const char *filename, int line)
 Delete operator used to deallocate an array of objects that takes the type of memory, filename and line number where the delete was called If the pointer is invalid, an exception will be thrown. More...
 
static UtilExport void operator delete[] (void *ptr, const std::nothrow_t &e, const char *filename, int line)
 Delete operator used to deallocate an array of objects that takes the filename and line number where the delete was called If the pointer is invalid, nothing will happen. More...
 
static UtilExport void operator delete[] (void *ptr, unsigned long flags)
 Delete operator used to deallocate an array of objects that takes extra flags to specify special operations If the pointer is invalid, an exception will be thrown. More...
 
static UtilExport void operator delete[] (void *ptr, const std::nothrow_t &e, unsigned long flags)
 Delete operator used to deallocate an array of objects that takes extra flags to specify special operations If the pointer is invalid, an exception will be thrown. More...
 
static UtilExport voidoperator new (size_t size, void *placement_ptr)
 Placement new operator. More...
 
static UtilExport void operator delete (void *ptr, void *placement_ptr)
 Placement delete operator. More...
 
static UtilExport voidaligned_malloc (size_t size, size_t alignment)
 Allocates memory on a specified alignment boundary. More...
 
static UtilExport voidaligned_realloc (void *ptr, size_t size, size_t alignment)
 Reallocates memory on a specified alignment boundary. More...
 
static UtilExport void aligned_free (void *ptr)
 Frees a block of memory that was allocated with aligned_malloc/aligned_realloc. More...
 

Constructor & Destructor Documentation

Tab ( )
inline

Default constructor.

186  : th(NULL)
187  {
189  }
#define NULL
Definition: autoptr.h:18
#define ADSK_MAXSDK_IS_PLAIN_OLD_DATA_TYPE(_Typename)
Definition: PodTypeCheck.h:142
Tab ( const Tab< T > &  tb)
inline

Copy constructor.

Parameters
[in]tbThe Tab that will be copied
194  : th(NULL)
195  {
197  TBCopy((TabHdr**)&th, tb.Count(), (tb.th ? &tb.th->data : NULL), sizeof(T));
198  }
int Count() const
Retrieves the number of items in the Tab.
Definition: tab.h:219
UtilExport int TBCopy(TabHdr **pth, int num, const void *el, int elsize)
#define NULL
Definition: autoptr.h:18
Definition: tab.h:52
#define ADSK_MAXSDK_IS_PLAIN_OLD_DATA_TYPE(_Typename)
Definition: PodTypeCheck.h:142
virtual ~Tab ( )
inlinevirtual

Destructor.

The memory occupied by the Tab's items is freed, but the objects pointed by the items are not.

204  {
205  zfree((void**)&th);
206  }
UtilExport void zfree(void **p)

Member Function Documentation

void Init ( )
inline

Initializes a Tab instance.

Provides a way of initializing a Tab instance outside of its constructor, such as when they are are in-place constructed (constructed in pre-allocated memory).

212  {
213  th = nullptr;
214  }
int Count ( ) const
inline

Retrieves the number of items in the Tab.

Returns
The number of items in use in the Tab
220  {
221  if (th) {
222  return (th->count);
223  }
224  return 0;
225  }
void ZeroCount ( )
inline

Resets the number of used items to zero.

WARNING: Using this method does not free any of the allocated memory stored.

232  {
233  if (th) {
234  th->count = 0;
235  }
236  }
void SetCount ( int  n,
BOOL  resize = TRUE 
)
inline

Sets the number of used items.

Parameters
nThe number of used items to set
resizeIf TRUE, the Tab is resized to n items
242  {
243  TBSetCount((TabHdr **)&th, n, sizeof(T), resize);
244  }
UtilExport void TBSetCount(TabHdr **pth, int n, int elsize, BOOL resize)
Definition: tab.h:52
T* Addr ( const INT_PTR  i) const
inline

Returns the address of the i-th item.

Parameters
iThe index of the item whose address is to be returned. If the index is out of bounds it will throw a MaxSDK::Util::TabOutOfRangeException exception.
Returns
Pointer to the i-th item
Note
This method returns a pointer which may be invalid after subsequent Insert, Append, Delete, Resize, or Shrink operations.
253  {
254  DbgAssert(th);
255  DbgAssert(i >= 0);
256  DbgAssert(th && i < th->count);
257  if (!th || i < 0 || (i >= th->count))
258  {
259  throw MaxSDK::Util::TabOutOfRangeException(_M("Invalid index passed into a Max SDK Tab::Addr(const INT_PTR i)"));
260  }
261  return (&th->data[i]);
262  }
Thrown when an invalid index is passed into Tab::operator[] or Tab::Addr.
Definition: tab.h:91
#define _M(x)
Used to wrap string literals.
Definition: strbasic.h:67
#define DbgAssert(expr)
Definition: assert1.h:72
int Insert ( int  at,
int  num,
T *  el 
)
inline

Inserts items in the Tab at a specified position.

Parameters
atIndex where to insert the items.
numNumber of items to insert
elPointer to the start of an array of items to insert
Returns
If the insertion was successful, returns the value of at.
270  {
271  return (TBInsertAt((TabHdr**)&th, at, num, (void *)el, sizeof(T), 0));
272  }
Definition: tab.h:52
UtilExport int TBInsertAt(TabHdr **pth, int at, int num, const void *el, int elsize, int extra)
int Append ( int  num,
T *  el,
int  allocExtra = 0 
)
inline

Appends items at the end of the Tab.

Parameters
numNumber of items to append
elPointer to the start of an array of items to insert
allocExtraNumber of extra Tab elements to be allocated in order to enlarge the Tab.
Returns
Returns the number of items in use (count of items) prior to appending
281  {
282  return (TBInsertAt((TabHdr**)&th, (th ? th->count : 0), num, (void *)el, sizeof(T), allocExtra));
283  }
Definition: tab.h:52
UtilExport int TBInsertAt(TabHdr **pth, int at, int num, const void *el, int elsize, int extra)
int Delete ( int  start,
int  num 
)
inline

Deletes items from the Tab.

Parameters
startThe index of the item the deletion starts at
numThe number of items to be deleted
Returns
The number of items left in the table
290  {
291  return (TBDelete((TabHdr**)&th, start, num, sizeof(T)));
292  }
Definition: tab.h:52
UtilExport int TBDelete(TabHdr **pth, int starting, int num, int elsize)
int Resize ( int  num)
inline

Changes the number of items allocated in memory.

Resize sets the amount of allocated memory, but doesn't change the actual number of items said to be in the tab So if you know you will want a Tab with 1000 items, you could use Resize to pre-allocate the memory for the 1000 items, and then use Append to add each item without taking a hit on reallocs as the count increases

Parameters
numThe new size (in number of items) of the array
Returns
Nonzero if the array was resized; otherwise 0.
304  {
305  return (TBMakeSize((TabHdr**)&th, num, sizeof(T)));
306  }
Definition: tab.h:52
UtilExport int TBMakeSize(TabHdr **pth, int num, int elsize)
void Shrink ( )
inline

Frees unused Tab items to reduce memory footprint.

309  {
310  TBMakeSize((TabHdr**)&th, (th ? th->count : 0), sizeof(T));
311  }
Definition: tab.h:52
UtilExport int TBMakeSize(TabHdr **pth, int num, int elsize)
void Sort ( CompareFnc  cmp)
inline

Sorts the array using the compare function.

Parameters
cmpPointer to the comparison function to the used by Sort to compare Tab items.
Note
: Sort() uses the C library qsort function. 3rd party developers must implement the CompareFnc function.
typedef int( __cdecl *CompareFnc) (const void *item1, const void *item2);
The return value of CompareFnc is show below: < 0 - if item1 less than item2 0 - if item 1 is identical to item2

0 - if item1 is greater than item2

static int CompTable(const void* item1, const void* item2) {
const MCHAR* a = (const MCHAR*)item1;
const MCHAR* b = (const MCHAR*)item2;
return(_tcscmp(a, b));
}
334  {
335  if (th) {
336  qsort(th->data, th->count, sizeof(T), cmp);
337  }
338  }
Tab& operator= ( const Tab< T > &  tb)
inline

Assignment operator.

Parameters
tbThe Tab to copy the items from
Note
The objects pointed to by the Tab items are not copied, only the Tab items are copied.
Returns
Reference to this Tab
346  {
347  TBCopy((TabHdr**)&th, tb.Count(), (tb.th ? &tb.th->data : NULL), sizeof(T));
348  return *this;
349  }
int Count() const
Retrieves the number of items in the Tab.
Definition: tab.h:219
UtilExport int TBCopy(TabHdr **pth, int num, const void *el, int elsize)
#define NULL
Definition: autoptr.h:18
Definition: tab.h:52
T& operator[] ( const INT_PTR  i) const
inline

Accesses the i-th Tab item.

Parameters
iThe index of the Tab item to access. If the index is out of bounds it will throw a MaxSDK::Util::TabOutOfRangeException exception. The index is bounds checked.
Returns
Reference to the object in the i-th item.
357  {
358  DbgAssert(th);
359  DbgAssert(i >= 0);
360  DbgAssert(th && i < th->count);
361  if (!th || i < 0 || (i >= th->count))
362  {
363  throw MaxSDK::Util::TabOutOfRangeException(_M("Invalid index passed into a Max SDK Tab::operator[]"));
364  }
365 
366  return (th->data[i]);
367  }
Thrown when an invalid index is passed into Tab::operator[] or Tab::Addr.
Definition: tab.h:91
#define _M(x)
Used to wrap string literals.
Definition: strbasic.h:67
#define DbgAssert(expr)
Definition: assert1.h:72