Read in TPR char buffer as vector
authorPaul Bauer <paul.bauer.q@gmail.com>
Fri, 14 Jun 2019 14:50:22 +0000 (16:50 +0200)
committerMagnus Lundborg <magnus.lundborg@scilifelab.se>
Tue, 24 Sep 2019 12:10:15 +0000 (14:10 +0200)
Perform the I/O of the TPR char buffer as xdr_vector operation instead
of using single bytes.

Also use the xdr vector specialization for unsigned char and rvecs.

Refs #2971

Change-Id: I20534985fbdee8108792f676b3cb4264ab74c456

src/gromacs/fileio/gmxfio_xdr.cpp
src/gromacs/fileio/gmxfio_xdr.h
src/gromacs/utility/iserializer.h

index 2fe2217f1b0ddb69184e8852fd2f7c0a89e4abb1..55606a9f31a20ca63586bf73f4f1cd8876ab0be2 100644 (file)
 /* Enumerated for data types in files */
 enum {
     eioREAL, eioFLOAT, eioDOUBLE, eioINT, eioINT32, eioINT64,
-    eioUCHAR, eioCHAR, eioNUCHAR, eioUSHORT,
+    eioUCHAR, eioCHAR, eioNCHAR, eioNUCHAR, eioUSHORT,
     eioRVEC, eioNRVEC, eioIVEC, eioSTRING, eioNR
 };
 
 static const char *eioNames[eioNR] =
 {
     "REAL", "FLOAT", "DOUBLE", "INT", "INT32", "INT64",
-    "UCHAR", "CHAR", "NUCHAR", "USHORT",
+    "UCHAR", "CHAR", "NCHAR", "NUCHAR", "USHORT",
     "RVEC", "NRVEC", "IVEC", "STRING"
 };
 
@@ -92,12 +92,12 @@ XDR *gmx_fio_getxdr(t_fileio *fio)
 /* check the number of items given against the type */
 static void gmx_fio_check_nitem(int eio, int nitem, const char *file, int line)
 {
-    if ((nitem != 1) && !((eio == eioNRVEC) || (eio == eioNUCHAR)))
+    if ((nitem != 1) && !((eio == eioNRVEC) || (eio == eioNUCHAR) || (eio == eioNCHAR)))
     {
         gmx_fatal(FARGS,
-                  "nitem (%d) may differ from 1 only for %s or %s, not   for %s"
+                  "nitem (%d) may differ from 1 only for %s, %s or %s, not   for %s"
                   "(%s, %d)", nitem, eioNames[eioNUCHAR], eioNames[eioNRVEC],
-                  eioNames[eio], file, line);
+                  eioNames[eioNCHAR], eioNames[eio], file, line);
     }
 }
 
