xref: /petsc/src/sys/classes/viewer/impls/socket/mex-scripts/bread.c (revision 98d129c30f3ee9fdddc40fdbc5a989b7be64f888)
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 static 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 static 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 static 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 (err < 0 && errno == EINTR) continue;
99     if (!err && wsize > 0) return 1;
100     if (err < 0) PETSC_MEX_ERROR("Error reading from socket\n");
101     n -= err;
102     pp += err;
103   }
104 
105   if (!PetscBinaryBigEndian()) {
106     if (type == PETSC_INT) SYByteSwapInt((int *)ptmp, ntmp);
107     else if (type == PETSC_SCALAR) SYByteSwapScalar((PetscScalar *)ptmp, ntmp);
108     else if (type == PETSC_SHORT) SYByteSwapShort((short *)ptmp, ntmp);
109   }
110   return 0;
111 }
112 
113 /*
114     PetscBinaryWrite - Writes to a socket, called from MATLAB
115 
116   Input Parameters:
117 +   fd - the file
118 .   n  - the number of items to read
119 .   p - the data
120 -   type - the type of items to read (PETSC_INT or PETSC_SCALAR)
121 
122   Notes:
123     does byte swapping to work on all machines.
124 */
125 PetscErrorCode PetscBinaryWrite(int fd, const void *p, int n, PetscDataType type)
126 {
127   int   maxblock, wsize, err = 0, retv = 0;
128   char *pp   = (char *)p;
129   int   ntmp = n;
130   void *ptmp = (void *)p;
131 
132   maxblock = 65536;
133   if (type == PETSC_INT) n *= sizeof(int);
134   else if (type == PETSC_SCALAR) n *= sizeof(PetscScalar);
135   else if (type == PETSC_SHORT) n *= sizeof(short);
136   else if (type == PETSC_CHAR) n *= sizeof(char);
137   else PETSC_MEX_ERROR("PetscBinaryRead: Unknown type");
138 
139   if (!PetscBinaryBigEndian()) {
140     /* make sure data is in correct byte ordering before sending  */
141     if (type == PETSC_INT) SYByteSwapInt((int *)ptmp, ntmp);
142     else if (type == PETSC_SCALAR) SYByteSwapScalar((PetscScalar *)ptmp, ntmp);
143     else if (type == PETSC_SHORT) SYByteSwapShort((short *)ptmp, ntmp);
144   }
145 
146   while (n) {
147     wsize = (n < maxblock) ? n : maxblock;
148     err   = write(fd, pp, wsize);
149     if (err < 0 && errno == EINTR) continue;
150     if (!err && wsize > 0) {
151       retv = 1;
152       break;
153     };
154     if (err < 0) break;
155     n -= err;
156     pp += err;
157   }
158 
159   if (!PetscBinaryBigEndian()) {
160     /* swap the data back if we swapped it before sending it */
161     if (type == PETSC_INT) SYByteSwapInt((int *)ptmp, ntmp);
162     else if (type == PETSC_SCALAR) SYByteSwapScalar((PetscScalar *)ptmp, ntmp);
163     else if (type == PETSC_SHORT) SYByteSwapShort((short *)ptmp, ntmp);
164   }
165 
166   if (err < 0) PETSC_MEX_ERROR("Error writing to socket\n");
167   return retv;
168 }
169