Logo Search packages:      
Sourcecode: octave2.9 version File versions

data-conv.cc

/*

Copyright (C) 1996, 1997 John W. Eaton

This file is part of Octave.

Octave 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, or (at your option) any
later version.

Octave 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 Octave; see the file COPYING.  If not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.

*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <cctype>
#include <cstdlib>

#include <iostream>
#include <vector>

#include "byte-swap.h"
#include "data-conv.h"
#include "lo-error.h"

template void swap_bytes<2> (volatile void *, int);
template void swap_bytes<4> (volatile void *, int);
template void swap_bytes<8> (volatile void *, int);

#if defined HAVE_LONG_LONG_INT
#define FIND_SIZED_INT_TYPE(VAL, BITS, TQ, Q) \
  do \
    { \
      int sz = BITS / CHAR_BIT; \
      if (sizeof (TQ char) == sz) \
      VAL = oct_data_conv::dt_ ## Q ## char; \
      else if (sizeof (TQ short) == sz) \
      VAL = oct_data_conv::dt_ ## Q ## short; \
      else if (sizeof (TQ int) == sz) \
      VAL = oct_data_conv::dt_ ## Q ## int; \
      else if (sizeof (TQ long) == sz) \
      VAL = oct_data_conv::dt_ ## Q ## long; \
      else if (sizeof (TQ long long) == sz) \
      VAL = oct_data_conv::dt_ ## Q ## longlong; \
      else \
        VAL = oct_data_conv::dt_unknown; \
    } \
  while (0)
#else
#define FIND_SIZED_INT_TYPE(VAL, BITS, TQ, Q) \
  do \
    { \
      int sz = BITS / CHAR_BIT; \
      if (sizeof (TQ char) == sz) \
      VAL = oct_data_conv::dt_ ## Q ## char; \
      else if (sizeof (TQ short) == sz) \
      VAL = oct_data_conv::dt_ ## Q ## short; \
      else if (sizeof (TQ int) == sz) \
      VAL = oct_data_conv::dt_ ## Q ## int; \
      else if (sizeof (TQ long) == sz) \
      VAL = oct_data_conv::dt_ ## Q ## long; \
      else \
        VAL = oct_data_conv::dt_unknown; \
    } \
  while (0)
#endif

#define FIND_SIZED_FLOAT_TYPE(VAL, BITS) \
  do \
    { \
      int sz = BITS / CHAR_BIT; \
      if (sizeof (float) == sz) \
      VAL = oct_data_conv::dt_float; \
      else if (sizeof (double) == sz) \
      VAL = oct_data_conv::dt_double; \
      else \
        VAL = oct_data_conv::dt_unknown; \
    } \
  while (0)

// I'm not sure it is worth the trouble, but let's use a lookup table
// for the types that are supposed to be a specific number of bits
// wide.  Given the macros above, this should work as long as CHAR_BIT
// is a multiple of 8 and there are types with the right sizes.
//
// The sized data type lookup table has the following format:
//
//                            bits
//                    +----+----+----+----+
//                    |  8 | 16 | 32 | 64 |
//                    +----+----+----+----+
//     signed integer |    |    |    |    |
//                    +----+----+----+----+
//   unsigned integer |    |    |    |    |
//                    +----+----+----+----+
//     floating point |    |    |    |    |
//                    +----+----+----+----+
//
// So, the 0,3 element is supposed to contain the oct_data_conv enum
// value corresponding to the correct native data type for a signed
// 32-bit integer.

static void
init_sized_type_lookup_table (oct_data_conv::data_type table[3][4])
{
  int bits = 8;

  for (int i = 0; i < 4; i++)
    {
      FIND_SIZED_INT_TYPE (table[0][i], bits, , );

      FIND_SIZED_INT_TYPE (table[1][i], bits, unsigned, u);

      FIND_SIZED_FLOAT_TYPE (table[2][i], bits);

      bits *= 2;
    }
}

static std::string
strip_spaces (const std::string& str)
{
  int n = str.length ();

  int k = 0;

  std::string s (n, ' ');

  for (int i = 0; i < n; i++)
    if (! isspace (str[i]))
      s[k++] = tolower (str[i]);

  s.resize (k);

  return s;
}

#define GET_SIZED_INT_TYPE(T, U) \
  do \
    { \
      switch (sizeof (T)) \
      { \
      case 1: \
        retval = dt_ ## U ## int8; \
        break; \
 \
      case 2: \
        retval = dt_ ## U ## int16; \
        break; \
 \
      case 4: \
        retval = dt_ ## U ## int32; \
        break; \
 \
      case 8: \
        retval = dt_ ## U ## int64; \
        break; \
 \
      default: \
        retval = dt_unknown; \
        break; \
      } \
    } \
  while (0)

oct_data_conv::data_type
oct_data_conv::string_to_data_type (const std::string& str)
{
  data_type retval = dt_unknown;

  static bool initialized = false;

  static data_type sized_type_table[3][4];

  if (! initialized)
    {
      init_sized_type_lookup_table (sized_type_table);

      initialized = true;
    }

  std::string s = strip_spaces (str);

  if (s == "int8" || s == "integer*1")
    retval = dt_int8;
  else if (s == "uint8")
    retval = dt_uint8;
  else if (s == "int16" || s == "integer*2")
    retval = dt_int16;
  else if (s == "uint16")
    retval = dt_uint16;
  else if (s == "int32" || s == "integer*4")
    retval = dt_int32;
  else if (s == "uint32")
    retval = dt_uint32;
  else if (s == "int64" || s == "integer*8")
    retval = dt_int64;
  else if (s == "uint64")
    retval = dt_uint64;
  else if (s == "single" || s == "float32" || s == "real*4")
    retval = dt_single;
  else if (s == "double" || s == "float64" || s == "real*8")
    retval = dt_double;
  else if (s == "char" || s == "char*1")
    retval = dt_char;
  else if (s == "schar" || s == "signedchar")
    retval = dt_schar;
  else if (s == "uchar" || s == "unsignedchar")
    retval = dt_uchar;
  else if (s == "short")
    GET_SIZED_INT_TYPE (short, );
  else if (s == "ushort" || s == "unsignedshort")
    GET_SIZED_INT_TYPE (unsigned short, u);
  else if (s == "int")
    GET_SIZED_INT_TYPE (int, );
  else if (s == "uint" || s == "unsignedint")
    GET_SIZED_INT_TYPE (unsigned int, u);
  else if (s == "long")
    GET_SIZED_INT_TYPE (long, );
  else if (s == "ulong" || s == "unsignedlong")
    GET_SIZED_INT_TYPE (unsigned long, u);
  else if (s == "longlong")
    GET_SIZED_INT_TYPE (long long, );
  else if (s == "ulonglong" || s == "unsignedlonglong")
    GET_SIZED_INT_TYPE (unsigned long long, u);
  else if (s == "float")
    {
      if (sizeof (float) == sizeof (double))
      retval = dt_double;
      else
      retval = dt_single;
    }
  else if (s == "logical")
    retval = dt_logical;
  else
    (*current_liboctave_error_handler) ("invalid data type specified");

  if (retval == dt_unknown)
    (*current_liboctave_error_handler)
      ("unable to find matching native data type for %s", s.c_str ());

  return retval;
}

void
oct_data_conv::string_to_data_type
  (const std::string& str, int& block_size,
   oct_data_conv::data_type& input_type,
   oct_data_conv::data_type& output_type)
{
  block_size = 1;
  input_type = dt_uchar;
  output_type = dt_double;

  bool input_is_output = false;

  std::string s = strip_spaces (str);

  size_t pos = 0;

  if (s[0] == '*')
    input_is_output = true;
  else
    {
      size_t len = s.length ();

      while (pos < len && isdigit (s[pos]))
      pos++;

      if (pos > 0)
      {
        if (s[pos] == '*')
          {
            block_size = atoi (s.c_str ());
            s = s.substr (pos+1);
          }
        else
          {
            (*current_liboctave_error_handler)
            ("invalid repeat count in `%s'", str.c_str ());

            return;
          }
      }
    }

  pos = s.find ('=');

  if (pos != std::string::npos)
    {
      if (s[pos+1] == '>')
      {
        std::string s1;

        if (input_is_output)
          {
            input_is_output = false;

            s1 = s.substr (1, pos-1);

            (*current_liboctave_warning_handler)
            ("warning: ignoring leading * in fread precision");
          }
        else
          s1 = s.substr (0, pos);

        input_type = string_to_data_type (s1);
        output_type = string_to_data_type (s.substr (pos+2));
      }
      else
      (*current_liboctave_error_handler)
        ("fread: invalid precision specified");
    }
  else
    {
      if (input_is_output)
      s = s.substr (1);

      input_type = string_to_data_type (s);

      if (input_is_output)
      output_type = input_type;
    }
}

void
oct_data_conv::string_to_data_type
  (const std::string& str, int& block_size,
   oct_data_conv::data_type& output_type)
{
  block_size = 1;
  output_type = dt_double;

  std::string s = strip_spaces (str);

  size_t pos = 0;

  size_t len = s.length ();

  while (pos < len && isdigit (s[pos]))
    pos++;

  if (pos > 0)
    {
      if (s[pos] == '*')
      {
        block_size = atoi (s.c_str ());
        s = s.substr (pos+1);
      }
      else
      {
        (*current_liboctave_error_handler)
          ("invalid repeat count in `%s'", str.c_str ());

        return;
      }
    }

  output_type = string_to_data_type (s);
}

std::string
oct_data_conv::data_type_as_string (oct_data_conv::data_type dt)
{
  std::string retval;

  switch (dt)
    {
    case oct_data_conv::dt_int8:
      retval = "int8";
      break;

    case oct_data_conv::dt_uint8:
      retval = "uint8";
      break;

    case oct_data_conv::dt_int16:
      retval = "int16";
      break;

    case oct_data_conv::dt_uint16:
      retval = "uint16";
      break;

    case oct_data_conv::dt_int32:
      retval = "int32";
      break;

    case oct_data_conv::dt_uint32:
      retval = "uint32";
      break;

    case oct_data_conv::dt_int64:
      retval = "int64";
      break;

    case oct_data_conv::dt_uint64:
      retval = "uint64";
      break;

    case oct_data_conv::dt_single:
      retval = "single";
      break;

    case oct_data_conv::dt_double:
      retval = "double";
      break;

    case oct_data_conv::dt_char:
      retval = "char";
      break;

    case oct_data_conv::dt_schar:
      retval = "signed char";
      break;

    case oct_data_conv::dt_uchar:
      retval = "usigned char";
      break;

    case oct_data_conv::dt_short:
      retval = "short";
      break;

    case oct_data_conv::dt_ushort:
      retval = "unsigned short";
      break;

    case oct_data_conv::dt_int:
      retval = "int";
      break;

    case oct_data_conv::dt_uint:
      retval = "usigned int";
      break;

    case oct_data_conv::dt_long:
      retval = "long";
      break;

    case oct_data_conv::dt_ulong:
      retval = "usigned long";
      break;

    case oct_data_conv::dt_longlong:
      retval = "long long";
      break;

    case oct_data_conv::dt_ulonglong:
      retval = "unsigned long long";
      break;

    case oct_data_conv::dt_float:
      retval = "float";
      break;

    case oct_data_conv::dt_logical:
      retval = "logical";
      break;

    case oct_data_conv::dt_unknown:
    default:
      retval = "unknown";
      break;
    }

  return retval;
}

#define LS_DO_READ(TYPE, swap, data, size, len, stream) \
  do \
    { \
      if (len > 0) \
      { \
        OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \
        stream.read (reinterpret_cast<char *>  (ptr), size * len); \
        if (swap) \
          swap_bytes< size > (ptr, len); \
        for (int i = 0; i < len; i++) \
          data[i] = ptr[i]; \
      } \
    } \
  while (0)

// Have to use copy here to avoid writing over data accessed via
// Matrix::data().

#define LS_DO_WRITE(TYPE, data, size, len, stream) \
  do \
    { \
      if (len > 0) \
      { \
        char tmp_type = type; \
        stream.write (&tmp_type, 1); \
        OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \
        for (int i = 0; i < len; i++) \
          ptr[i] = static_cast <TYPE> (data[i]);         \
        stream.write (reinterpret_cast<char *> (ptr), size * len); \
      } \
    } \
  while (0)

// Loading variables from files.

static void
gripe_unrecognized_float_fmt (void)
{
  (*current_liboctave_error_handler)
    ("unrecognized floating point format requested");
}

static void
gripe_data_conversion (const char *from, const char *to)
{
  (*current_liboctave_error_handler)
    ("unable to convert from %s to %s format", from, to);
}

// But first, some data conversion routines.

// Currently, we only handle conversions for the IEEE types.  To fix
// that, make more of the following routines work.

// FIXME -- assumes sizeof (Complex) == 8
// FIXME -- assumes sizeof (double) == 8
// FIXME -- assumes sizeof (float) == 4

static void
IEEE_big_double_to_IEEE_little_double (void *d, int len)
{
  swap_bytes<8> (d, len);
}

static void
VAX_D_double_to_IEEE_little_double (void * /* d */, int /* len */)
{
  gripe_data_conversion ("VAX D float", "IEEE little endian format");
}

