NXSL: arrays implemented
authorVictor Kirhenshtein <victor@netxms.org>
Thu, 5 Jun 2008 21:11:53 +0000 (21:11 +0000)
committerVictor Kirhenshtein <victor@netxms.org>
Thu, 5 Jun 2008 21:11:53 +0000 (21:11 +0000)
include/nxsl.h
include/nxsl_classes.h
src/libnxsl/array.cpp
src/libnxsl/program.cpp

index 0ceb8c1..b22df7e 100644 (file)
@@ -68,6 +68,8 @@
 #define NXSL_ERR_INVALID_OBJECT_OPERATION 20
 #define NXSL_ERR_BAD_CLASS                21
 #define NXSL_ERR_VARIABLE_ALREADY_EXIST   22
+#define NXSL_ERR_INDEX_NOT_INTEGER        23
+#define NXSL_ERR_NOT_ARRAY                24
 
 
 //
index b9490df..b05f9fe 100644 (file)
@@ -123,11 +123,19 @@ public:
 // Array
 //
 
+struct NXSL_ArrayElement
+{
+       int index;
+       NXSL_Value *value;
+};
+
 class LIBNXSL_EXPORTABLE NXSL_Array
 {
 private:
        int m_refCount;
-       NXSL_Value **m_data;
+       int m_size;
+       int m_allocated;
+       NXSL_ArrayElement *m_data;
 
 public:
        NXSL_Array();
index aa669d2..dc66eb9 100644 (file)
 NXSL_Array::NXSL_Array()\r
 {\r
        m_refCount = 0;\r
+       m_size = 0;\r
+       m_allocated = 0;\r
+       m_data = NULL;\r
 }\r
 \r
 NXSL_Array::NXSL_Array(NXSL_Array *src)\r
 {\r
+       int i;\r
+\r
        m_refCount = 0;\r
+       m_size = src->m_size;\r
+       m_allocated = src->m_size;\r
+       if (m_size > 0)\r
+       {\r
+               m_data = (NXSL_ArrayElement *)malloc(sizeof(NXSL_ArrayElement) * m_size);\r
+               for(i = 0; i < m_size; i++)\r
+               {\r
+                       m_data[i].index = src->m_data[i].index;\r
+                       m_data[i].value = new NXSL_Value(src->m_data[i].value);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               m_data = NULL;\r
+       }\r
 }\r
 \r
 \r
@@ -45,4 +65,63 @@ NXSL_Array::NXSL_Array(NXSL_Array *src)
 \r
 NXSL_Array::~NXSL_Array()\r
 {\r
+       int i;\r
+\r
+       for(i = 0; i < m_size; i++)\r
+               delete m_data[i].value;\r
+       safe_free(m_data);\r
+}\r
+\r
+\r
+//\r
+// Compare two ints\r
+//\r
+\r
+static int CompareElements(const void *p1, const void *p2)\r
+{\r
+       return COMPARE_NUMBERS(((NXSL_ArrayElement *)p1)->index, ((NXSL_ArrayElement *)p2)->index);\r
+}\r
+\r
+\r
+//\r
+// Get element\r
+//\r
+\r
+NXSL_Value *NXSL_Array::Get(int index)\r
+{\r
+       NXSL_ArrayElement *element, key;\r
+\r
+       key.index = index;\r
+       element = (NXSL_ArrayElement *)bsearch(&key, m_data, m_size, sizeof(NXSL_ArrayElement), CompareElements);\r
+       return (element != NULL) ? element->value : NULL;\r
+}\r
+\r
+\r
+//\r
+// Set element\r
+//\r
+\r
+void NXSL_Array::Set(int index, NXSL_Value *value)\r
+{\r
+       NXSL_ArrayElement *element, key;\r
+\r
+       key.index = index;\r
+       element = (NXSL_ArrayElement *)bsearch(&key, m_data, m_size, sizeof(NXSL_ArrayElement), CompareElements);\r
+       if (element != NULL)\r
+       {\r
+               delete element->value;\r
+               element->value = value;\r
+       }\r
+       else\r
+       {\r
+               if (m_size == m_allocated)\r
+               {\r
+                       m_allocated += 32;\r
+                       m_data = (NXSL_ArrayElement *)realloc(m_data, sizeof(NXSL_ArrayElement) * m_allocated);\r
+               }\r
+               m_data[m_size].index = index;\r
+               m_data[m_size].value = value;\r
+               m_size++;\r
+               qsort(m_data, m_size, sizeof(NXSL_ArrayElement), CompareElements);\r
+       }\r
 }\r
index 20a121e..18e8bfa 100644 (file)
@@ -33,7 +33,7 @@
 // Constants
 //
 
-#define MAX_ERROR_NUMBER         22
+#define MAX_ERROR_NUMBER         24
 #define CONTROL_STACK_LIMIT      32768
 
 
@@ -84,7 +84,9 @@ static const TCHAR *m_szErrorMessage[MAX_ERROR_NUMBER] =
        _T("Function or operation argument is not a whole number"),
        _T("Invalid operation on object"),
        _T("Bad (or incompatible) object class"),
-       _T("Variable already exist")
+       _T("Variable already exist"),
+       _T("Array index is not an integer"),
+       _T("Attempt to use array element access operation on non-array")
 };
 
 
@@ -608,6 +610,84 @@ void NXSL_Program::Execute(void)
                                Error(NXSL_ERR_VARIABLE_ALREADY_EXIST);
                        }
                        break;
