Logo Search packages:      
Sourcecode: ecs version File versions  Download package

cs_io_dump.c

/*============================================================================
 *  Dump of Kernel I/O file for Code_Saturne
 *============================================================================*/

/*
  This file is part of the Code_Saturne Preprocessor, element of the
  Code_Saturne CFD tool.

  Copyright (C) 2007-2008 EDF S.A., France

  contact: saturne-support@edf.fr

  The Code_Saturne Preprocessor 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.

  The Code_Saturne Preprocessor 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 the Code_Saturne Preprocessor; if not, write to the
  Free Software Foundation, Inc.,
  51 Franklin St, Fifth Floor,
  Boston, MA  02110-1301  USA
*/

/* Detect version of C used (C89 or C99) */

#if !defined(__STDC_VERSION__)
#  define __STDC_VERSION__ 1989
#endif

/* Include configuration file */

#include "ecs_config.h"

/*----------------------------------------------------------------------------
 * Standard C library headers
 *----------------------------------------------------------------------------*/

#include <assert.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#if (__STDC_VERSION__ >= 199901L)
#include <stdint.h>
#endif

/*----------------------------------------------------------------------------
 * Internationalization macros
 *----------------------------------------------------------------------------*/

#if defined(ENABLE_NLS)

#include <libintl.h>
#define _(String) gettext(String)
#define gettext_noop(String) String
#define N_(String) gettext_noop(String)

#else

#define _(String) String
#define N_(String) String
#define textdomain(Domain)
#define bindtextdomain(Package, Directory)

#endif

/*----------------------------------------------------------------------------
 * BFT library headers
 *----------------------------------------------------------------------------*/

#include <bft_error.h>
#include <bft_file.h>
#include <bft_mem.h>
#include <bft_printf.h>

/*----------------------------------------------------------------------------
 *  Local headers
 *----------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/

#ifdef __cplusplus
extern "C" {
#if 0
} /* Fake brace to force Emacs auto-indentation back to column 0 */
#endif
#endif /* __cplusplus */

/*============================================================================
 * Local Type Definitions
 *============================================================================*/

typedef struct {

  bft_file_t     *f;              /* Associated file structure pointer */

  size_t          header_size;    /* Header default size */
  size_t          header_align;   /* Header alignment */
  size_t          body_align;     /* Body alignment */

  size_t          buffer_size;    /* Current size of header buffer */
  unsigned char  *buffer;         /* Header buffer */

  size_t          n_values;       /* Number of values in section header */
  size_t          location_id;    /* Optional value location id (0 for none) */
  size_t          index_id;       /* Optional index id (0 for none) */
  size_t          n_loc_values;   /* Optional, number of values per location */
  size_t          type_size;      /* Size of current type */
  const char     *name;           /* Pointer to name field in section header */
  const char     *type_name;      /* Pointer to type field in section header */
  void           *data;           /* Pointer to data in section header */

} _cs_io_t;

/*============================================================================
 * Static global variables
 *============================================================================*/

/*============================================================================
 * Private function definitions
 *============================================================================*/

/*----------------------------------------------------------------------------
 * Print usage and exit.
 *
 * parameters:
 *   arg_0     <-- name of executable as given by argv[0]
 *   exit_code <-- EXIT_SUCCESS or EXIT_FAILURE
 *----------------------------------------------------------------------------*/

static void
_usage(const char  *arg_0,
       int          exit_code)
{
  bft_printf
    (_("\n"
       "  Usage: %s [-n <level>] <file_name>\n\n"
       "  Dump headers and optionnaly content of a Code_Saturne\n"
       "  Preprocessor, Partitioner, or restart file.\n\n"
       "  -n  <level>    number of first and last elements of each section\n"
       "                 to output (default: print headers only).\n\n"
       "  -h             this message.\n\n"),
     arg_0);

  exit(exit_code);
}

/*----------------------------------------------------------------------------
 * Convert a buffer of type uint64_t to size_t
 *
 * parameters:
 *   f   <-- pointer to file
 *   val --> array to which values are read
 *   n   <-- number of values to read
 *----------------------------------------------------------------------------*/