@@ -118,7 +118,7 @@ static gmx_bool do_xdr(t_fileio *fio, void *item, int nitem, int eio,
                        const char *desc, const char *srcfile, int line)
 {
     unsigned char   ucdum, *ucptr;
-    char            cdum;
+    char            cdum, *cptr;
     bool_t          res = 0;
     float           fvec[DIM];
     double          dvec[DIM];
@@ -237,13 +237,17 @@ static gmx_bool do_xdr(t_fileio *fio, void *item, int nitem, int eio,
                 *static_cast<char *>(item) = cdum;
             }
             break;
+        case eioNCHAR:
+            cptr = static_cast<char *>(item);
+            res  = xdr_vector(fio->xdr, cptr, nitem,
+                              static_cast<unsigned int>(sizeof(char)),
+                              reinterpret_cast<xdrproc_t>(xdr_char));
+            break;
         case eioNUCHAR:
             ucptr = static_cast<unsigned char *>(item);
-            res   = 1;
-            for (j = 0; (j < nitem) && res; j++)
-            {
-                res = xdr_u_char(fio->xdr, &(ucptr[j]));
-            }
+            res   = xdr_vector(fio->xdr, reinterpret_cast<char *>(ucptr), nitem,
+                               static_cast<unsigned int>(sizeof(unsigned char)),
+                               reinterpret_cast<xdrproc_t>(xdr_u_char));
             break;
         case eioUSHORT:
             if (item && !fio->bRead)
@@ -665,6 +669,15 @@ gmx_bool gmx_fio_ndoe_uchar(t_fileio *fio, unsigned char *item, int n,
     return ret;
 }
 
+gmx_bool gmx_fio_ndoe_char(t_fileio *fio, char *item,  int n,
+                           const char *desc, const char *srcfile, int line)
+{
+    gmx_bool ret = TRUE;
+    gmx_fio_lock(fio);
+    ret = ret && do_xdr(fio, item, n, eioNCHAR, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
 
 
 gmx_bool gmx_fio_ndoe_ushort(t_fileio *fio, unsigned short *item, int n,
@@ -802,6 +815,21 @@ void FileIOXdrSerializer::doRvec(rvec *value)
     gmx_fio_do_rvec(fio_, *value);
 }
 
+void FileIOXdrSerializer::doCharArray(char *values, int elements)
+{
+    gmx_fio_ndo_char(fio_, values, elements);
+}
+
+void FileIOXdrSerializer::doUCharArray(unsigned char *values, int elements)
+{
+    gmx_fio_ndo_uchar(fio_, values, elements);
+}
+
+void FileIOXdrSerializer::doRvecArray(rvec *values, int elements)
+{
+    gmx_fio_ndo_rvec(fio_, values, elements);
+}
+
 void FileIOXdrSerializer::doString(std::string *value)
 {
     // TODO: Use an arbitrary length buffer (but that is not supported in
index 313d145e682ac5c301538a13da9b6ca8fd4d9136..1007f6d12a0b1c2aeb5cb76283d30283e1b0dea3 100644 (file)
@@ -105,6 +105,8 @@ gmx_bool gmx_fio_ndoe_int64(struct t_fileio *fio, int64_t *item, int n,
                             int line);
 gmx_bool gmx_fio_ndoe_uchar(struct t_fileio *fio, unsigned char *item, int n,
                             const char *desc, const char *srcfile, int line);
+gmx_bool gmx_fio_ndoe_char(struct t_fileio *fio, char *item, int n,
+                           const char *desc, const char *srcfile, int line);
 gmx_bool gmx_fio_ndoe_ushort(struct t_fileio *fio, unsigned short *item, int n,
                              const char *desc, const char *srcfile, int line);
 gmx_bool gmx_fio_ndoe_rvec(struct t_fileio *fio, rvec *item, int n,
@@ -142,6 +144,7 @@ gmx_bool gmx_fio_ndoe_string(struct t_fileio *fio, char *item[], int n,
 #define gmx_fio_ndo_int32(fio, item, n)             gmx_fio_ndoe_int32(fio, item, n, (#item), __FILE__, __LINE__)
 #define gmx_fio_ndo_int64(fio, item, n)             gmx_fio_ndoe_int64(fio, item, n, (#item), __FILE__, __LINE__)
 #define gmx_fio_ndo_uchar(fio, item, n)             gmx_fio_ndoe_uchar(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_char(fio, item, n)              gmx_fio_ndoe_char(fio, item, n, (#item), __FILE__, __LINE__)
 #define gmx_fio_ndo_ushort(fio, item, n)            gmx_fio_ndoe_ushort(fio, item, n, (#item), __FILE__, __LINE__)
 #define gmx_fio_ndo_rvec(fio, item, n)              gmx_fio_ndoe_rvec(fio, item, n, (#item), __FILE__, __LINE__)
 #define gmx_fio_ndo_ivec(fio, item, n)              gmx_fio_ndoe_ivec(fio, item, n, (#item), __FILE__, __LINE__)
@@ -186,6 +189,12 @@ class FileIOXdrSerializer : public ISerializer
         void doRvec(rvec *value) override;
         //! Handle I/O if string.
         void doString(std::string *value) override;
+        //! Special case for handling I/O of a vector of characters.
+        void doCharArray(char *values, int elements) override;
+        //! Special case for handling I/O of a vector of unsigned characters.
+        void doUCharArray(unsigned char *values, int elements) override;
+        //! Special case for handling I/O of a vector of rvecs.
+        void doRvecArray(rvec *values, int elements) override;
 
     private:
         //! File I/O handle.
index 22141ed6cf055e126066e0efc30788f2449a8835..63ab9da95da0f1c8844d5ba88b89f418d15be3e9 100644 (file)
@@ -96,14 +96,16 @@ class ISerializer
                 doBool(&(values[i]));
             }
         }
-        void doCharArray(char *values, int elements)
+        // Char, UChar and RVec have vector specializations that can be
+        // used instead of the default looping.
+        virtual void doCharArray(char *values, int elements)
         {
             for (int i = 0; i < elements; i++)
             {
                 doChar(&(values[i]));
             }
         }
-        void doUCharArray(unsigned char *values, int elements)
+        virtual void doUCharArray(unsigned char *values, int elements)
         {
             for (int i = 0; i < elements; i++)
             {
@@ -166,7 +168,7 @@ class ISerializer
                 doIvec(&(values[i]));
             }
         }
-        void doRvecArray(rvec *values, int elements)
+        virtual void doRvecArray(rvec *values, int elements)
         {
             for (int i = 0; i < elements; i++)
             {