static void
VAX_G_double_to_IEEE_little_double (void * /* d */, int /* len */)
{
  gripe_data_conversion ("VAX G float", "IEEE little endian format");
}

static void
Cray_to_IEEE_little_double (void * /* d */, int /* len */)
{
  gripe_data_conversion ("Cray", "IEEE little endian format");
}

static void
IEEE_big_float_to_IEEE_little_float (void *d, int len)
{
  swap_bytes<4> (d, len);
}

static void
VAX_D_float_to_IEEE_little_float (void * /* d */, int /* len */)
{
  gripe_data_conversion ("VAX D float", "IEEE little endian format");
}

static void
VAX_G_float_to_IEEE_little_float (void * /* d */, int /* len */)
{
  gripe_data_conversion ("VAX G float", "IEEE little endian format");
}

static void
Cray_to_IEEE_little_float (void * /* d */, int /* len */)
{
  gripe_data_conversion ("Cray", "IEEE little endian format");
}

static void
IEEE_little_double_to_IEEE_big_double (void *d, int len)
{
  swap_bytes<8> (d, len);
}

static void
VAX_D_double_to_IEEE_big_double (void * /* d */, int /* len */)
{
  gripe_data_conversion ("VAX D float", "IEEE big endian format");
}

static void
VAX_G_double_to_IEEE_big_double (void * /* d */, int /* len */)
{
  gripe_data_conversion ("VAX G float", "IEEE big endian format");
}

static void
Cray_to_IEEE_big_double (void * /* d */, int /* len */)
{
  gripe_data_conversion ("Cray", "IEEE big endian format");
}

static void
IEEE_little_float_to_IEEE_big_float (void *d, int len)
{
  swap_bytes<4> (d, len);
}

static void
VAX_D_float_to_IEEE_big_float (void * /* d */, int /* len */)
{
  gripe_data_conversion ("VAX D float", "IEEE big endian format");
}

static void
VAX_G_float_to_IEEE_big_float (void * /* d */, int /* len */)
{
  gripe_data_conversion ("VAX G float", "IEEE big endian format");
}

static void
Cray_to_IEEE_big_float (void * /* d */, int /* len */)
{
  gripe_data_conversion ("Cray", "IEEE big endian format");
}

static void
IEEE_little_double_to_VAX_D_double (void * /* d */, int /* len */)
{
  gripe_data_conversion ("IEEE little endian", "VAX D");
}

static void
IEEE_big_double_to_VAX_D_double (void * /* d */, int /* len */)
{
  gripe_data_conversion ("IEEE big endian", "VAX D");
}

static void
VAX_G_double_to_VAX_D_double (void * /* d */, int /* len */)
{
  gripe_data_conversion ("VAX G float", "VAX D");
}

static void
Cray_to_VAX_D_double (void * /* d */, int /* len */)
{
  gripe_data_conversion ("Cray", "VAX D");
}

static void
IEEE_little_float_to_VAX_D_float (void * /* d */, int /* len */)
{
  gripe_data_conversion ("IEEE little endian", "VAX D");
}

static void
IEEE_big_float_to_VAX_D_float (void * /* d */, int /* len */)
{
  gripe_data_conversion ("IEEE big endian", "VAX D");
}

static void
VAX_G_float_to_VAX_D_float (void * /* d */, int /* len */)
{
  gripe_data_conversion ("VAX G float", "VAX D");
}

static void
Cray_to_VAX_D_float (void * /* d */, int /* len */)
{
  gripe_data_conversion ("Cray", "VAX D");
}

static void
IEEE_little_double_to_VAX_G_double (void * /* d */, int /* len */)
{
  gripe_data_conversion ("IEEE little endian", "VAX G");
}

static void
IEEE_big_double_to_VAX_G_double (void * /* d */, int /* len */)
{
  gripe_data_conversion ("IEEE big endian", "VAX G");
}

static void
VAX_D_double_to_VAX_G_double (void * /* d */, int /* len */)
{
  gripe_data_conversion ("VAX D float", "VAX G");
}

static void
Cray_to_VAX_G_double (void * /* d */, int /* len */)
{
  gripe_data_conversion ("VAX G float", "VAX G");
}

static void
IEEE_little_float_to_VAX_G_float (void * /* d */, int /* len */)
{
  gripe_data_conversion ("IEEE little endian", "VAX G");
}

static void
IEEE_big_float_to_VAX_G_float (void * /* d */, int /* len */)
{
  gripe_data_conversion ("IEEE big endian", "VAX G");
}

static void
VAX_D_float_to_VAX_G_float (void * /* d */, int /* len */)
{
  gripe_data_conversion ("VAX D float", "VAX G");
}

static void
Cray_to_VAX_G_float (void * /* d */, int /* len */)
{
  gripe_data_conversion ("VAX G float", "VAX G");
}

void
do_double_format_conversion (void *data, int len,
                       oct_mach_info::float_format from_fmt,
                       oct_mach_info::float_format to_fmt)
{
  switch (to_fmt)
    {
    case oct_mach_info::flt_fmt_ieee_little_endian:
      switch (from_fmt)
      {
      case oct_mach_info::flt_fmt_ieee_little_endian:
        break;

      case oct_mach_info::flt_fmt_ieee_big_endian:
        IEEE_big_double_to_IEEE_little_double (data, len);
        break;

      case oct_mach_info::flt_fmt_vax_d:
        VAX_D_double_to_IEEE_little_double (data, len);
        break;

      case oct_mach_info::flt_fmt_vax_g:
        VAX_G_double_to_IEEE_little_double (data, len);
        break;

      case oct_mach_info::flt_fmt_cray:
        Cray_to_IEEE_little_double (data, len);
        break;

      default:
        gripe_unrecognized_float_fmt ();
        break;
      }
      break;

    case oct_mach_info::flt_fmt_ieee_big_endian:
      switch (from_fmt)
      {
      case oct_mach_info::flt_fmt_ieee_little_endian:
        IEEE_little_double_to_IEEE_big_double (data, len);
        break;

      case oct_mach_info::flt_fmt_ieee_big_endian:
        break;

      case oct_mach_info::flt_fmt_vax_d:
        VAX_D_double_to_IEEE_big_double (data, len);
        break;

      case oct_mach_info::flt_fmt_vax_g:
        VAX_G_double_to_IEEE_big_double (data, len);
        break;

      case oct_mach_info::flt_fmt_cray:
        Cray_to_IEEE_big_double (data, len);
        break;

      default:
        gripe_unrecognized_float_fmt ();
        break;
      }
      break;

    case oct_mach_info::flt_fmt_vax_d:
      switch (from_fmt)
      {
      case oct_mach_info::flt_fmt_ieee_little_endian:
        IEEE_little_double_to_VAX_D_double (data, len);
        break;

      case oct_mach_info::flt_fmt_ieee_big_endian:
        IEEE_big_double_to_VAX_D_double (data, len);
        break;

      case oct_mach_info::flt_fmt_vax_d:
        break;

      case oct_mach_info::flt_fmt_vax_g:
        VAX_G_double_to_VAX_D_double (data, len);
        break;

      case oct_mach_info::flt_fmt_cray:
        Cray_to_VAX_D_double (data, len);
        break;

      default:
        gripe_unrecognized_float_fmt ();
        break;
      }
      break;

    case oct_mach_info::flt_fmt_vax_g:
      switch (from_fmt)
      {
      case oct_mach_info::flt_fmt_ieee_little_endian:
        IEEE_little_double_to_VAX_G_double (data, len);
        break;

      case oct_mach_info::flt_fmt_ieee_big_endian:
        IEEE_big_double_to_VAX_G_double (data, len);
        break;

      case oct_mach_info::flt_fmt_vax_d:
        VAX_D_double_to_VAX_G_double (data, len);
        break;

      case oct_mach_info::flt_fmt_vax_g:
        break;

      case oct_mach_info::flt_fmt_cray:
        Cray_to_VAX_G_double (data, len);
        break;

      default:
        gripe_unrecognized_float_fmt ();
        break;
      }
      break;

    default:
      (*current_liboctave_error_handler)
      ("impossible state reached in file `%s' at line %d",
       __FILE__, __LINE__);
      break;
    }
}

void
do_float_format_conversion (void *data, int len,
                      oct_mach_info::float_format from_fmt,
                      oct_mach_info::float_format to_fmt)
{
  switch (to_fmt)
    {
    case oct_mach_info::flt_fmt_ieee_little_endian:
      switch (from_fmt)
      {
      case oct_mach_info::flt_fmt_ieee_little_endian:
        break;

      case oct_mach_info::flt_fmt_ieee_big_endian:
        IEEE_big_float_to_IEEE_little_float (data, len);
        break;

      case oct_mach_info::flt_fmt_vax_d:
        VAX_D_float_to_IEEE_little_float (data, len);
        break;

      case oct_mach_info::flt_fmt_vax_g:
        VAX_G_float_to_IEEE_little_float (data, len);
        break;

      case oct_mach_info::flt_fmt_cray:
        Cray_to_IEEE_little_float (data, len);
        break;

      default:
        gripe_unrecognized_float_fmt ();
        break;
      }
      break;

    case oct_mach_info::flt_fmt_ieee_big_endian:
      switch (from_fmt)
      {
      case oct_mach_info::flt_fmt_ieee_little_endian:
        IEEE_little_float_to_IEEE_big_float (data, len);
        break;

      case oct_mach_info::flt_fmt_ieee_big_endian:
        break;

      case oct_mach_info::flt_fmt_vax_d:
        VAX_D_float_to_IEEE_big_float (data, len);
        break;

      case oct_mach_info::flt_fmt_vax_g:
        VAX_G_float_to_IEEE_big_float (data, len);
        break;

      case oct_mach_info::flt_fmt_cray:
        Cray_to_IEEE_big_float (data, len);
        break;

      default:
        gripe_unrecognized_float_fmt ();
        break;
      }
      break;

    case oct_mach_info::flt_fmt_vax_d:
      switch (from_fmt)
      {
      case oct_mach_info::flt_fmt_ieee_little_endian:
        IEEE_little_float_to_VAX_D_float (data, len);
        break;

      case oct_mach_info::flt_fmt_ieee_big_endian:
        IEEE_big_float_to_VAX_D_float (data, len);
        break;

      case oct_mach_info::flt_fmt_vax_d:
        break;

      case oct_mach_info::flt_fmt_vax_g:
        VAX_G_float_to_VAX_D_float (data, len);
        break;

      case oct_mach_info::flt_fmt_cray:
        Cray_to_VAX_D_float (data, len);
        break;

      default:
        gripe_unrecognized_float_fmt ();
        break;
      }
      break;

    case oct_mach_info::flt_fmt_vax_g:
      switch (from_fmt)
      {
      case oct_mach_info::flt_fmt_ieee_little_endian:
        IEEE_little_float_to_VAX_G_float (data, len);
        break;

      case oct_mach_info::flt_fmt_ieee_big_endian:
        IEEE_big_float_to_VAX_G_float (data, len);
        break;

      case oct_mach_info::flt_fmt_vax_d:
        VAX_D_float_to_VAX_G_float (data, len);
        break;

      case oct_mach_info::flt_fmt_vax_g:
        break;

      case oct_mach_info::flt_fmt_cray:
        Cray_to_VAX_G_float (data, len);
        break;

      default:
        gripe_unrecognized_float_fmt ();
        break;
      }
      break;

    default:
      (*current_liboctave_error_handler)
      ("impossible state reached in file `%s' at line %d",
       __FILE__, __LINE__);
      break;
    }
}

void
do_float_format_conversion (void *data, size_t sz, int len,
                      oct_mach_info::float_format from_fmt,
                      oct_mach_info::float_format to_fmt)
{
  switch (sz)
    {
    case sizeof (float):
      do_float_format_conversion (data, len, from_fmt, to_fmt);
      break;

    case sizeof (double):
      do_double_format_conversion (data, len, from_fmt, to_fmt);
      break;

    default:
      (*current_liboctave_error_handler)
      ("impossible state reached in file `%s' at line %d",
       __FILE__, __LINE__);
      break;
    }
}


void
read_doubles (std::istream& is, double *data, save_type type, int len,
            bool swap, oct_mach_info::float_format fmt)
{
  switch (type)
    {
    case LS_U_CHAR:
      LS_DO_READ (uint8_t, swap, data, 1, len, is);
      break;

    case LS_U_SHORT:
      LS_DO_READ (uint16_t, swap, data, 2, len, is);
      break;

    case LS_U_INT:
      LS_DO_READ (uint32_t, swap, data, 4, len, is);
      break;

    case LS_CHAR:
      LS_DO_READ (int8_t, swap, data, 1, len, is);
      break;

    case LS_SHORT:
      LS_DO_READ (int16_t, swap, data, 2, len, is);
      break;

    case LS_INT:
      LS_DO_READ (int32_t, swap, data, 4, len, is);
      break;

    case LS_FLOAT:
      {
      OCTAVE_LOCAL_BUFFER (float, ptr, len);
      is.read (reinterpret_cast<char *> (ptr), 4 * len);
      do_float_format_conversion (ptr, len, fmt);
      for (int i = 0; i < len; i++)
        data[i] = ptr[i];
      }
      break;

    case LS_DOUBLE: // No conversion necessary.
      is.read (reinterpret_cast<char *> (data), 8 * len);
      do_double_format_conversion (data, len, fmt);
      break;

    default:
      is.clear (std::ios::failbit|is.rdstate ());
      break;
    }
}

void
write_doubles (std::ostream& os, const double *data, save_type type, int len)
{
  switch (type)
    {
    case LS_U_CHAR:
      LS_DO_WRITE (uint8_t, data, 1, len, os);
      break;

    case LS_U_SHORT:
      LS_DO_WRITE (uint16_t, data, 2, len, os);
      break;

    case LS_U_INT:
      LS_DO_WRITE (uint32_t, data, 4, len, os);
      break;

    case LS_CHAR:
      LS_DO_WRITE (int8_t, data, 1, len, os);
      break;

    case LS_SHORT:
      LS_DO_WRITE (int16_t, data, 2, len, os);
      break;

    case LS_INT:
      LS_DO_WRITE (int32_t, data, 4, len, os);
      break;

    case LS_FLOAT:
      LS_DO_WRITE (float, data, 4, len, os);
      break;

    case LS_DOUBLE: // No conversion necessary.
      {
      char tmp_type = static_cast<char> (type);
      os.write (&tmp_type, 1);
      os.write (reinterpret_cast <const char *> (data), 8 * len);
      }
      break;

    default:
      (*current_liboctave_error_handler)
      ("unrecognized data format requested");
      break;
    }
}

/*
;;; Local Variables: ***
;;; mode: C++ ***
;;; End: ***
*/

Generated by  Doxygen 1.6.0   Back to index