string map preserves key case in case-insensitive mode
authorVictor Kirhenshtein <victor@netxms.org>
Fri, 3 Oct 2014 08:03:58 +0000 (11:03 +0300)
committerVictor Kirhenshtein <victor@netxms.org>
Fri, 3 Oct 2014 08:06:36 +0000 (11:06 +0300)
netxms.sln
src/libnetxms/strmap-internal.h
src/libnetxms/strmap.cpp
src/libnetxms/strmapbase.cpp

index 814cf54..b742260 100644 (file)
@@ -1571,12 +1571,12 @@ Global
                {BBE9028E-725C-45C6-97C9-BFC443F19EA8} = {451F583D-C2DB-4414-870C-7FA0189BE7DD}
                {CB89D905-C8BE-4027-B2D8-F96C245E9160} = {B93920F5-65F4-4531-B87E-A5B357AF2476}
                {3B172035-5EEC-45A3-8471-2C390B7ED683} = {B93920F5-65F4-4531-B87E-A5B357AF2476}
-               {E417A0C4-41F1-4F87-8C33-8526ECB1F8AF} = {B93920F5-65F4-4531-B87E-A5B357AF2476}
                {64482674-7B36-4A14-A612-247333174315} = {B93920F5-65F4-4531-B87E-A5B357AF2476}
                {5818CCA9-B585-44B8-B29E-98B1DC278A3C} = {B93920F5-65F4-4531-B87E-A5B357AF2476}
                {53997B2A-D94C-428C-816D-938C297A1866} = {B93920F5-65F4-4531-B87E-A5B357AF2476}
                {80EB59BF-5CEC-4248-BF3B-7C30E67063B8} = {B93920F5-65F4-4531-B87E-A5B357AF2476}
                {7C6DD495-5A44-4D50-B065-A8CA120272F7} = {B93920F5-65F4-4531-B87E-A5B357AF2476}
+               {E417A0C4-41F1-4F87-8C33-8526ECB1F8AF} = {B93920F5-65F4-4531-B87E-A5B357AF2476}
                {7DC90EE4-E31C-4F12-8F1E-81F10E9099FB} = {268BC97D-BFC6-4BD7-BF78-E6AC1D8BA37E}
                {0A4CE471-020A-42C6-91C0-DFEFA7E815E0} = {268BC97D-BFC6-4BD7-BF78-E6AC1D8BA37E}
                {9EA98E79-EB7D-4F6C-8105-AC7B231ABB10} = {268BC97D-BFC6-4BD7-BF78-E6AC1D8BA37E}
index baa0d63..3536106 100644 (file)
@@ -33,6 +33,7 @@ struct StringMapEntry
    UT_hash_handle hh;
    TCHAR *key;
    void *value;
+   TCHAR *originalKey;
 };
 
 #endif
index a3f19d4..0d20276 100644 (file)
@@ -36,7 +36,7 @@ StringMap::StringMap(const StringMap &src) : StringMapBase(true)
    StringMapEntry *entry, *tmp;
    HASH_ITER(hh, src.m_data, entry, tmp)
    {
-      setObject(_tcsdup(entry->key), _tcsdup((TCHAR *)entry->value), true);
+      setObject(_tcsdup(m_ignoreCase ? entry->originalKey : entry->key), _tcsdup((TCHAR *)entry->value), true);
    }
 }
 
@@ -61,7 +61,7 @@ StringMap& StringMap::operator =(const StringMap &src)
    StringMapEntry *entry, *tmp;
    HASH_ITER(hh, src.m_data, entry, tmp)
    {
-      setObject(_tcsdup(entry->key), _tcsdup((TCHAR *)entry->value), true);
+      setObject(_tcsdup(m_ignoreCase ? entry->originalKey : entry->key), _tcsdup((TCHAR *)entry->value), true);
    }
        return *this;
 }
@@ -74,7 +74,7 @@ void StringMap::addAll(StringMap *src)
    StringMapEntry *entry, *tmp;
    HASH_ITER(hh, src->m_data, entry, tmp)
    {
-      setObject(_tcsdup(entry->key), _tcsdup((TCHAR *)entry->value), true);
+      setObject(_tcsdup(src->m_ignoreCase ? entry->originalKey : entry->key), _tcsdup((TCHAR *)entry->value), true);
    }
 }
 
@@ -125,7 +125,7 @@ void StringMap::fillMessage(CSCPMessage *msg, UINT32 sizeFieldId, UINT32 baseFie
    StringMapEntry *entry, *tmp;
    HASH_ITER(hh, m_data, entry, tmp)
    {
-      msg->SetVariable(id++, entry->key);
+      msg->SetVariable(id++, m_ignoreCase ? entry->originalKey : entry->key);
       msg->SetVariable(id++, (TCHAR *)entry->value);
    }
 }
