summaryrefslogtreecommitdiff
path: root/src/im_attrib.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/im_attrib.cpp')
-rw-r--r--src/im_attrib.cpp316
1 files changed, 316 insertions, 0 deletions
diff --git a/src/im_attrib.cpp b/src/im_attrib.cpp
new file mode 100644
index 0000000..a1b95b7
--- /dev/null
+++ b/src/im_attrib.cpp
@@ -0,0 +1,316 @@
+/** \file
+ * \brief Attributes Table
+ *
+ * See Copyright Notice in im_lib.h
+ * $Id: im_attrib.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $
+ */
+
+#include <stdlib.h>
+#include <memory.h>
+#include <string.h>
+#include <assert.h>
+
+#include "im_attrib.h"
+#include "im_util.h"
+
+#define IM_DEFAULTSIZE 101
+#define IM_MULTIPLIER 31
+
+// Unique Hash index for a name
+static int iHashIndex(const char *name, int hash_size)
+{
+ unsigned short hash = 0;
+ const unsigned char *p_name = (const unsigned char*)name;
+
+ for(; *p_name; p_name++)
+ hash = hash*IM_MULTIPLIER + *p_name;
+
+ return hash % hash_size;
+}
+
+
+/*******************************************************************/
+
+
+class imAttribNode
+{
+public:
+ int data_type;
+ int count;
+ void* data;
+ char* name;
+
+ imAttribNode* next;
+
+ imAttribNode(const char* name, int _data_type, int _count, const void* _data, imAttribNode* next);
+ ~imAttribNode();
+};
+
+static char* utlStrDup(const char* str)
+{
+ int size;
+ char* new_str;
+
+ assert(str);
+
+ size = strlen(str) + 1;
+ new_str = (char*)malloc(size);
+ memcpy(new_str, str, size);
+
+ return new_str;
+}
+
+imAttribNode::imAttribNode(const char* name, int _data_type, int _count, const void* _data, imAttribNode* _next)
+{
+ this->name = utlStrDup(name);
+ this->data_type = _data_type;
+ this->count = _count;
+ this->next = _next;
+
+ int size = count * imDataTypeSize(_data_type);
+ this->data = malloc(size);
+ if (_data) memcpy(this->data, _data, size);
+ else memset(this->data, 0, size);
+}
+
+imAttribNode::~imAttribNode()
+{
+ free(this->name);
+ free(this->data);
+}
+
+
+/*******************************************************************/
+
+struct imAttribTablePrivate
+{
+ int count,
+ hash_size;
+ imAttribNode* *hash_table;
+};
+
+imAttribTablePrivate* imAttribTableCreate(int hash_size)
+{
+ imAttribTablePrivate* ptable = (imAttribTablePrivate*)malloc(sizeof(imAttribTablePrivate));
+ ptable->count = 0;
+ ptable->hash_size = (hash_size == 0)? IM_DEFAULTSIZE: hash_size;
+ ptable->hash_table = (imAttribNode**)malloc(ptable->hash_size*sizeof(imAttribNode*));
+ memset(ptable->hash_table, 0, ptable->hash_size*sizeof(imAttribNode*));
+ return ptable;
+}
+
+imAttribTablePrivate* imAttribArrayCreate(int count)
+{
+ imAttribTablePrivate* ptable = (imAttribTablePrivate*)malloc(sizeof(imAttribTablePrivate));
+ ptable->hash_size = ptable->count = count;
+ ptable->hash_table = (imAttribNode**)malloc(ptable->count*sizeof(imAttribNode*));
+ memset(ptable->hash_table, 0, ptable->hash_size*sizeof(imAttribNode*));
+ return ptable;
+}
+
+void imAttribTableDestroy(imAttribTablePrivate* ptable)
+{
+ imAttribTableRemoveAll(ptable);
+ free(ptable->hash_table);
+ free(ptable);
+}
+
+int imAttribTableCount(imAttribTablePrivate* ptable)
+{
+ return ptable->count;
+}
+
+void imAttribTableRemoveAll(imAttribTablePrivate* ptable)
+{
+ if (ptable->count == 0) return;
+
+ int n = 0;
+ for(int i = 0; i < ptable->hash_size; i++)
+ {
+ imAttribNode* cur_node = ptable->hash_table[i];
+ while (cur_node)
+ {
+ imAttribNode* next_node = cur_node->next;
+ delete cur_node;
+ cur_node = next_node;
+ n++;
+ }
+
+ ptable->hash_table[i] = NULL;
+
+ if (n == ptable->count)
+ break;
+ }
+
+ ptable->count = 0;
+}
+
+void imAttribTableSet(imAttribTablePrivate* ptable, const char* name, int data_type, int count, const void* data)
+{
+ assert(name);
+
+ int index = iHashIndex(name, ptable->hash_size);
+ imAttribNode* first_node = ptable->hash_table[index];
+
+ // The name already exists ?
+ imAttribNode* cur_node = first_node;
+ imAttribNode* prev_node = NULL;
+ while (cur_node)
+ {
+ if (imStrEqual(cur_node->name, name))
+ {
+ // Found, replace current node.
+ imAttribNode* new_node = new imAttribNode(name, data_type, count, data, cur_node->next);
+
+ // Is first node ?
+ if (cur_node == first_node)
+ ptable->hash_table[index] = new_node;
+ else
+ prev_node->next = new_node;
+
+ delete cur_node;
+ return;
+ }
+
+ prev_node = cur_node;
+ cur_node = cur_node->next;
+ }
+
+ // Not found, the new item goes first.
+ cur_node = new imAttribNode(name, data_type, count, data, first_node);
+ ptable->hash_table[index] = cur_node;
+ ptable->count++;
+}
+
+void imAttribTableUnSet(imAttribTablePrivate* ptable, const char *name)
+{
+ assert(name);
+
+ if (ptable->count == 0) return;
+
+ int index = iHashIndex(name, ptable->hash_size);
+
+ imAttribNode* cur_node = ptable->hash_table[index];
+ imAttribNode* prev_node = cur_node;
+ while (cur_node)
+ {
+ if (imStrEqual(cur_node->name, name))
+ {
+ // Is first node ?
+ if (cur_node == prev_node)
+ ptable->hash_table[index] = cur_node->next;
+ else
+ prev_node->next = cur_node->next;
+
+ delete cur_node;
+ ptable->count--;
+ return;
+ }
+
+ prev_node = cur_node;
+ cur_node = cur_node->next;
+ }
+}
+
+const void* imAttribTableGet(const imAttribTablePrivate* ptable, const char *name, int *data_type, int *count)
+{
+ assert(name);
+
+ if (ptable->count == 0) return NULL;
+
+ int index = iHashIndex(name, ptable->hash_size);
+
+ imAttribNode* cur_node = ptable->hash_table[index];
+ while (cur_node)
+ {
+ if (imStrEqual(cur_node->name, name))
+ {
+ if (data_type) *data_type = cur_node->data_type;
+ if (count) *count = cur_node->count;
+ return cur_node->data;
+ }
+
+ cur_node = cur_node->next;
+ }
+
+ return NULL;
+}
+
+void imAttribArraySet(imAttribTablePrivate* ptable, int index, const char* name, int data_type, int count, const void* data)
+{
+ assert(name);
+ assert(index < ptable->count);
+
+ if (index >= ptable->count) return;
+
+ imAttribNode* node = ptable->hash_table[index];
+ if (node) delete node;
+
+ ptable->hash_table[index] = new imAttribNode(name, data_type, count, data, NULL);
+}
+
+const void* imAttribArrayGet(const imAttribTablePrivate* ptable, int index, char *name, int *data_type, int *count)
+{
+ if (ptable->count == 0) return NULL;
+
+ imAttribNode* node = ptable->hash_table[index];
+ if (node)
+ {
+ if (name) strcpy(name, node->name);
+ if (data_type) *data_type = node->data_type;
+ if (count) *count = node->count;
+ return node->data;
+ }
+
+ return NULL;
+}
+
+void imAttribTableForEach(const imAttribTablePrivate* ptable, void* user_data, imAttribTableCallback attrib_func)
+{
+ assert(attrib_func);
+
+ if (ptable->count == 0) return;
+
+ int index = 0;
+ for(int i = 0; i < ptable->hash_size; i++)
+ {
+ imAttribNode* cur_node = ptable->hash_table[i];
+ while (cur_node)
+ {
+ if (!attrib_func(user_data, index, cur_node->name, cur_node->data_type, cur_node->count, cur_node->data))
+ return;
+
+ index++;
+ cur_node = cur_node->next;
+ }
+
+ if (index == ptable->count)
+ return;
+ }
+}
+
+static int iCopyFunc(void* user_data, int index, const char* name, int data_type, int count, const void* data)
+{
+ (void)index;
+ imAttribTablePrivate* ptable = (imAttribTablePrivate*)user_data;
+ imAttribTableSet(ptable, name, data_type, count, data);
+ return 1;
+}
+
+void imAttribTableCopyFrom(imAttribTablePrivate* ptable_dst, const imAttribTablePrivate* ptable_src)
+{
+ imAttribTableForEach(ptable_src, (void*)ptable_dst, iCopyFunc);
+}
+
+static int iCopyArrayFunc(void* user_data, int index, const char* name, int data_type, int count, const void* data)
+{
+ (void)index;
+ imAttribTablePrivate* ptable = (imAttribTablePrivate*)user_data;
+ imAttribArraySet(ptable, index, name, data_type, count, data);
+ return 1;
+}
+
+void imAttribArrayCopyFrom(imAttribTablePrivate* ptable_dst, const imAttribTablePrivate* ptable_src)
+{
+ imAttribTableForEach(ptable_src, (void*)ptable_dst, iCopyArrayFunc);
+}