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