index 358d7aa..533adc4 100644 (file)
@@ -65,6 +65,7 @@ void StringMapBase::clear()
    {
       HASH_DEL(m_data, entry);
       free(entry->key);
+      safe_free(entry->originalKey);
       destroyObject(entry->value);
       free(entry);
    }
@@ -106,7 +107,22 @@ void StringMapBase::setObject(TCHAR *key, void *value, bool keyPreAllocated)
        if (entry != NULL)
        {
                if (keyPreAllocated)
-                       free(key);
+      {
+         if (m_ignoreCase)
+         {
+            free(entry->originalKey);
+            entry->originalKey = key;
+         }
+         else
+         {
+                          free(key);
+         }
+      }
+      else if (m_ignoreCase)
+      {
+         free(entry->originalKey);
+         entry->originalKey = _tcsdup(key);
+      }
                if (m_objectOwner)
          destroyObject(entry->value);
       entry->value = value;
@@ -116,7 +132,14 @@ void StringMapBase::setObject(TCHAR *key, void *value, bool keyPreAllocated)
       entry = (StringMapEntry *)malloc(sizeof(StringMapEntry));
       entry->key = keyPreAllocated ? key : _tcsdup(key);
       if (m_ignoreCase)
+      {
+         entry->originalKey = _tcsdup(entry->key);
          _tcsupr(entry->key);
+      }
+      else
+      {
+         entry->originalKey = NULL;
+      }
       int keyLen = (int)(_tcslen(key) * sizeof(TCHAR));
       entry->value = value;
       HASH_ADD_KEYPTR(hh, m_data, entry->key, keyLen, entry);
@@ -142,6 +165,7 @@ void StringMapBase::remove(const TCHAR *key)
    {
       HASH_DEL(m_data, entry);
       free(entry->key);
+      safe_free(entry->originalKey);
                if (m_objectOwner)
          destroyObject(entry->value);
       free(entry);
@@ -158,7 +182,7 @@ bool StringMapBase::forEach(bool (*cb)(const TCHAR *, const void *, void *), voi
    StringMapEntry *entry, *tmp;
    HASH_ITER(hh, m_data, entry, tmp)
    {
-      if (!cb(entry->key, entry->value, userData))
+      if (!cb(m_ignoreCase ? entry->originalKey : entry->key, entry->value, userData))
       {
          result = false;
          break;
@@ -176,7 +200,7 @@ const void *StringMapBase::findElement(bool (*comparator)(const TCHAR *, const v
    StringMapEntry *entry, *tmp;
    HASH_ITER(hh, m_data, entry, tmp)
    {
-      if (comparator(entry->key, entry->value, userData))
+      if (comparator(m_ignoreCase ? entry->originalKey : entry->key, entry->value, userData))
       {
          result = entry->value;
          break;
@@ -195,7 +219,7 @@ StructArray<KeyValuePair> *StringMapBase::toArray()
    HASH_ITER(hh, m_data, entry, tmp)
    {
       KeyValuePair p;
-      p.key = entry->key;
+      p.key = m_ignoreCase ? entry->originalKey : entry->key;
       p.value = entry->value;
       a->add(&p);
    }
@@ -209,3 +233,45 @@ int StringMapBase::size()
 {
    return HASH_COUNT(m_data);
 }
+
+/**
+ * Change case sensitivity mode
+ */
+void StringMapBase::setIgnoreCase(bool ignore)
+{ 
+   if (m_ignoreCase == ignore)
+      return;  // No change required
+
+   m_ignoreCase = ignore;
+   if (m_data == NULL)
+      return;  // Empty set
+
+   StringMapEntry *data = NULL;
+   StringMapEntry *entry, *tmp;
+   if (m_ignoreCase)
+   {
+      // switching to case ignore mode
+      HASH_ITER(hh, m_data, entry, tmp)
+      {
+         HASH_DEL(m_data, entry);
+         entry->originalKey = _tcsdup(entry->key);
+         _tcsupr(entry->key);
+         int keyLen = (int)(_tcslen(entry->key) * sizeof(TCHAR));
+         HASH_ADD_KEYPTR(hh, data, entry->key, keyLen, entry);
+      }
+   }
+   else
+   {
+      // switching to case sensitive mode
+      HASH_ITER(hh, m_data, entry, tmp)
+      {
+         HASH_DEL(m_data, entry);
+         free(entry->key);
+         entry->key = entry->originalKey;
+         entry->originalKey = NULL;
+         int keyLen = (int)(_tcslen(entry->key) * sizeof(TCHAR));
+         HASH_ADD_KEYPTR(hh, data, entry->key, keyLen, entry);
+      }
+   }
+   m_data = data;
+}