xref: /petsc/src/sys/classes/viewer/impls/socket/mex-scripts/bread.c (revision 3b751433063d81e134f7574f65c0d235a4700d16)
1 #include <petscsys.h>
2 #include <../src/sys/classes/viewer/impls/socket/socket.h>
3 
4 /*
5    TAKEN from src/sys/fileio/sysio.c The swap byte routines are
6   included here because the MATLAB programs that use this do NOT
7   link to the PETSc libraries.
8 */
9 #include <errno.h>
10 #if defined(PETSC_HAVE_UNISTD_H)
11   #include <unistd.h>
12 #endif
13 
14 /*
15   SYByteSwapInt - Swap bytes in an integer
16 */
SYByteSwapInt(int * buff,PetscCount n)17 static void SYByteSwapInt(int *buff, PetscCount n)
18 {
19   int   tmp;
20   char *ptr1, *ptr2 = (char *)&tmp;
21   for (PetscCount j = 0; j < n; j++) {
22     ptr1 = (char *)(buff + j);
23     for (PetscCount i = 0; i < sizeof(int); i++) ptr2[i] = ptr1[sizeof(int) - 1 - i];
24     buff[j] = tmp;
25   }
26 }
27 /*
28   SYByteSwapShort - Swap bytes in a short
29 */
SYByteSwapShort(short * buff,PetscCount n)30 static void SYByteSwapShort(short *buff, PetscCount n)
31 {
32   short tmp;
33   char *ptr1, *ptr2 = (char *)&tmp;
34   for (PetscCount j = 0; j < n; j++) {
35     ptr1 = (char *)(buff + j);
36     for (PetscCount i = 0; i < sizeof(short); i++) ptr2[i] = ptr1[sizeof(int) - 1 - i];
37     buff[j] = tmp;
38   }
39 }
40 /*
41   SYByteSwapScalar - Swap bytes in a double
42   Complex is dealt with as if array of double twice as long.
43 */
SYByteSwapScalar(PetscScalar * buff,PetscCount n)44 static void SYByteSwapScalar(PetscScalar *buff, PetscCount n)
45 {
46   double tmp, *buff1 = (double *)buff;
47   char  *ptr1, *ptr2 = (char *)&tmp;
48 #if defined(PETSC_USE_COMPLEX)
49   n *= 2;
50 #endif
51   for (PetscCount j = 0; j < n; j++) {
52     ptr1 = (char *)(buff1 + j);
53     for (PetscCount i = 0; i < sizeof(double); i++) ptr2[i] = ptr1[sizeof(double) - 1 - i];
54     buff1[j] = tmp;
55   }
56 }
57 
58 #define PETSC_MEX_ERROR(a) \
59   { \
60     fprintf(stdout, "sread: %s \n", a); \
61     return PETSC_ERR_SYS; \
62   }
63 
64 // PetscClangLinter pragma disable: -fdoc.*
65 /*
66   PetscBinaryRead - Reads from a socket, called from MATLAB
67 
68   Input Parameters:
69 + fd   - the file
70 . n    - the number of items to read
71 - type - the type of items to read (PETSC_INT or PETSC_SCALAR)
72 
73   Output Parameter:
74 . p - the buffer
75 
76   Notes:
77   does byte swapping to work on all machines.
78 */
PetscBinaryRead(int fd,void * p,PetscCount n,PetscInt * dummy,PetscDataType type)79 PetscErrorCode PetscBinaryRead(int fd, void *p, PetscCount n, PetscInt *dummy, PetscDataType type)
80 {
81   int        maxblock, err;
82   char      *pp   = (char *)p;
83   PetscCount ntmp = n, wsize;
84   void      *ptmp = p;
85 
86   maxblock = 65536;
87   if (type == PETSC_INT) n *= sizeof(int);
88   else if (type == PETSC_SCALAR) n *= sizeof(PetscScalar);
89   else if (type == PETSC_SHORT) n *= sizeof(short);
90   else if (type == PETSC_CHAR) n *= sizeof(char);
91   else PETSC_MEX_ERROR("PetscBinaryRead: Unknown type");
92 
93   while (n) {
94     wsize = (n < maxblock) ? n : maxblock;
95     err   = (int)read(fd, pp, (int)wsize);
96     if (err < 0 && errno == EINTR) continue;
97     if (!err && wsize > 0) return 1;
98     if (err < 0) PETSC_MEX_ERROR("Error reading from socket\n");
99     n -= err;
100     pp += err;
101   }
102 
103   if (!PetscBinaryBigEndian()) {
104     if (type == PETSC_INT) SYByteSwapInt((int *)ptmp, ntmp);
105     else if (type == PETSC_SCALAR) SYByteSwapScalar((PetscScalar *)ptmp, ntmp);
106     else if (type == PETSC_SHORT) SYByteSwapShort((short *)ptmp, ntmp);
107   }
108   return 0;
109 }
110 
111 /*
112     PetscBinaryWrite - Writes to a socket, called from MATLAB
113 
114   Input Parameters:
115 +   fd - the file
116 .   n  - the number of items to read
117 .   p - the data
118 -   type - the type of items to read (PETSC_INT or PETSC_SCALAR)
119 
120   Notes:
121     does byte swapping to work on all machines.
122 */
PetscBinaryWrite(int fd,const void * p,PetscCount n,PetscDataType type)123 PetscErrorCode PetscBinaryWrite(int fd, const void *p, PetscCount n, PetscDataType type)
124 {
125   int        maxblock, err = 0, retv = 0;
126   char      *pp   = (char *)p;
127   PetscCount ntmp = n;
128   void      *ptmp = (void *)p;
129   PetscCount wsize;
130 
131   maxblock = 65536;
132   if (type == PETSC_INT) n *= sizeof(int);
133   else if (type == PETSC_SCALAR) n *= sizeof(PetscScalar);
134   else if (type == PETSC_SHORT) n *= sizeof(short);
135   else if (type == PETSC_CHAR) n *= sizeof(char);
136   else PETSC_MEX_ERROR("PetscBinaryRead: Unknown type");
137 
138   if (!PetscBinaryBigEndian()) {
139     /* make sure data is in correct byte ordering before sending  */
140     if (type == PETSC_INT) SYByteSwapInt((int *)ptmp, ntmp);
141     else if (type == PETSC_SCALAR) SYByteSwapScalar((PetscScalar *)ptmp, ntmp);
142     else if (type == PETSC_SHORT) SYByteSwapShort((short *)ptmp, ntmp);
143   }
144 
145   while (n) {
146     wsize = (n < maxblock) ? n : maxblock;
147     err   = (int)write(fd, pp, (int)wsize);
148     if (err < 0 && errno == EINTR) continue;
149     if (!err && wsize > 0) {
150       retv = 1;
151       break;
152     };
153     if (err < 0) break;
154     n -= err;
155     pp += err;
156   }
157 
158   if (!PetscBinaryBigEndian()) {
159     /* swap the data back if we swapped it before sending it */
160     if (type == PETSC_INT) SYByteSwapInt((int *)ptmp, ntmp);
161     else if (type == PETSC_SCALAR) SYByteSwapScalar((PetscScalar *)ptmp, ntmp);
162     else if (type == PETSC_SHORT) SYByteSwapShort((short *)ptmp, ntmp);
163   }
164 
165   if (err < 0) PETSC_MEX_ERROR("Error writing to socket\n");
166   return retv;
167 }
168