Previous: manip4, Up: Examples


B.5 bpipe_dump.c

This program will dump the contents of an input BPipe stream (on stdin) to stdout, formatting it for human comprehension.

     /* --8<--8<--8<--8<--
      *
      * Copyright (C) 2006 Smithsonian Astrophysical Observatory
      *
      * This file is part of bpipe
      *
      * bpipe is free software; you can redistribute it and/or
      * modify it under the terms of the GNU General Public License
      * as published by the Free Software Foundation; either version 2
      * of the License, or (at your option) any later version.
      *
      * bpipe is distributed in the hope that it will be useful,
      * but WITHOUT ANY WARRANTY; without even the implied warranty of
      * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      * GNU General Public License for more details.
      *
      * You should have received a copy of the GNU General Public License
      * along with this program; if not, write to the
      *       Free Software Foundation, Inc.
      *       51 Franklin Street, Fifth Floor
      *       Boston, MA  02110-1301, USA
      *
      * -->8-->8-->8-->8-- */
     
     #include <stddef.h>
     #include <stdlib.h>
     #include <stdio.h>
     #include <string.h>
     
     #include <bpipe/bpipe.h>
     #include <bpipe/datatypes.h>
     
     /* simple print error and exit routine */
     #define error(string)							\
       do {									\
           fprintf( stderr, __FILE__ " %d: %s\n", __LINE__, string );	\
           exit( EXIT_FAILURE );						\
          } while (0)
     
     /* -----------------------------------------------------------------------*/
     
     /* forward definitions */
     void 	print_matrix( BPMatrix *matrix, char *buf );
     void *	print_data( char *prefix, BPDataType type, BPMatrix *matrix,
                               void *data, size_t level );
     
     /* -----------------------------------------------------------------------*/
     
     
     int
     main (int argc, char *argv[])
     {
       BPipe *bpipe;
       DpktField *dpktf;
       BPMatrix *matrix;
       void *data;
       size_t index;
       void *last;
       char *name;
     
       size_t dpkt_core_size, n;
     
       /* create BPipe object */
       if ( NULL == ( bpipe = bpipe_new( ) ) )
         error( bpipe_strerror( bpipe_errno ) );
     
       /* attach standard input to the BPipe */
       if ( bpipe_input( bpipe, "stdin" ) )
         error( bpipe_strerror( bpipe_errno ) );
     
       /* step through header fields and print out their definitions and data */
       printf( "header fields:\n" );
     
       /* last is used by bpipe_hdrf_next to keep track of where it is */
       last = NULL;	/* initialize it for first time through */
     
       /* loop until there are no more header fields available */
       while ( bpipe_hdrf_next( bpipe, &name, &index, &last ) )
       {
         char buf[1024];
     
         /*
           extract the data type and a pointer to the data.  these should
           be valid since we've been handed name and index by bpipe_hdrf_next
          */
         BPDataType type = bpipe_hdrf_type( bpipe, name, index );
         void *     data = bpipe_hdrf_data( bpipe, name, index );
     
         if ( bpipe_errno != BPNOERROR )
           error( bpipe_strerror( bpipe_errno ) );
     
         /*
           extract matrix spec.  since it's copying the matrix, there's a
           possibility that we're out of memory, which we check for
          */
         if ( NULL == (matrix = bpipe_hdrf_matrix ( bpipe, name, index ) ) )
           error( bpipe_strerror( bpipe_errno ) );
     
         /*
           generate the field definition.  this is used to prefix the data
           output
          */
         sprintf(buf, "%s-%lu", name, (unsigned long) index );
         print_matrix( matrix, buf );
         strcat( buf, ": " );
     
         /* dump the data */
     
         /*
           if it's a one dimensional character array, assume that it's a C
           string
          */
         if ( BPDType_char == type && matrix->nd == 1 )
           printf( "%s%s\n", buf, (char*) data );
         else
           print_data( buf, type, matrix, data, matrix->nd - 1 );
     
         /*
           we're responsible for deleting the matrix spec returned by
           bpipe_hdrf_matrix
          */
         bpipe_matrix_delete( matrix );
       }
     
       /* now print out the data packet field definitions */
     
       printf( "\ndata fields:\n" );
       last = NULL;	/* initialize it for first time through */
     
       while (( dpktf = bpipe_dpktf_next( bpipe, &last ) ))
       {
         char buf[1024];
     
         /*
           extract matrix spec.  since it's copying the matrix, there's a
           possibility that we're out of memory, which we check for
          */
         if ( NULL == (matrix = bpipe_dpktf_matrix( dpktf, BPDSite_CORE, NULL ) ) )
           error( bpipe_strerror( bpipe_errno ) );
     
         /* print out the definition */
         strcpy( buf, bpipe_dpktf_name( dpktf ) );
         print_matrix( matrix, buf );
         puts( buf );
     
         /*
           we're responsible for deleting the matrix spec returned by
           bpipe_dpktf_matrix
          */
         bpipe_matrix_delete( matrix );
       }
     
       /*
         we haven't manipulated any fields, but still must map the data
         packet images to get the size of the core image
        */
     
       /*
         since we haven't done anything, bpipe_map should only fail if it
         runs out of memory.  note that its possible that there are no data
         packet fields, in which case a return of zero isn't an error
        */
     
       if ( 0 == ( dpkt_core_size = bpipe_map( bpipe ) ) &&
            bpipe_errno != BPNOERROR )
         error( bpipe_strerror( bpipe_errno ) );
     
       /* if there are no data packets, there's not much left to do */
       if ( dpkt_core_size == 0 )
       {
         bpipe_delete( bpipe );
         return EXIT_SUCCESS;
       }
     
       /* space for instance of data packet */
       if ( NULL == (data = malloc( dpkt_core_size )) )
         error( "unable to allocate data packet" );
     
       /* loop through data packets */
       n = 0;
       while( bpipe_read_dpkts( bpipe, data, (size_t) 1 ) )
       {
         n++;
         printf( "\ndata packet %lu:\n", (unsigned long) n );
     
         last = NULL;
     
         while (( dpktf = bpipe_dpktf_next( bpipe, &last ) ))
         {
           char buf[1024];
     
           /*
     	for speed, we could have saved these while printing the field
     	definitions above, but these are pretty cheap calls
            */
           void *dpktf_data = bpipe_dpktf_data( dpktf, data );
           BPDataType  type = bpipe_dpktf_type( dpktf );
     
           if ( bpipe_errno != BPNOERROR )
             error( bpipe_strerror( bpipe_errno ) );
     
           /*
     	this call is expensive, as it must copy the matrix.
     	ordinarily one would do this outside of the read loop and
     	store the values
            */
           if ( NULL ==
     	   (matrix = bpipe_dpktf_matrix( dpktf, BPDSite_CORE, NULL ) ) )
     	error( bpipe_strerror( bpipe_errno ) );
     
           strcpy( buf, bpipe_dpktf_name( dpktf ) );
           print_matrix( matrix, buf );
           strcat( buf, ": " );
     
           if ( BPDType_char == type && matrix->nd == 1 )
     	printf( "%s%s\n", buf, (char*) dpktf_data );
           else
     	print_data( buf, type, matrix, dpktf_data, matrix->nd - 1 );
     
           /*
     	we're responsible for deleting the matrix spec returned by
     	bpipe_dpktf_matrix
            */
           bpipe_matrix_delete( matrix );
         }
       }
     
       /*
         we'll get an error out of bpipe_read_dpkts if something's gone awry.
         bpipe_errno should have been equal to BPNOERROR when entering the
         above loop
        */
       if ( bpipe_errno != BPNOERROR )
         error( bpipe_strerror( bpipe_errno ) );
     
       bpipe_delete(bpipe);
     
       free( data );
     
       return EXIT_SUCCESS;
     }
     
     /* print out matrix spec */
     void
     print_matrix( BPMatrix *matrix, char *buf )
     {
       int i;
     
       for ( i = 0 ; i < matrix->nd ; i++ )
         sprintf(buf + strlen( buf ),  "[%lu]", (unsigned long) matrix->extent[i] );
     }
     
     /* recursive N-dimensional matrix data print routine */
     void *
     print_data( char *prefix,
     	    BPDataType type, BPMatrix *matrix, void *data, size_t level )
     {
       char buf[1024];
       size_t i;
       size_t size = bpipe_datatype_size( type );
     
       if (level == 0)
       {
         fputs( prefix, stdout );
         fputs( ": ", stdout );
         for (i = 0 ; i < matrix->extent[level] ; i++, data = (char *) data + size)
         {
           bpipe_sprintf( buf, data, type, NULL );
           fputs( buf, stdout );
           if ( i < matrix->extent[level] - 1 )
     	fputs( " | ", stdout );
         }
         putchar('\n');
         return data;
       }
       else
       {
         for ( i = 0 ; i < matrix->extent[level] ; i++ )
         {
           sprintf( buf, "%s[%lu]", prefix, (unsigned long) i );
           data = print_data( buf, type, matrix, data, level - 1 );
         }
         if ( level == 1 )
           puts( "--------------------" );
       }
     
       return data;
     }