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, 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 */ 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 */ 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 */ 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 */ 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