Previous: manip4, Up: Examples   [Contents]


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) 2005-2011 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 3 of the License, or (at
 * your option) any later version.
 *
 * This program 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, see <http://www.gnu.org/licenses/>.
 *
 * -->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;
  const 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;
}

Previous: manip4, Up: Examples   [Contents]