static void
_convert_size(unsigned char  buf[],
              size_t         val[],
              size_t         n)
{
  size_t i;

#if (__STDC_VERSION__ >= 199901L)

  for (i = 0; i < n; i++)
    val[i] = ((uint64_t *)buf)[i];

#else

  if (sizeof(size_t) == 8) {
    for (i = 0; i < n; i++)
      val[i] = ((size_t *)buf)[i];
  }
  else if (sizeof(unsigned long long) == 8) {
    for (i = 0; i < n; i++)
      val[i] = ((unsigned long long *)buf)[i];
  }
  else
    bft_error(__FILE__, __LINE__, 0,
              _("Compilation configuration / porting error:\n"
                "Unable to determine a 64-bit unsigned int type.\n"
                "size_t is %d bits, unsigned long long %d bits"),
              sizeof(size_t)*8, sizeof(unsigned long long)*8);

#endif
}

/*----------------------------------------------------------------------------
 * Open input file, testing magic string for type.
 *
 * parameters:
 *   filename     <-- file name
 *   header_size  --> header default size
 *   header_align --> header alignment
 *   body_align   --> body alignment
 *
 * returns:
 *   File metadata structure
 *----------------------------------------------------------------------------*/

static _cs_io_t
_open_input(const char *filename)
{
  size_t alignments[3];
  char header_buf[65];

  _cs_io_t inp;

  inp.f = NULL;
  inp.header_size = 0;
  inp.header_align = 0;
  inp.body_align = 0;
  inp.buffer_size = 0;
  inp.buffer = NULL;

  inp.n_values = 0;
  inp.location_id = 0;
  inp.index_id = 0,
  inp.n_loc_values = 0;
  inp.type_size = 0;
  inp.name = NULL;
  inp.type_name = NULL;
  inp.data = NULL;

  /* Open file */

  bft_printf(_("\nOpening input file: \"%s\"\n\n"), filename) ;

  bft_printf_flush();

  inp.f = bft_file_open(filename,
                        BFT_FILE_MODE_READ,
                        BFT_FILE_TYPE_BINARY);

  bft_file_set_big_endian(inp.f);

  /* Read "magic string" */

  bft_file_read(header_buf, 1, 64, inp.f);

  if (strncmp(header_buf, "Code_Saturne I/O, BE, R0", 64) != 0) {
    header_buf[64] = '\0';
    bft_error(__FILE__, __LINE__, 0,
              _("File format of \"%s\" is not recognized:\n"
                "First %d bytes: \"%s\"."),
              filename, 64, header_buf);
  }

  bft_file_read(header_buf, 1, 64, inp.f);

  header_buf[64] = '\0';
  bft_printf(_("\n  File type: %s\n"), header_buf);

  bft_file_read(header_buf, 8, 3, inp.f);

  _convert_size((unsigned char*)header_buf, alignments, 3);

  inp.header_size = alignments[0];
  inp.header_align = alignments[1];
  inp.body_align = alignments[2];

  bft_printf(_("\n"
               "  Base header size: %d\n"
               "  Header alignment: %d\n"
               "  Body alignment:   %d\n"),
             (int)(inp.header_size),
             (int)(inp.header_align),
             (int)(inp.body_align));

  inp.buffer_size = inp.header_size;
  BFT_MALLOC(inp.buffer, inp.buffer_size, unsigned char);

  /* Finish */

  return inp;
}

/*----------------------------------------------------------------------------
 * Close input file
 *
 * parameters:
 *   f <-> pointer to file object
 *----------------------------------------------------------------------------*/

static void
_close_input(_cs_io_t *inp)
{
  if (inp != NULL) {
    if (inp->f != NULL) {
      bft_printf(_("\nClosing input: \"%s\"\n\n"),
                 bft_file_get_name(inp->f)) ;
      inp->f = bft_file_free(inp->f);
    }
    inp->header_size = 0;
    inp->header_align = 0;
    inp->body_align = 0;
    inp->buffer_size = 0;
    BFT_FREE(inp->buffer);
  }
}

