3ds Max C++ API Reference
Loading...
Searching...
No Matches
Tab< T > Class Template Reference

Generic container class. More...

#include <C:/adskgit/3dsmax/3dsmax/3dswin/src/maxsdk/include/tab.h>

Inheritance diagram for Tab< T >:

Public Member Functions

 Tab ()=default
 Default constructor.
 Tab (const Tab &tb)
 Copy constructor.
 Tab (Tab &&tb) noexcept
 Move constructor.
virtual ~Tab ()
 Destructor.
void Init ()
 Initializes a Tab instance.
int Count () const
 Retrieves the number of items in the Tab.
constexpr size_t size () const noexcept
 Retrieves the number of items in the Tab. Standard compliant.
void ZeroCount ()
 Resets the number of used items to zero.
void SetCount (int n, BOOL resize=TRUE)
 Sets the number of used items.
T * Addr (const INT_PTR i) const
 Returns the address of the i-th item.
constexpr T * data () noexcept
 Returns a pointer to the data buffer of tab. Standard compliant.
constexpr const T * data () const noexcept
 Returns a const pointer to the data buffer of tab. Standard compliant.
int Insert (int at, int num, T *el)
 Inserts items in the Tab at a specified position.
int Append (int num, T *el, int allocExtra=0)
 Appends items at the end of the Tab.
int Append (const T &el, int allocExtra=0)
 Appends a single item at the end of the Tab.
int Delete (int start, int num)
 Deletes items from the Tab.
int Resize (int num)
 Changes the number of items allocated in memory.
void Shrink ()
 Frees unused Tab items to reduce memory footprint.
void Sort (CompareFnc cmp)
 Sorts the array using the compare function.
Taboperator= (const Tab &tb)
 Copy assignment operator.
Taboperator= (Tab &&tb)
 Move assignment operator.
T & operator[] (const INT_PTR i) const
 Accesses the i-th Tab item.
const T * begin () const
 Accesses the begin iterator, which is a plain pointer in this case.
T * begin ()
const T * end () const
 Accesses the end iterator (one past last valid element). Do not dereference.
T * end ()

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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
static UtilExport voidoperator new[] (size_t size, int block_type, const char *filename, int line)
 New operator used to allocate arrays of objects.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
static UtilExport voidoperator new (size_t size, void *placement_ptr)
 Placement new operator.
static UtilExport void operator delete (void *ptr, void *placement_ptr)
 Placement delete operator.
static UtilExport voidaligned_malloc (size_t size, size_t alignment)
 Allocates memory on a specified alignment boundary.
static UtilExport voidaligned_realloc (void *ptr, size_t size, size_t alignment)
 Reallocates memory on a specified alignment boundary.
static UtilExport void aligned_free (void *ptr)
 Frees a block of memory that was allocated with aligned_malloc/aligned_realloc.

Detailed 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 are trivially copyable and trivially destructible. Define MAXSDK_ENABLE_STRICT_TAB to check these requirements at compile time. 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

Constructor & Destructor Documentation

◆ Tab() [1/3]

template<class T>
Tab ( )
default

Default constructor.

◆ Tab() [2/3]

template<class T>
Tab ( const Tab< T > & tb)
inline

Copy constructor.

Parameters
[in]tbThe Tab that will be copied
200 {
201 this->operator=(tb);
202 }
Generic container class.
Definition tab.h:178
Tab & operator=(const Tab &tb)
Copy assignment operator.
Definition tab.h:407

◆ Tab() [3/3]

template<class T>
Tab ( Tab< T > && tb)
inlinenoexcept

Move constructor.

Parameters
[in]tbThe Tab that will be moved from
Note
tb is empty after this operation
208 {
209 th = tb.th;
210 tb.th = nullptr;
211 }

◆ ~Tab()

template<class T>
virtual ~Tab ( )
inlinevirtual

Destructor.

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

217 {
218 MaxSDK::TabImpl::zfree((void**)&th);
219 }
UtilExport void zfree(void **p)

Member Function Documentation

◆ Init()

template<class T>
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).

225 {
226 th = nullptr;
227 }

◆ Count()

template<class T>
int Count ( ) const
inline

Retrieves the number of items in the Tab.

Returns
The number of items in use in the Tab
233 {
234 if (th) {
235 return th->count;
236 }
237 return 0;
238 }

◆ size()

template<class T>
size_t size ( ) const
inlineconstexprnoexcept

Retrieves the number of items in the Tab. Standard compliant.

Returns
The number of items in the tab.
244 {
245 if (th == nullptr)
246 return 0;
247
248 return size_t(th->count);
249 }
MAXMEM_EXTERN_C UtilExport size_t(__cdecl *MAX_msize)(void *memblock)

◆ ZeroCount()

template<class T>
void ZeroCount ( )
inline

Resets the number of used items to zero.

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

256 {
257 if (th) {
258 th->count = 0;
259 }
260 }

◆ SetCount()

template<class T>
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
267 {
269 }
UtilExport void TBSetCount(TabHdr **pth, int n, int elsize, BOOL resize)

◆ Addr()

