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