/*----------------------------------------------------------------------------
 * Read command line arguments.
 *
 * parameters:
 *   argc             <-- number of command line arguments
 *   argv             <-- array of command line arguments
 *   echo             --> echo (verbosity) level
 *   file_name_arg_id --> index of command line arguments defining file name
 *----------------------------------------------------------------------------*/

static void
_read_args(int               argc,
           char            **argv,
           size_t           *echo,
           int              *file_name_arg_id)
{
  int i = 1;

  /* Initialize return arguments */

  *echo = 0;
  *file_name_arg_id = 0;

  /* Parse and check command line */

  if (argc < 2)
    _usage(argv[0], EXIT_FAILURE);

  while (i < argc) {

    if (strcmp(argv[i], "-h") == 0)
      _usage(argv[0], EXIT_SUCCESS);

    else if (strcmp(argv[i], "-n") == 0) {

      i++;

      if (i >= argc)
        _usage(argv[0], EXIT_FAILURE);

      else {

#if (__STDC_VERSION__ >= 199901L)
        *echo = atoll(argv[i]);
#else
        *echo = atol(argv[i]);
#endif

      }

    }

    else {

      if (*file_name_arg_id == 0)
        *file_name_arg_id = i;
      else
        _usage(argv[0], EXIT_FAILURE);

    }

    i++;
  }

  if (*file_name_arg_id == 0)
    _usage(argv[0], EXIT_FAILURE);

  /* At this point, command line seems correct */

  bft_printf(_("\n"
               "  .----------------------------.\n"
               "  |   Code_Saturne file dump   |\n"
               "  `----------------------------'\n"));
}

/*----------------------------------------------------------------------------
 * Echo values depending on type.
 *
 * Type name should already have been checked when this function is called,
 * so no additional check is done here.
 *
 * parameters:
 *   n_values       <-- number of values to echo
 *   n_values_shift <-- shift to second (end) series of values to echo
 *   buffer         <-- pointer to data
 *   type_name      <-- name of data type
 *----------------------------------------------------------------------------*/

static void
_echo_values(size_t       n_values,
             size_t       n_values_shift,
             const void  *buffer,
             const char   type_name[])
{
  size_t i;

  /* Check type name */

  if (type_name[0] == 'c') {
    const char *_buffer = buffer;
    for (i = 0; i < n_values; i++)
      bft_printf("    %10lu : '%c'\n",
                 (unsigned long)(i + n_values_shift),
                 _buffer[i]);
  }

#if (__STDC_VERSION__ >= 199901L)

  else if (type_name[0] == 'i' && type_name[1] == '4') {
    const int32_t *_buffer = buffer;
    for (i = 0; i < n_values; i++)
      bft_printf("    %10lu : %d\n",
                 (unsigned long)(i + n_values_shift),
                 (int)(_buffer[i]));
  }

  else if (type_name[0] == 'i' && type_name[1] == '8') {
    const int64_t *_buffer = buffer;
    for (i = 0; i < n_values; i++)
      bft_printf("    %10lu : %ld\n",
                 (unsigned long)(i + n_values_shift),
                 (long)(_buffer[i]));
  }

  else if (type_name[0] == 'u' && type_name[1] == '4') {
    const uint32_t *_buffer = buffer;
    for (i = 0; i < n_values; i++)
      bft_printf("    %10lu : %u\n",
                 (unsigned long)(i + n_values_shift),
                 (unsigned)(_buffer[i]));
  }

  else if (type_name[0] == 'u' && type_name[1] == '8') {
    const uint64_t *_buffer = buffer;
    for (i = 0; i < n_values; i++)
      bft_printf("    %10lu : %lu\n",
                 (unsigned long)(i + n_values_shift),
                 (unsigned long)(_buffer[i]));
  }

#else /* (__STDC_VERSION__ < 199901L) */

  else if (type_name[0] == 'i' && type_name[1] == '4') {
    if (sizeof(int) == 4) {
      const int *_buffer = buffer;
      for (i = 0; i < n_values; i++)
        bft_printf("    %10lu : %d\n",
                   (unsigned long)(i + n_values_shift),
                   _buffer[i]);
    }
    else if (sizeof(short) == 4) {
      const short *_buffer = buffer;
      for (i = 0; i < n_values; i++)
        bft_printf("    %10lu : %d\n",
                   (unsigned long)(i + n_values_shift),
                   (int)(_buffer[i]));
    }
    else
      bft_printf("    int32_t undefined"
                 " (porting error, C99 compiler needed)\n");
  }

  else if (type_name[0] == 'i' && type_name[1] == '8') {
    if (sizeof(long) == 8) {
      const long *_buffer = buffer;
      for (i = 0; i < n_values; i++)
        bft_printf("    %10lu : %ld\n",
                   (unsigned long)(i + n_values_shift),
                   _buffer[i]);
    }
    else if (sizeof(long long) == 8) {
      const long long *_buffer = buffer;
      for (i = 0; i < n_values; i++)
        bft_printf("    %10lu : %ld\n",
                   (unsigned long)(i + n_values_shift),
                   (long)(_buffer[i]));
    }
    else
      bft_printf("    int64_t undefined"
                 " (porting error, C99 compiler needed)\n");
  }

  else if (type_name[0] == 'u' && type_name[1] == '4') {
    if (sizeof(unsigned) == 4) {
      const unsigned *_buffer = buffer;
      for (i = 0; i < n_values; i++)
        bft_printf("    %10lu : %u\n",
                   (unsigned long)(i + n_values_shift),
                   _buffer[i]);
    }
    else if (sizeof(unsigned short) == 4) {
      const unsigned short *_buffer = buffer;
      for (i = 0; i < n_values; i++)
        bft_printf("    %10lu : %u\n",
                   (unsigned long)(i + n_values_shift),
                   (unsigned)(_buffer[i]));
    }
    else
      bft_printf("    uint32_t undefined"
                 " (porting error, C99 compiler needed)\n");
  }

  else if (type_name[0] == 'u' && type_name[1] == '8') {
    if (sizeof(unsigned long) == 8) {
      const unsigned long *_buffer = buffer;
      for (i = 0; i < n_values; i++)
        bft_printf("    %10lu : %lu\n",
                   (unsigned long)(i + n_values_shift),
                   (unsigned long)(_buffer[i]));
    }
    else if (sizeof(unsigned long long) == 8) {
      const unsigned long long *_buffer = buffer;
      for (i = 0; i < n_values; i++)
        bft_printf("    %10lu : %lu\n",
                   (unsigned long)(i + n_values_shift),
                   (unsigned long)(_buffer[i]));
    }
    else
      bft_printf("    uint64_t undefined"
                 " (porting error, C99 compiler needed)\n");
  }

#endif /* (__STDC_VERSION__) */

  else if (type_name[0] == 'r' && type_name[1] == '4') {
    const float *_buffer = buffer;
    for (i = 0; i < n_values; i++)
      bft_printf("    %10lu : %15.9e\n",
                 (unsigned long)(i + n_values_shift),
                 (double)(_buffer[i]));
  }

  else if (type_name[0] == 'r' && type_name[1] == '8') {
    const double *_buffer = buffer;
    for (i = 0; i < n_values; i++)
      bft_printf("    %10lu : %22.15e\n",
                 (unsigned long)(i + n_values_shift),
                 _buffer[i]);
  }

}

/*----------------------------------------------------------------------------
 * Read section header.
 *
 * parameters:
 *   inp <-> pointer to input object
 *
 * returns:
 *   number of bytes in section body
 *----------------------------------------------------------------------------*/

static size_t
_read_section_header(_cs_io_t  *inp)
{
  int type_name_error = 0;
  size_t body_size = 0;
  size_t header_vals[6];
  unsigned int_endian = 0;

  *((char *)(&int_endian)) = '\1'; /* Determine if we are little-endian */

  assert(inp != NULL);
  assert(inp->f != NULL);
  assert(inp->buffer != NULL);

  /* Position read pointer if necessary */
  /*------------------------------------*/

  {
    bft_file_off_t offset = bft_file_tell(inp->f);
    size_t ha = inp->header_align;
    offset += (ha - (offset % ha)) % ha;
    bft_file_seek(inp->f, offset, BFT_FILE_SEEK_SET);
  }

  /* Read header */
  /*-------------*/

  bft_file_read(inp->buffer, 1, inp->header_size, inp->f);

  if (int_endian == 1)
    bft_file_swap_endian(inp->buffer, inp->buffer, 8, 6);

  _convert_size(inp->buffer, header_vals, 6);

  if (header_vals[0] > inp->header_size) {

    if (header_vals[0] > inp->buffer_size) {
      while (header_vals[0] > inp->buffer_size)
        inp->buffer_size *=2;
      BFT_REALLOC(inp->buffer, inp->buffer_size, unsigned char);
    }

    bft_file_read(inp->buffer + inp->header_size,
                  1,
                  header_vals[0] - inp->header_size,
                  inp->f);

  }

  /* Set pointers to data fields */

  inp->n_values = header_vals[1];
  inp->location_id = header_vals[2];
  inp->index_id = header_vals[3],
  inp->n_loc_values = header_vals[4];
  inp->type_size = 0;
  inp->data = NULL;
  inp->type_name = (char *)(inp->buffer + 48);
  inp->name = (char *)(inp->buffer + 56);

  if (header_vals[1] > 0 && inp->type_name[7] == 'e')
    inp->data = inp->buffer + 56 + header_vals[5];

  inp->type_size = 0;

  if (inp->n_values > 0) {

    /* Check type name and compute size of data */

    if (inp->type_name[0] == 'c') {
      if (inp->type_name[1] != ' ')
        type_name_error = 1;
      else
        inp->type_size = 1;
    }
    else if (   inp->type_name[0] == 'i'
             || inp->type_name[0] == 'u'
             || inp->type_name[0] == 'r') {

      if (inp->type_name[1] == '4')
        inp->type_size = 4;
      else if (inp->type_name[1] == '8')
        inp->type_size = 8;
      else
        type_name_error = 1;

    }
    else
      type_name_error = 1;

    if (type_name_error)
      bft_error(__FILE__, __LINE__, 0,
                _("Type \"%s\" is not known\n"
                  "Known types: \"c \", \"i4\", \"i8\", \"u4\", \"u8\", "
                  "\"r4\", \"r8\"."), inp->type_name);

    else if (inp->data == NULL)
      body_size = inp->type_size*inp->n_values;

    else if (int_endian == 1 && inp->type_size > 1)
      bft_file_swap_endian(inp->data,
                           inp->data,
                           inp->type_size,
                           inp->n_values);
  }

  return body_size;
}

/*----------------------------------------------------------------------------
 * Read section values and print associated info
 *
 * If values are already embedded in the header, no actual reading is done
 *
 * parameters:
 *   inp  <-> pointer to input object
 *   echo <-- number of values to print
 *----------------------------------------------------------------------------*/

static void
_read_section_values(_cs_io_t  *inp,
                     size_t     echo)
{
  size_t n_print = 0, n_skip = 0;
  unsigned char  *buffer = NULL;
  const unsigned char  *data = NULL;

  assert(inp->n_values > 0);

  if (inp->data != NULL)
    bft_printf(_("      Values in header\n"));

  /* Compute number of values to skip */

  if (inp->n_values > echo*2) {
    n_skip = inp->n_values - echo*2;
    n_print = echo;
  }
  else {
    n_skip = 0;
    n_print = inp->n_values;
  }

  /* Position read pointer if non-embedded data is present */

  if (inp->data == NULL) {

    bft_file_off_t offset = bft_file_tell(inp->f);
    size_t ba = inp->body_align;
    offset += (ba - (offset % ba)) % ba;
    bft_file_seek(inp->f, offset, BFT_FILE_SEEK_SET);

    /* Allocate buffer */

    if (n_print > 0) {
      BFT_MALLOC(buffer, n_print*inp->type_size, unsigned char);
      bft_file_read(buffer, inp->type_size, n_print, inp->f);
      data = buffer;
    }
  }

  else if (n_print > 0)
    data = inp->data;

  /* Print first part of data */

  if (n_print > 0) {

    if (n_skip > 0)
      bft_printf(_("    %d first and last elements:\n"), echo);
    else
      bft_printf(_("    elements:\n"));

    _echo_values(n_print, 1, data, inp->type_name);

    if (n_skip > 0)
      bft_printf("    ..........   ..........\n");

  }

  /* Mode to tail of data and read if necessary */

  if (n_skip > 0) {

    if (inp->data == NULL) {

      bft_file_off_t offset = bft_file_tell(inp->f) + n_skip*inp->type_size;
      bft_file_seek(inp->f, offset, BFT_FILE_SEEK_SET);

      if (n_print > 0) {
        bft_file_read(buffer, inp->type_size, n_print, inp->f);
        data = buffer;
      }
    }

    else if (n_print > 0)
      data = ((unsigned char *)inp->data) + ((n_print+n_skip)*inp->type_size);

    if (n_print > 0)
      _echo_values(n_print, inp->n_values - n_print + 1, data, inp->type_name);

  }

  if (buffer != NULL)
    BFT_FREE(buffer);
}

/*----------------------------------------------------------------------------
 * Read section.
 *
 * parameters:
 *   inp  <-> pointer to input object
 *   echo <-- number of values to print
 *----------------------------------------------------------------------------*/

static void
_read_section(_cs_io_t  *inp,
              int        echo)
{
  assert(inp != NULL);
  assert(inp->f != NULL);

  /* Read section header and print basic information */

  _read_section_header(inp);

  bft_printf(_("\n"
               "  Section:                \"%s\"\n"
               "    Number of values:      %lu\n"),
             inp->name, (unsigned long)(inp->n_values));

  if (inp->n_values > 0)
    bft_printf(_("    Type:                 \"%s\"\n"), inp->type_name);

  bft_printf(_("      Location id:         %lu\n"
               "      Index id:            %lu\n"
               "      Values per location: %lu\n"),
             (unsigned long)(inp->location_id),
             (unsigned long)(inp->index_id),
             (unsigned long)(inp->n_loc_values));

  if (inp->n_values > 0)
     _read_section_values(inp, echo);
}

/*============================================================================
 * Public function definitions
 *============================================================================*/

int
main (int argc, char *argv[])
{
  int file_name_arg = 0;
  size_t echo = 0;
  bft_file_off_t start_offset = 0, end_offset = 0;
  _cs_io_t inp;

  if (getenv("LANG") != NULL)
     setlocale(LC_ALL,"");
  else
     setlocale(LC_ALL,"C");
  setlocale(LC_NUMERIC,"C");

#if defined(ENABLE_NLS)
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain(PACKAGE);
#endif

  /* Parse command line arguments */

  _read_args(argc, argv, &echo, &file_name_arg);

  bft_mem_init(NULL);

  inp = _open_input(argv[file_name_arg]);

  /* Determine end of file;
     bft_file_eof() may not work when using seeks,
     so we determine the size of the file first */

  start_offset = bft_file_tell(inp.f);
  bft_file_seek(inp.f, 0, BFT_FILE_SEEK_END);
  end_offset = bft_file_tell(inp.f);
  bft_file_seek(inp.f, start_offset, BFT_FILE_SEEK_SET);

  /* Read file sections (or portions thereof) */

  while (  bft_file_tell(inp.f) + (bft_file_off_t)(inp.header_size)
         <= end_offset)
    _read_section(&inp, echo);

  /* Clean-up */

  _close_input(&inp);

  bft_mem_end();

  exit(EXIT_SUCCESS);
}

/*----------------------------------------------------------------------------*/

#ifdef __cplusplus
}
#endif /* __cplusplus */

Generated by  Doxygen 1.6.0   Back to index