+               case OPCODE_SET_ELEMENT:        // Set array element; stack should contain: array index value (top)
+                       pValue = (NXSL_Value *)m_pDataStack->Pop();
+                       if (pValue != NULL)
+                       {
+                               NXSL_Value *array, *index;
+
+                               index = (NXSL_Value *)m_pDataStack->Pop();
+                               array = (NXSL_Value *)m_pDataStack->Pop();
+                               if ((index != NULL) && (array != NULL))
+                               {
+                                       if (!index->IsInteger())
+                                       {
+                                               Error(NXSL_ERR_INDEX_NOT_INTEGER);
+                                               delete pValue;
+                                       }
+                                       else if (!array->IsArray())
+                                       {
+                                               Error(NXSL_ERR_NOT_ARRAY);
+                                               delete pValue;
+                                       }
+                                       else
+                                       {
+                                               array->GetValueAsArray()->Set(index->GetValueAsInt32(), pValue);
+                                       }
+                               }
+                               else
+                               {
+                                       Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
+                                       delete pValue;
+                               }
+                               delete index;
+                               delete array;
+                       }
+         else
+         {
+            Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
+         }
+                       break;
+               case OPCODE_GET_ELEMENT:        // Get array element; stack should contain: array index (top)
+                       pValue = (NXSL_Value *)m_pDataStack->Pop();
+                       if (pValue != NULL)
+                       {
+                               NXSL_Value *array;
+
+                               array = (NXSL_Value *)m_pDataStack->Pop();
+                               if (array != NULL)
+                               {
+                                       if (array->IsArray())
+                                       {
+                                               if (pValue->IsInteger())
+                                               {
+                                                       NXSL_Value *element;
+
+                                                       element = array->GetValueAsArray()->Get(pValue->GetValueAsInt32());
+                                                       m_pDataStack->Push((element != NULL) ? new NXSL_Value(element) : new NXSL_Value);
+                                               }
+                                               else
+                                               {
+                                                       Error(NXSL_ERR_INDEX_NOT_INTEGER);
+                                               }
+                                       }
+                                       else
+                                       {
+                                               Error(NXSL_ERR_NOT_ARRAY);
+                                       }
+                                       delete array;
+                               }
+                               else
+                               {
+                                       Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
+                               }
+                               delete pValue;
+                       }
+         else
+         {
+            Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
+         }
+                       break;
       case OPCODE_CAST:
          pValue = (NXSL_Value *)m_pDataStack->Peek();
          if (pValue != NULL)