template<class T>
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.
278 {
279 DbgAssert(th);
280 DbgAssert(i >= 0);
282 if (!th || i < 0 || (i >= th->count))
283 {
284 throw MaxSDK::Util::TabOutOfRangeException(_M("Invalid index passed into a Max SDK Tab::Addr(const INT_PTR i)"));
285 }
286 return &th->data[i];
287 }
#define DbgAssert(expr)
Definition assert1.h:83
#define _M(x)
Used to wrap string literals.
Definition strbasic.h:67

◆ data() [1/2]

template<class T>
T * data ( )
inlineconstexprnoexcept

Returns a pointer to the data buffer of tab. Standard compliant.

Returns
A pointer to the tab data buffer.
293 {
294 if (th == nullptr)
295 return nullptr;
296
297 return th->data;
298 }

◆ data() [2/2]

template<class T>
const T * data ( ) const
inlineconstexprnoexcept

Returns a const pointer to the data buffer of tab. Standard compliant.

Returns
A const pointer to the tab data buffer.
303 {
304 if (th == nullptr)
305 return nullptr;
306
307 return th->data;
308 }

◆ Insert()

template<class T>
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.
317 {
318 return InsertImpl(at, num, el, 0);
319 }

◆ Append() [1/2]

template<class T>
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
329 {
330 return InsertImpl(Count(), num, el, allocExtra);
331 }
int Count() const
Retrieves the number of items in the Tab.
Definition tab.h:232

◆ Append() [2/2]

template<class T>
int Append ( const T & el,
int allocExtra = 0 )
inline

Appends a single item at the end of the Tab.

Parameters
elitem 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
338 {
339 return InsertImpl(Count(), 1, &el, allocExtra);
340 }

◆ Delete()

template<class T>
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
Note
This doesn't free any allocated memory. If there are any existing items after start + num, these items are moved using memmove.
Returns
The number of items left in the table
350 {
352 }
UtilExport int TBDelete(TabHdr **pth, int starting, int num, int elsize)

◆ Resize()

template<class T>
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.
365 {
367 }
UtilExport int TBMakeSize(TabHdr **pth, int num, int elsize)

◆ Shrink()

template<class T>
void Shrink ( )
inline

Frees unused Tab items to reduce memory footprint.

370 {
371 Resize(Count());
372 }
int Resize(int num)
Changes the number of items allocated in memory.
Definition tab.h:364

◆ Sort()

template<class T>
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. qsort should only be used with trivially copyable types. 3rd party developers must implement the CompareFnc function.
typedef int( __cdecl *CompareFnc) (const void *item1, const void *item2);
MAXMEM_EXTERN_C UtilExport int(__cdecl *MAX_heapchk)(void)
int(* CompareFnc)(const void *elem1, const void *elem2)
Definition tab.h:107
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));
}
#define MCHAR
MBCS/Unicode helper defines std::wofstream doesn't mix well with Unicode.
Definition strbasic.h:42
395 {
396 if (th) {
397 qsort(th->data, th->count, sizeof(T), cmp);
398 }
399 }

◆ operator=() [1/2]

template<class T>
Tab & operator= ( const Tab< T > & tb)
inline

Copy 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
408 {
409 if (this != &tb)
410 {
412 }
413 return *this;
414 }
const T * begin() const
Accesses the begin iterator, which is a plain pointer in this case.
Definition tab.h:450
UtilExport int TBCopy(TabHdr **pth, int num, const void *el, int elsize)

◆ operator=() [2/2]

template<class T>
Tab & operator= ( Tab< T > && tb)
inline

Move assignment operator.

Parameters
tbThe Tab to move the items from
Note
tb is empty after this operation
Returns
Reference to this Tab
421 {
422 if (this != &tb)
423 {
424 MaxSDK::TabImpl::zfree((void**)&th);
425 th = tb.th;
426 tb.th = nullptr;
427 }
428 return *this;
429 }

◆ operator[]()

template<class T>
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.
437 {
438 DbgAssert(th);
439 DbgAssert(i >= 0);
441 if (!th || i < 0 || (i >= th->count))
442 {
443 throw MaxSDK::Util::TabOutOfRangeException(_M("Invalid index passed into a Max SDK Tab::operator[]"));
444 }
445
446 return th->data[i];
447 }

◆ begin() [1/2]

template<class T>
const T * begin ( ) const
inline

Accesses the begin iterator, which is a plain pointer in this case.

450 {
451 if (th == nullptr)
452 return nullptr;
453
454 return th->data;
455 }

◆ begin() [2/2]

template<class T>
T * begin ( )
inline
456 {
457 if (th == nullptr)
458 return nullptr;
459
460 return th->data;
461 }

◆ end() [1/2]

template<class T>
const T * end ( ) const
inline

Accesses the end iterator (one past last valid element). Do not dereference.

464 {
465 if (th == nullptr)
466 return nullptr;
467
468 return th->data + th->count;
469 }

◆ end() [2/2]

template<class T>
T * end ( )
inline
470 {
471 if (th == nullptr)
472 return nullptr;
473
474 return th->data + th->count;
475 }