📄 hashtable.c
字号:
//-------------------------------------------------------------------------------------------------
// National Instruments - LabWindows/CVI
// New for version 8.5
//
// This example demonstrates how to use the Hash Table API found in the Programmer's Toolbox.
// It allows you to create hash tables with various key and value types. As you add/remove
// key-value pairs, you can monitor the table size, load, and item distribution throughout the
// buckets. An intensity graph provides a visual indicator of how the hash function distributes
// the keys throughout the buckets. You can also see how the resize policy affects the table's
// size and load as elements are added or removed.
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
// Include files
//-------------------------------------------------------------------------------------------------
#include <cvirte.h>
#include <userint.h>
#include <toolbox.h>
#include "hashtable.h"
//-------------------------------------------------------------------------------------------------
// Macros
//-------------------------------------------------------------------------------------------------
#ifdef errChk
#undef errChk
#endif
#define errChk(fCall) do { if ((error = (fCall)) < 0) goto Error; } while (0)
#define handleError do { if (error < 0 && error != kErrorAlreadyHandled) { MessagePopup("Error", GetGeneralErrorString(error)); error = kErrorAlreadyHandled; } } while (0)
//-------------------------------------------------------------------------------------------------
// Constants
//-------------------------------------------------------------------------------------------------
static const unsigned int kExpectedOccupancy = 10;
static const int kErrorAlreadyHandled = UIEErrorLimit - 1;
//-------------------------------------------------------------------------------------------------
// Global variables
//-------------------------------------------------------------------------------------------------
static int gPanel;
static HashTableType gHashTable = NULL;
static int gKeyType,
gValType,
gKeySize,
gValSize;
static ColorMapEntry gColorMap[2];
//-------------------------------------------------------------------------------------------------
// Forward declarations
//-------------------------------------------------------------------------------------------------
static int SetKeyAndValueGlobals(void);
static int UpdateDistributionGraph(void);
static int UpdateCtrlDimming(void);
static int UpdateCtrlsAccordingToTableDefaults(void);
static int UpdateCtrlsAccordingToKeyValueTypes(void);
static int GetKeyFromCtrl(void **key);
static int GetValueFromCtrl(void **val);
//-------------------------------------------------------------------------------------------------
// Module entry-point
//-------------------------------------------------------------------------------------------------
int main (int argc, char *argv[])
{
if (InitCVIRTE (0, argv, 0) == 0)
return -1; /* out of memory */
if ((gPanel = LoadPanel (0, "hashtable.uir", PANEL)) < 0)
return -1;
DisplayPanel (gPanel);
RunUserInterface ();
DiscardPanel (gPanel);
return 0;
}
/// HIFN Callback function for the "Create" button
int CVICALLBACK CreateTable (int gPanel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
int error = 0;
switch (event)
{
case EVENT_COMMIT:
errChk (SetKeyAndValueGlobals());
errChk (HashTableCreate(kExpectedOccupancy,
(gKeyType == VAL_STRING) ? C_STRING_KEY : FIXED_SIZE_KEY,
gKeySize,
gValSize,
&gHashTable));
errChk (UpdateCtrlsAccordingToTableDefaults());
errChk (UpdateCtrlsAccordingToKeyValueTypes());
errChk (UpdateCtrlDimming());
break;
}
Error:
handleError;
return 0;
}
/// HIFN Callback function for the "Dispose" button
int CVICALLBACK DisposeTable (int gPanel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
int error = 0;
switch (event)
{
case EVENT_COMMIT:
errChk (HashTableDispose(gHashTable));
gHashTable = NULL;
errChk (UpdateCtrlDimming());
break;
}
Error:
handleError;
return 0;
}
/// HIFN Callback function for the "Insert" button
int CVICALLBACK Insert (int gPanel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
int error = 0;
void *key = NULL,
*value = NULL;
unsigned int size,
buckets;
double load;
switch (event)
{
case EVENT_COMMIT:
errChk (GetKeyFromCtrl(&key));
errChk (GetValueFromCtrl(&value));
errChk (HashTableInsertItem(gHashTable, key, value));
errChk (HashTableGetAttribute(gHashTable, ATTR_HT_SIZE, &size));
errChk (HashTableGetAttribute(gHashTable, ATTR_HT_NUM_BUCKETS, &buckets));
errChk (HashTableGetAttribute(gHashTable, ATTR_HT_LOAD, &load));
errChk (SetCtrlVal(gPanel, PANEL_SIZE, size));
errChk (SetCtrlVal(gPanel, PANEL_BUCKETS, buckets));
errChk (SetCtrlVal(gPanel, PANEL_LOAD, load));
errChk (UpdateDistributionGraph());
break;
}
Error:
if (key)
free(key);
if (value)
free(value);
handleError;
return 0;
}
/// HIFN Callback function for the "Remove" button
int CVICALLBACK Remove (int gPanel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
int error = 0;
void *key = NULL;
unsigned int size,
buckets;
double load;
switch (event)
{
case EVENT_COMMIT:
errChk (GetKeyFromCtrl(&key));
errChk (HashTableRemoveItem(gHashTable, key, NULL, 0));
errChk (HashTableGetAttribute(gHashTable, ATTR_HT_SIZE, &size));
errChk (HashTableGetAttribute(gHashTable, ATTR_HT_NUM_BUCKETS, &buckets));
errChk (HashTableGetAttribute(gHashTable, ATTR_HT_LOAD, &load));
errChk (SetCtrlVal(gPanel, PANEL_SIZE, size));
errChk (SetCtrlVal(gPanel, PANEL_BUCKETS, buckets));
errChk (SetCtrlVal(gPanel, PANEL_LOAD, load));
errChk (UpdateDistributionGraph());
break;
}
Error:
if (key)
free(key);
handleError;
return 0;
}
/// HIFN Callback function for the "Find" button
int CVICALLBACK Find (int gPanel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
int error = 0,
found;
void *key = NULL;
switch (event)
{
case EVENT_COMMIT:
errChk (GetKeyFromCtrl(&key));
errChk (HashTableFindItem(gHashTable, key, &found));
MessagePopup("Find Key", found ? "Found" : "Not Found");
break;
}
Error:
if (key)
free(key);
handleError;
return 0;
}
/// HIFN Callback function for the "Enumerate Table Contents" button
int CVICALLBACK Enumerate (int gPanel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
int error = 0;
HashTableIterator iter;
void *key = NULL,
*value = NULL;
char *stringKey = NULL,
numericKey[8];
unsigned int i,
size;
switch (event)
{
case EVENT_COMMIT:
// Hide the control to unnecessary draws and flickering
errChk (SetCtrlAttribute(gPanel, PANEL_ENUM_TABLE, ATTR_VISIBLE, 0));
errChk (DeleteTableRows(gPanel, PANEL_ENUM_TABLE, 1, -1));
errChk (HashTableGetAttribute(gHashTable, ATTR_HT_SIZE, &size));
errChk (InsertTableRows(gPanel, PANEL_ENUM_TABLE, -1, size, VAL_USE_MASTER_CELL_TYPE));
if (gKeyType != VAL_STRING)
{
nullChk (key = malloc(gKeySize));
size = gKeySize;
}
nullChk (value = malloc(gValSize));
for (error = HashTableIteratorCreate(gHashTable, &iter), i = 1;
error >= 0 && error != HASH_TABLE_END;
error = HashTableIteratorAdvance(gHashTable, iter), ++i)
{
if (gKeyType == VAL_STRING)
{
if (key)
free(key);
errChk (size = HashTableIteratorGetItem(gHashTable, iter, NULL, 0, NULL, 0));
nullChk (key = malloc(size));
}
errChk (HashTableIteratorGetItem(gHashTable, iter, key, size, value, gValSize));
switch (gKeyType)
{
case VAL_STRING:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(1, i), ATTR_CTRL_VAL, (char *)key));
break;
case VAL_CHAR:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(1, i), ATTR_CTRL_VAL, *(char *)key));
break;
case VAL_UNSIGNED_CHAR:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(1, i), ATTR_CTRL_VAL, *(unsigned char *)key));
break;
case VAL_INTEGER:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(1, i), ATTR_CTRL_VAL, *(int *)key));
break;
case VAL_UNSIGNED_INTEGER:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(1, i), ATTR_CTRL_VAL, *(unsigned int *)key));
break;
case VAL_64BIT_INTEGER:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(1, i), ATTR_CTRL_VAL, *(__int64 *)key));
break;
case VAL_UNSIGNED_64BIT_INTEGER:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(1, i), ATTR_CTRL_VAL, *(unsigned __int64 *)key));
break;
case VAL_FLOAT:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(1, i), ATTR_CTRL_VAL, *(float *)key));
break;
case VAL_DOUBLE:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(1, i), ATTR_CTRL_VAL, *(double *)key));
break;
}
switch (gValType)
{
case VAL_STRING:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(2, i), ATTR_CTRL_VAL, (char *)value));
break;
case VAL_CHAR:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(2, i), ATTR_CTRL_VAL, *(char *)value));
break;
case VAL_UNSIGNED_CHAR:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(2, i), ATTR_CTRL_VAL, *(unsigned char *)value));
break;
case VAL_INTEGER:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(2, i), ATTR_CTRL_VAL, *(int *)value));
break;
case VAL_UNSIGNED_INTEGER:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(2, i), ATTR_CTRL_VAL, *(unsigned int *)value));
break;
case VAL_64BIT_INTEGER:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(2, i), ATTR_CTRL_VAL, *(__int64 *)value));
break;
case VAL_UNSIGNED_64BIT_INTEGER:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(2, i), ATTR_CTRL_VAL, *(unsigned __int64 *)value));
break;
case VAL_FLOAT:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(2, i), ATTR_CTRL_VAL, *(float *)value));
break;
case VAL_DOUBLE:
errChk (SetTableCellAttribute(gPanel, PANEL_ENUM_TABLE, MakePoint(2, i), ATTR_CTRL_VAL, *(double *)value));
break;
}
}
HashTableIteratorDispose(gHashTable, iter);
break;
}
Error:
if (event == EVENT_COMMIT)
SetCtrlAttribute(gPanel, PANEL_ENUM_TABLE, ATTR_VISIBLE, 1);
handleError;
return 0;
}
/// HIFN Callback function for the grow policy checkbox
int CVICALLBACK ToggleGrowLoad (int gPanel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
int error = 0,
enable;
double load;
switch (event)
{
case EVENT_COMMIT:
errChk (GetCtrlVal(gPanel, PANEL_GROW_ENABLE, &enable));
if (enable)
{
errChk (GetCtrlVal(gPanel, PANEL_GROW_LOAD, &load));
}
else
{
load = VAL_DO_NOT_GROW;
}
errChk (HashTableSetAttribute(gHashTable, ATTR_HT_GROW_LOAD, load));
errChk (SetCtrlAttribute(gPanel, PANEL_GROW_LOAD, ATTR_DIMMED, !enable));
errChk (UpdateDistributionGraph());
break;
}
Error:
handleError;
return 0;
}
/// HIFN Callback function for the shrink policy checkbox
int CVICALLBACK ToggleShrinkLoad (int gPanel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
int error = 0,
enable;
double load;
switch (event)
{
case EVENT_COMMIT:
errChk (GetCtrlVal(gPanel, PANEL_SHRINK_ENABLE, &enable));
if (enable)
{
errChk (GetCtrlVal(gPanel, PANEL_SHRINK_LOAD, &load));
}
else
{
load = VAL_DO_NOT_SHRINK;
}
errChk (HashTableSetAttribute(gHashTable, ATTR_HT_SHRINK_LOAD, load));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -