byte swap functions refactored; added helper functions for swapping bytes in arrays
authorVictor Kirhenshtein <victor@netxms.org>
Sun, 30 Oct 2016 10:09:45 +0000 (12:09 +0200)
committerVictor Kirhenshtein <victor@netxms.org>
Sun, 30 Oct 2016 10:09:45 +0000 (12:09 +0200)
configure.ac
include/nms_cscp.h
include/nms_util.h
src/libnetxms/main.cpp
src/libnetxms/message.cpp
src/server/core/session.cpp
tests/test-libnetxms/test-libnetxms.cpp

index 69bf2d4..ed7e351 100644 (file)
@@ -1987,7 +1987,7 @@ AC_RUN_IFELSE(
 # Checks for macros and definitions
 #--------------------------------------------------------------------
 
-AC_CHECK_DECLS([__bswap_32, __bswap_64, htonll, ntohll],,,[
+AC_CHECK_DECLS([bswap_16, bswap_32, bswap_64, htonll, ntohll],,,[
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
index e5b1587..3685dc0 100644 (file)
@@ -94,7 +94,7 @@ typedef struct
    UINT32 fieldId;  // Field identifier
    BYTE type;       // Data type
    BYTE flags;      // flags (may by type-dependent)
-   WORD int16;
+   UINT16 int16;
    union
    {
       INT32 int32;
@@ -105,7 +105,7 @@ typedef struct
       struct
       {
          UINT32 length;
-         WORD value[1]; // actual size depends on length value
+         UINT16 value[1]; // actual size depends on length value
       } string;
       struct
       {
index a41a201..4e78d92 100644 (file)
 #define ntohq(x) (x)
 #define htond(x) (x)
 #define ntohd(x) (x)
-#define SwapWideString(x)
+#define SwapUCS2String(x)
 #else
-#ifdef HAVE_HTONLL
+#if HAVE_HTONLL
 #define htonq(x) htonll(x)
 #else
-#define htonq(x) __bswap_64(x)
+#define htonq(x) bswap_64(x)
 #endif
-#ifdef HAVE_NTOHLL
+#if HAVE_NTOHLL
 #define ntohq(x) ntohll(x)
 #else
-#define ntohq(x) __bswap_64(x)
+#define ntohq(x) bswap_64(x)
 #endif
-#define htond(x) __bswap_double(x)
-#define ntohd(x) __bswap_double(x)
-#define SwapWideString(x)  __bswap_wstr(x)
+#define htond(x) bswap_double(x)
+#define ntohd(x) bswap_double(x)
+#define SwapUCS2String(x) bswap_array_16((x), -1)
 #endif
 
 #ifdef __cplusplus
-extern "C" {
+
+#if !(HAVE_DECL_BSWAP_16)
+inline UINT16 bswap_16(UINT16 val)
+{
+   return (val >> 8) | ((val << 8) & 0xFF00);
+}
 #endif
 
-#if defined(_WIN32) || !(HAVE_DECL___BSWAP_32)
-UINT32 LIBNETXMS_EXPORTABLE __bswap_32(UINT32 dwVal);
+#if !(HAVE_DECL_BSWAP_32)
+inline UINT32 bswap_32(UINT32 val)
+{
+   UINT32 result;
+   BYTE *sptr = (BYTE *)&val;
+   BYTE *dptr = (BYTE *)&result + 7;
+   for(int i = 0; i < 4; i++, sptr++, dptr--)
+      *dptr = *sptr;
+   return result;
+}
 #endif
-#if defined(_WIN32) || !(HAVE_DECL___BSWAP_64)
-UINT64 LIBNETXMS_EXPORTABLE __bswap_64(UINT64 qwVal);
+
+#if !(HAVE_DECL_BSWAP_64)
+inline UINT64 bswap_64(UINT64 val)
+{
+   UINT64 result;
+   BYTE *sptr = (BYTE *)&val;
+   BYTE *dptr = (BYTE *)&result + 7;
+   for(int i = 0; i < 8; i++, sptr++, dptr--)
+      *dptr = *sptr;
+   return result;
+}
 #endif
-double LIBNETXMS_EXPORTABLE __bswap_double(double dVal);
-void LIBNETXMS_EXPORTABLE __bswap_wstr(UCS2CHAR *pStr);
 
-#ifdef __cplusplus
+inline double bswap_double(double val)
+{
+   double result;
+   BYTE *sptr = (BYTE *)&val;
+   BYTE *dptr = (BYTE *)&result + 7;
+   for(int i = 0; i < 8; i++, sptr++, dptr--)
+      *dptr = *sptr;
+   return result;
 }
+
+void LIBNETXMS_EXPORTABLE bswap_array_16(UINT16 *v, int len);
+void LIBNETXMS_EXPORTABLE bswap_array_32(UINT32 *v, int len);
+
 #endif
 
 
index 7bfbcef..1495350 100644 (file)
 #include "libnetxms.h"
 
 /**
- * Swap byte order in 64-bit integer
+ * Swap bytes in INT16 array or UCS-2 string
+ * Length -1 causes stop at first 0 value
  */
-#if defined(_WIN32) || !(HAVE_DECL___BSWAP_64)
-
-QWORD LIBNETXMS_EXPORTABLE __bswap_64(QWORD qwVal)
+void LIBNETXMS_EXPORTABLE bswap_array_16(UINT16 *v, int len)
 {
-   QWORD qwResult;
-   BYTE *sptr = (BYTE *)&qwVal;
-   BYTE *dptr = (BYTE *)&qwResult + 7;
-   int i;
-
-   for(i = 0; i < 8; i++, sptr++, dptr--)
-      *dptr = *sptr;
-
-   return qwResult;
-}
-
-#endif
-
-/**
- * Swap bytes in double
- */
-double LIBNETXMS_EXPORTABLE __bswap_double(double dVal)
-{
-   double dResult;
-   BYTE *sptr = (BYTE *)&dVal;
-   BYTE *dptr = (BYTE *)&dResult + 7;
-   int i;
-
-   for(i = 0; i < 8; i++, sptr++, dptr--)
-      *dptr = *sptr;
-
-   return dResult;
+   if (len < 0)
+   {
+      for(UINT16 *p = v; *p != 0; p++)
+         *p = bswap_16(*p);
+   }
+   else
+   {
+      int count = 0;
+      for(UINT16 *p = v; count < len; p++, count++)
+         *p = bswap_16(*p);
+   }
 }
 
 /**
- * Swap bytes in wide string (UCS-2)
+ * Swap bytes in INT32 array or UCS-4 string
+ * Length -1 causes stop at first 0 value
  */
-void LIBNETXMS_EXPORTABLE __bswap_wstr(UCS2CHAR *pStr)
+void LIBNETXMS_EXPORTABLE bswap_array_32(UINT32 *v, int len)
 {
-   UCS2CHAR *pch;
-
-   for(pch = pStr; *pch != 0; pch++)
-      *pch = htons(*pch);
+   if (len < 0)
+   {
+      for(UINT32 *p = v; *p != 0; p++)
+         *p = bswap_32(*p);
+   }
+   else
+   {
+      int count = 0;
+      for(UINT32 *p = v; count < len; p++, count++)
+         *p = bswap_32(*p);
+   }
 }
 
 #if !defined(_WIN32) && !defined(_NETWARE)
index d47aeac..f1c447c 100644 (file)
@@ -192,8 +192,7 @@ NXCPMessage::NXCPMessage(NXCP_MESSAGE *msg, int version)
             case NXCP_DT_STRING:
 #if !(WORDS_BIGENDIAN)
                entry->data.df_string.length = ntohl(entry->data.df_string.length);
-               for(i = 0; i < entry->data.df_string.length / 2; i++)
-                  entry->data.df_string.value[i] = ntohs(entry->data.df_string.value[i]);
+               bswap_array_16(entry->data.df_string.value, entry->data.df_string.length / 2);
 #endif
                break;
             case NXCP_DT_BINARY:
@@ -798,8 +797,7 @@ NXCP_MESSAGE *NXCPMessage::createMessage() const
             case NXCP_DT_STRING:
 #if !(WORDS_BIGENDIAN)
                {
-                  for(UINT32 i = 0; i < field->df_string.length / 2; i++)
-                     field->df_string.value[i] = htons(field->df_string.value[i]);
+                  bswap_array_16(field->df_string.value, field->df_string.length / 2);
                   field->df_string.length = htonl(field->df_string.length);
                }
 #endif
@@ -1046,8 +1044,7 @@ String NXCPMessage::dump(const NXCP_MESSAGE *msg, int version)
          case NXCP_DT_STRING:
 #if !(WORDS_BIGENDIAN)
             convertedField->df_string.length = ntohl(convertedField->df_string.length);
-            for(i = 0; i < (int)convertedField->df_string.length / 2; i++)
-               convertedField->df_string.value[i] = ntohs(convertedField->df_string.value[i]);
+            bswap_array_16(convertedField->df_string.value, (int)convertedField->df_string.length / 2);
 #endif
             str = GetStringFromField((BYTE *)convertedField + 8);
             out.appendFormattedString(_T("  ** [%6d] STRING   \"%s\"\n"), (int)convertedField->fieldId, str);
index a1cd52c..fe86e6d 100644 (file)
@@ -4308,7 +4308,7 @@ bool ClientSession::getCollectedDataFromDB(NXCPMessage *request, NXCPMessage *re
 #else
             mb_to_ucs2(value.getString(), -1, pCurr->value.string, MAX_DCI_STRING_VALUE);
 #endif
-            SwapWideString(pCurr->value.string);
+            SwapUCS2String(pCurr->value.string);
             break;
       }
       pData->numRows = 1;
@@ -4428,7 +4428,7 @@ read_from_db:
                      DBGetField(hResult, 1, szBuffer, MAX_DCI_STRING_VALUE);
                      mb_to_ucs2(szBuffer, -1, pCurr->value.string, MAX_DCI_STRING_VALUE);
 #endif
-                     SwapWideString(pCurr->value.string);
+                     SwapUCS2String(pCurr->value.string);
                      break;
                }
                                }
@@ -4469,7 +4469,7 @@ read_from_db:
 #else
                                     mb_to_ucs2(CHECK_NULL_EX(table->getAsString(row, col)), -1, pCurr->value.string, MAX_DCI_STRING_VALUE);
 #endif
-                                    SwapWideString(pCurr->value.string);
+                                    SwapUCS2String(pCurr->value.string);
                                     break;
                               }
                                         delete table;
index 36ffdfa..dc83f58 100644 (file)
@@ -639,6 +639,52 @@ static void TestTable()
 }
 
 /**
+ * Test byte swap
+ */
+static void TestByteSwap()
+{
+   StartTest(_T("bswap_16"));
+   AssertEquals(bswap_16(0xABCD), 0xCDAB);
+   EndTest();
+
+   StartTest(_T("bswap_32"));
+   AssertEquals(bswap_32(0x0102ABCD), 0xCDAB0201);
+   EndTest();
+
+   StartTest(_T("bswap_64"));
+   AssertEquals(bswap_64(_ULL(0x01020304A1A2A3A4)), _ULL(0xA4A3A2A104030201));
+   EndTest();
+
+   StartTest(_T("bswap_array_16"));
+   UINT16 s16[] = { 0xABCD, 0x1020, 0x2233, 0x0102 };
+   UINT16 d16[] = { 0xCDAB, 0x2010, 0x3322, 0x0201 };
+   bswap_array_16(s16, 4);
+   AssertTrue(!memcmp(s16, d16, 8));
+   EndTest();
+
+   StartTest(_T("bswap_array_16 (string)"));
+   UINT16 ss16[] = { 0xABCD, 0x1020, 0x2233, 0x0102, 0 };
+   UINT16 sd16[] = { 0xCDAB, 0x2010, 0x3322, 0x0201, 0 };
+   bswap_array_16(ss16, -1);
+   AssertTrue(!memcmp(ss16, sd16, 10));
+   EndTest();
+
+   StartTest(_T("bswap_array_32"));
+   UINT32 s32[] = { 0xABCDEF01, 0x10203040, 0x22334455, 0x01020304 };
+   UINT32 d32[] = { 0x01EFCDAB, 0x40302010, 0x55443322, 0x04030201 };
+   bswap_array_32(s32, 4);
+   AssertTrue(!memcmp(s32, d32, 16));
+   EndTest();
+
+   StartTest(_T("bswap_array_32 (string)"));
+   UINT32 ss32[] = { 0xABCDEF01, 0x10203040, 0x22334455, 0x01020304, 0 };
+   UINT32 sd32[] = { 0x01EFCDAB, 0x40302010, 0x55443322, 0x04030201, 0 };
+   bswap_array_32(ss32, -1);
+   AssertTrue(!memcmp(ss32, sd32, 20));
+   EndTest();
+}
+
+/**
  * main()
  */
 int main(int argc, char *argv[])
@@ -663,6 +709,7 @@ int main(int argc, char *argv[])
    TestMutexWrapper();
    TestRWLockWrapper();
    TestConditionWrapper();
+   TestByteSwap();
 
    MsgWaitQueue::shutdown();
    return 0;