Actual source code: bread.c

      1: #include <petscsys.h>
      2: #include <../src/sys/classes/viewer/impls/socket/socket.h>

      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

     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: }

     58: #define PETSC_MEX_ERROR(a) \
     59:   { \
     60:     fprintf(stdout, "sread: %s \n", a); \
     61:     return PETSC_ERR_SYS; \
     62:   }

     64: // PetscClangLinter pragma disable: -fdoc.*
     65: /*
     66:   PetscBinaryRead - Reads from a socket, called from MATLAB

     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)

     73:   Output Parameter:
     74: . p - the buffer

     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;

     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");

     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:   }

    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: }

    111: /*
    112:     PetscBinaryWrite - Writes to a socket, called from MATLAB

    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)

    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;

    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");

    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:   }

    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:   }

    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:   }

    165:   if (err < 0) PETSC_MEX_ERROR("Error writing to socket\n");
    166:   return retv;
    167: }