/* AbstractCdrInput.java --
   Copyright (C) 2005 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath 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.

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

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.CORBA.CDR;

import gnu.CORBA.BigDecimalHelper;
import gnu.CORBA.OrbFunctional;
import gnu.CORBA.GIOP.CharSets_OSF;
import gnu.CORBA.GIOP.CodeSetServiceContext;
import gnu.CORBA.IOR;
import gnu.CORBA.IorDelegate;
import gnu.CORBA.Minor;
import gnu.CORBA.TypeCodeHelper;
import gnu.CORBA.Unexpected;
import gnu.CORBA.Version;
import gnu.CORBA.gnuAny;
import gnu.CORBA.StubLocator;

import org.omg.CORBA.Any;
import org.omg.CORBA.AnySeqHolder;
import org.omg.CORBA.BAD_OPERATION;
import org.omg.CORBA.BooleanSeqHolder;
import org.omg.CORBA.CharSeqHolder;
import org.omg.CORBA.DoubleSeqHolder;
import org.omg.CORBA.FloatSeqHolder;
import org.omg.CORBA.LongLongSeqHolder;
import org.omg.CORBA.LongSeqHolder;
import org.omg.CORBA.MARSHAL;
import org.omg.CORBA.ORB;
import org.omg.CORBA.OctetSeqHolder;
import org.omg.CORBA.ShortSeqHolder;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.TypeCodePackage.BadKind;
import org.omg.CORBA.TypeCodePackage.Bounds;
import org.omg.CORBA.ULongLongSeqHolder;
import org.omg.CORBA.ULongSeqHolder;
import org.omg.CORBA.UShortSeqHolder;
import org.omg.CORBA.WCharSeqHolder;
import org.omg.CORBA.portable.InputStream;
import org.omg.CORBA.portable.ObjectImpl;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Serializable;

import java.math.BigDecimal;

/**
 * A simple CORBA CDR (common data representation) input stream, reading data
 * from the given {@link java.io.InputStream}. The primitive types are aligned
 * on they natural boundaries by implementing the abstract method
 * {@link #align(int boundary)}.
 *
 * The same class also implements {@link org.omg.CORBA.DataInputStream} to read
 * the object content in a user defined way.
 *
 * TODO This class uses 16 bits per Unicode character only, as it was until jdk
 * 1.4 inclusive.
 *
 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
 */
public abstract class AbstractCdrInput
  extends org.omg.CORBA_2_3.portable.InputStream
  implements org.omg.CORBA.DataInputStream
{
  /**
   * The runtime, associated with this stream. This field is only used when
   * reading and writing value types and filled-in in gnu.CORBA.CDR.Vio.
   */
  public transient gnuRuntime runtime;

  /**
   * The message, explaining that the exception has been thrown due unexpected
   * end of the input stream. This usually happens the server and client
   * disagree on communication or data representation rules.
   */
  protected static final String UNEXP_EOF = "Unexpected end of stream";

  /**
   * This instance is used to convert primitive data types into the byte
   * sequences.
   */
  protected AbstractDataInput b;

  /**
   * The input stream, from where the data are actually being read.
   */
  protected java.io.InputStream actual_stream;

  /**
   * The associated orb, if any.
   */
  protected ORB orb;

  /**
   * The GIOP version.
   */
  protected Version giop = new Version(1, 2);

  /**
   * The code set information.
   */
  protected CodeSetServiceContext codeset = CodeSetServiceContext.STANDARD;

  /**
   * The name of the currently used narrow charset, null if the native narrow
   * charset is used.
   */
  private String narrow_charset = null;

  /**
   * The name of the currently used wide charset, null if the native wide
   * charset is used.
   */
  private String wide_charset = null;

  /**
   * True if the native code set is used for narrow characters. If the set is
   * native, no the intermediate Reader object is instantiated when writing
   * characters.
   */
  private boolean narrow_native;

  /**
   * True if the native code set is used for wide characters. If the set is
   * native, no the intermediate Reader object is instantiated when writing
   * characters.
   */
  private boolean wide_native;

  /**
   * If true, the stream expect the multi-byte data in the form "less
   * significant byte first" (Little Endian). This is the opposite to the java
   * standard (Big Endian).
   */
  private boolean little_endian;

  /**
   * Creates the stream. The stream reads Big Endian by default.
   *
   * @param readFrom a stream to read CORBA input from.
   */
  public AbstractCdrInput(java.io.InputStream readFrom)
  {
    setInputStream(readFrom);
    setCodeSet(CodeSetServiceContext.STANDARD);
  }

  /**
   * Creates the stream, requiring the subsequent call of
   * {@link #setInputStream(java.io.InputStream)}.
   */
  public AbstractCdrInput()
  {
    setCodeSet(CodeSetServiceContext.STANDARD);
  }

  /**
   * Set the Big Endian or Little Endian encoding. The stream reads Big Endian
   * by default.
   *
   * @param use_big_endian if true, the stream expect the multi-byte data in
   * the form "most significant byte first" (Big Endian). This is the
   * java standard.
   */
  public void setBigEndian(boolean use_big_endian)
  {
    little_endian = !use_big_endian;
    setInputStream(actual_stream);
  }

  /**
   * Get the used encoding.
   *
   * @return true for Big Endian, false for Little Endian.
   */
  public boolean isBigEndian()
  {
    return !little_endian;
  }

  /**
   * Clone all important settings to another stream.
   */
  public void cloneSettings(AbstractCdrInput stream)
  {
    stream.setBigEndian(isBigEndian());
    stream.setCodeSet(getCodeSet());
    stream.setVersion(giop);
    stream.setOrb(orb);
  }

  /**
   * Set the input stream that receives the CORBA input.
   *
   * @param readFrom the stream.
   */
  public void setInputStream(java.io.InputStream readFrom)
  {
    if (little_endian)
      b = new LittleEndianInputStream(readFrom);
    else
      b = new BigEndianInputStream(readFrom);

    actual_stream = readFrom;
  }

  /**
   * Set the alignment offset, if the index of the first byte in the stream is
   * different from 0.
   */
  public abstract void setOffset(int offset);

  /**
   * Set the orb, associated with this stream.
   *
   * @param an_orb
   */
  public void setOrb(ORB an_orb)
  {
    orb = an_orb;
  }

  /**
   * Set the GIOP version. Some data types are written differently for the
   * different versions. The default version is 1.0 .
   */
  public void setVersion(Version giop_version)
  {
    giop = giop_version;
  }

  /**
   * Align the curretn position at the given natural boundary.
   */
  public abstract void align(int boundary);

  /**
   * Reads the CORBA unsigned long (java int), returning the value in the
   * sufficiently large java long.
   */
  public long gnu_read_ulong()
  {
    try
      {
        long l = b.readInt();
        l &= 0xFFFFFFF;
        return l;
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }
    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read the unsigned short integer value and return it as java int,
   * sufficiently large to hold all values.
   */
  public int gnu_read_ushort()
  {
    try
      {
        align(2);
        return b.readUnsignedShort();
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Return the associated {@link ORB}.
   *
   * @return the associated {@link ORB} or null is no such is set.
   */
  public ORB orb()
  {
    return orb;
  }

  /**
   * Read a single byte directly from the buffer.
   */
  public int read()
    throws java.io.IOException
  {
    try
      {
        return b.read();
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }
  }

  /**
   * Read bytes directly from the buffer.
   */
  public int read(byte[] x, int ofs, int len)
    throws java.io.IOException
  {
    try
      {
        return b.read(x, ofs, len);
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }
  }

  /**
   * Read bytes directly from the buffer.
   */
  public int read(byte[] x)
    throws java.io.IOException
  {
    try
      {
        return b.read(x);
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }
  }

  /**
   * Read the CORBA object. The object to read is represented in the form of the
   * plain (not a string-encoded) IOR profile without the heading endian
   * indicator. The responsible method for reading such data is
   * {@link IOR.read_no_endian}.
   *
   * The returned object is usually casted into the given type using the .narrow
   * method of its helper, despite in some cases the direct cast would also
   * work.
   *
   * The null objects are recognised from the empty profile set. For such
   * objects, null is returned.
   *
   * @return the loaded and constructed object.
   */
  public org.omg.CORBA.Object read_Object()
  {
    try
      {
        IOR ior = new IOR();
        ior._read_no_endian(this);

        if (ior.Id == null)
          return null;

        // Check maybe this is a remote reference to the local object.
        // This is only possible if we access the repository of the
        // connected object.
        if (orb instanceof OrbFunctional)
          {
            OrbFunctional forb = (OrbFunctional) orb;
            org.omg.CORBA.Object local = forb.find_local_object(ior);
            if (local != null)
              return local;
          }

        // Search for the available stubs.
        ObjectImpl impl = StubLocator.search(orb, ior);
        try
          {
            if (impl._get_delegate() == null)
              impl._set_delegate(new IorDelegate(orb, ior));
          }
        catch (BAD_OPERATION ex)
          {
            // Some colaborants may throw this exception
            // in response to the attempt to get the unset delegate.
            impl._set_delegate(new IorDelegate(orb, ior));
          }

        return impl;
      }
    catch (IOException ex)
      {
        MARSHAL bad = new MARSHAL();
        bad.minor = Minor.IOR;
        bad.initCause(ex);
        throw bad;
      }
  }

  /**
   * Read the type code. The type code format is defined in the CORBA
   * documenation.
   */
  public TypeCode read_TypeCode()
  {
    try
      {
        return TypeCodeHelper.read(this);
      }

    catch (Bounds ex)
      {
        throw new Unexpected();
      }
    catch (BadKind ex)
      {
        throw new Unexpected();
      }
  }

  /**
   * Read the CORBA {@link Any}. This method first reads the type code, then
   * delegates the functionality to {@link Any#read_value}.
   */
  public Any read_any()
  {
    TypeCode ty = read_TypeCode();
    gnuAny any = new gnuAny();
    any.read_value(this, ty);
    return any;
  }

  /**
   * Read the boolean, treating any non zero byte as true, zero byte as false.
   */
  public boolean read_boolean()
  {
    try
      {
        return b.read() == 0 ? false : true;
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }
    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read the array of boolean.
   */
  public void read_boolean_array(boolean[] x, int offs, int len)
  {
    try
      {
        for (int i = offs; i < offs + len; i++)
          {
            x[i] = b.read() == 0 ? false : true;
          }
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read a character using narrow charset encoding. Depending form which
   * encoding is set, this still can be Unicode or ever wider.
   */
  public char read_char()
  {
    try
      {
        if (narrow_native)
          return (char) b.read();
        else
          return (char) new InputStreamReader((InputStream) b, narrow_charset).read();
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read a character array, using narrow charset encoding.
   */
  public void read_char_array(char[] x, int offset, int length)
  {
    try
      {
        if (narrow_native)
          {
            for (int i = offset; i < offset + length; i++)
              x[i] = (char) b.read();
          }
        else
          {
            InputStreamReader reader = new InputStreamReader((InputStream) b,
              narrow_charset);
            reader.read(x, offset, length);
          }
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read the double value, IEEE 754 format.
   */
  public double read_double()
  {
    try
      {
        align(8);
        return b.readDouble();
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected();
      }
  }

  /**
   * Read the array of double values, IEEE 754 format.
   */
  public void read_double_array(double[] x, int offs, int len)
  {
    try
      {
        align(8);
        for (int i = offs; i < offs + len; i++)
          {
            x[i] = b.readDouble();
          }
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read the encapsulated stream. If the encapsulated sequence appears to be in
   * the Little endian format, the flag of the returned stream is set to read
   * Little endian.
   */
  public BufferredCdrInput read_encapsulation()
  {
    try
      {
        int l = read_long();

        byte[] r = new byte[l];
        int n = 0;
        while (n < r.length)
          {
            n += read(r, n, r.length - n);
          }

        BufferredCdrInput capsule = new BufferredCdrInput(r);
        capsule.setOrb(orb);

        int endian = capsule.read_octet();

        if (endian != 0)
          {
            capsule.setBigEndian(false);
          }

        return capsule;
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read the CORBA fixed (the end of the <code>fixed</code> can be determined
   * by its last byte). The scale is always assumed to be zero.
   */
  public BigDecimal read_fixed()
  {
    try
      {
        return BigDecimalHelper.read(this, 0);
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read the float value, IEEE 754 format.
   */
  public float read_float()
  {
    try
      {
        align(4);
        return b.readFloat();
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read an array of float values, IEEE 754 format.
   */
  public void read_float_array(float[] x, int offs, int len)
  {
    try
      {
        align(4);
        for (int i = offs; i < offs + len; i++)
          {
            x[i] = b.readFloat();
          }
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read the CORBA long (java int), high byte first.
   */
  public int read_long()
  {
    try
      {
        align(4);
        return b.readInt();
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read an array of CORBA longs (java ints).
   */
  public void read_long_array(int[] x, int offs, int len)
  {
    try
      {
        align(4);
        for (int i = offs; i < offs + len; i++)
          {
            x[i] = b.readInt();
          }
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read the CORBA long long (java long).
   */
  public long read_longlong()
  {
    try
      {
        align(8);
        return b.readLong();
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read an array of CORBA long longs (java longs).
   */
  public void read_longlong_array(long[] x, int offs, int len)
  {
    try
      {
        align(8);
        for (int i = offs; i < offs + len; i++)
          {
            x[i] = b.readLong();
          }
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read a single byte.
   */
  public byte read_octet()
  {
    try
      {
        return b.readByte();
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read the byte array.
   */
  public void read_octet_array(byte[] x, int offs, int len)
  {
    try
      {
        b.read(x, offs, len);
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read the length of the byte array as CORBA long and then the array itseld.
   */
  public byte[] read_sequence()
  {
    try
      {
        int l = read_long();
        byte[] buf = new byte[l];
        if (l > 0)
          {
            b.readFully(buf);
          }
        return buf;
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read the CORBA short integer.
   */
  public short read_short()
  {
    try
      {
        align(2);
        return b.readShort();
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read the array of CORBA short integer values.
   */
  public void read_short_array(short[] x, int offs, int len)
  {
    try
      {
        align(2);
        for (int i = offs; i < offs + len; i++)
          {
            x[i] = b.readShort();
          }
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Read a singe byte string. The method firs reads the byte array and then
   * calls a constructor to create a string from this array. The character
   * encoding, if previously set, is taken into consideration.
   *
   * @return a loaded string.
   */
  public String read_string()
  {
    int n = 0;
    try
      {
        align(4);

        n = b.readInt();
        byte[] s = new byte[n];
        b.read(s);

        // Discard the null terminator.
        if (narrow_charset == null)
          return new String(s, 0, n - 1);
        else
          return new String(s, 0, n - 1, narrow_charset);
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }
    catch (IOException ex)
      {
        throw new Unexpected();
      }
    catch (NegativeArraySizeException nex)
      {
        MARSHAL m = new MARSHAL("Input stream broken, got " + n + "(0x"
          + Integer.toHexString(n) + ") as a string size");
        m.minor = Minor.Negative;
        throw m;
      }
  }

  /**
   * Reads the CORBA unsigned long (java int), delegating functionality to
   * {@link #read_long}.
   */
  public int read_ulong()
  {
    return read_long();
  }

  /**
   * Reads the array of CORBA unsigned long (java integer) values, delegating
   * functionality to {@link #real_long_array}.
   */
  public void read_ulong_array(int[] x, int offs, int len)
  {
    read_long_array(x, offs, len);
  }

  /**
   * Read the CORBA unsigned long long value, delegating functionality to
   * {@link #read_longlong}. There is no way to return values over the limit of
   * the java signed long in other way than returning the negative value.
   */
  public long read_ulonglong()
  {
    return read_longlong();
  }

  /**
   * Reads the array of CORBA long long (java long) values, delegating
   * functionality to {@link #real_longlong_array}.
   */
  public void read_ulonglong_array(long[] x, int offs, int len)
  {
    read_longlong_array(x, offs, len);
  }

  /**
   * Read the unsigned short integer value. Due strange specification, the
   * returned value must be the short type as well, so the the best solution
   * seems just to delegete functionality to read_short.
   */
  public short read_ushort()
  {
    return read_short();
  }

  /**
   * Read an array of unsigned short values, delegating the functionality to
   * {@link read_short_array}.
   */
  public void read_ushort_array(short[] x, int offs, int len)
  {
    read_short_array(x, offs, len);
  }

  /**
   * Reads the wide character using the encoding, specified in the wide_charset.
   */
  public char read_wchar()
  {
    try
      {
        if (giop.until_inclusive(1, 1))
          {
            align(2);

            if (wide_native)
              return (char) b.readShort();
            else
              return (char) new InputStreamReader((InputStream) b, wide_charset).read();
          }
        else
          {
            int l = b.read();
            if (l == 2 && wide_native)
              return b.readChar();
            else if (l <= 0)
              {
                 MARSHAL m = new MARSHAL("wchar size " + l);
                 m.minor = Minor.Negative;
                 throw m;
              }
            else
              {
                byte[] bytes = new byte[l];
                b.readFully(bytes);
                String cs;

                if (bytes.length > 2 && bytes[0] == 0xFE && bytes[1] == 0xFF)
                  cs = new String(bytes, 2, bytes.length - 2, wide_charset);
                else if (bytes.length > 2 && bytes[0] == 0xFF
                  && bytes[1] == 0xFE)
                  {
                    // Litle endian detected - swap bytes.
                    byte t;
                    for (int i = 3; i < bytes.length; i = i + 2)
                      {
                        t = bytes[i];
                        bytes[i - 1] = bytes[i];
                        bytes[i] = t;
                      }
                    cs = new String(bytes, 2, bytes.length - 2, wide_charset);
                  }
                else
                  cs = new String(bytes, wide_charset);

                return cs.charAt(0);
              }
          }
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }
    catch (IOException ex)
      {
        throw new Unexpected();
      }
  }

  /**
   * Read an array of "wide chars", each representing a two byte Unicode
   * character, high byte first.
   */
  public void read_wchar_array(char[] x, int offset, int length)
  {
    try
      {
        if (giop.until_inclusive(1, 1))
          align(2);

        if (wide_native)
          {
            for (int i = offset; i < offset + length; i++)
              x[i] = (char) b.readShort();
          }
        else
          {
            InputStreamReader reader = new InputStreamReader((InputStream) b,
              wide_charset);
            reader.read(x, offset, length);
          }
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Reads the string in wide character format (ussually UTF-16, Unicode). Takes
   * the currently set charset into consideration.
   *
   * If the native (UTF-16) encoding is used of the GIOP protocol is before 1.2,
   * delegates functionality to "plain" {@link #read_wstring_UTF_16}.
   */
  public String read_wstring()
  {
    // Native encoding or word oriented data.
    if (wide_native || giop.until_inclusive(1, 1))
      return read_wstring_UTF_16();
    try
      {
        align(4);

        int n = b.readInt();
        byte[] s = new byte[n];
        b.read(s);

        return new String(s, 0, n, wide_charset);
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Reads first length of the string and the all characters as an Unicode
   * (UTF-16) characters. Mind that GIOP 1.1 has the extra null character at the
   * end that must be discarded.
   */
  public String read_wstring_UTF_16()
  {
    try
      {
        int p = 0;
        int n = read_long();

        if (n<0)
          {
            MARSHAL m = new MARSHAL("Negative string size");
            m.minor = Minor.Negative;
            throw m;
          }

        // The null terminator that is no longer present since 1.2 .
        int nt = giop.since_inclusive(1, 2) ? 0 : 1;

        // Convert bytes to shorts.
        n = n / 2;

        // Empty string.
        if (n == 0)
          return "";

        char[] s = new char[n];

        for (int i = 0; i < s.length; i++)
          s[i] = (char) b.readShort();

        // Check for the byte order marker here.
        if (s[0] == 0xFEFF)
          {
            // Big endian encoding - do nothing, but move the pointer
            // one position forward.
            p = 1;
          }
        else if (s[0] == 0xFFFE)
          {
            // Little endian encoding, swap the bytes and move one
            // position forward.
            p = 1;

            for (int i = p; i < s.length; i++)
              s[i] = swap(s[i]);
          }

        // Discard the null terminator and, if needed, the endian marker.
        String r = new String(s, p, n - nt - p);
        return r;
      }
    catch (EOFException ex)
      {
        MARSHAL t = new MARSHAL(UNEXP_EOF);
        t.minor = Minor.EOF;
        t.initCause(ex);
        throw t;
      }

    catch (IOException ex)
      {
        throw new Unexpected(ex);
      }
  }

  /**
   * Swap bytes in the character.
   */
  public static char swap(char x)
  {
    int hi;
    int lo;

    lo = x & 0xFF;
    hi = (x >> 8) & 0xFF;

    return (char) ((lo << 8) | hi);
  }

  /**
   * Set the current code set context.
   */
  public void setCodeSet(CodeSetServiceContext a_codeset)
  {
    this.codeset = a_codeset;
    narrow_charset = CharSets_OSF.getName(codeset.char_data);
    wide_charset = CharSets_OSF.getName(codeset.wide_char_data);

    narrow_native = CharSets_OSF.NATIVE_CHARACTER == codeset.char_data;
    wide_native = CharSets_OSF.NATIVE_WIDE_CHARACTER == codeset.wide_char_data;
  }

  /**
   * Get the current code set context.
   */
  public CodeSetServiceContext getCodeSet()
  {
    return codeset;
  }

  /**
   * Read the object that is an instance of the given class. The current
   * implementation delegates functionality to the parameterless
   * {@link readObject()}.
   *
   * @param klass a class of that this object the instance is.
   *
   * @return the returned object.
   */
  public org.omg.CORBA.Object read_Object(Class klass)
  {
    return read_Object();
  }

  /**
   * Read a value type structure from the stream.
   *
   * OMG specification states the writing format is outside the scope of GIOP
   * definition. This implementation uses java serialization mechanism, calling
   * {@link ObjectInputStream#readObject}
   *
   * @return an value type structure, unmarshaled from the stream
   */
  public Serializable read_Value()
  {
    return read_value();
  }

  /**
   * Read the abstract interface. An abstract interface can be either CORBA
   * value type or CORBA object and is returned as an abstract java.lang.Object.
   *
   * As specified in OMG specification, this reads a single boolean and then
   * delegates either to {@link #read_Object()} (for false) or to
   * {@link #read_Value()} (for true).
   *
   * @return an abstract interface, unmarshaled from the stream
   */
  public java.lang.Object read_Abstract()
  {
    return read_abstract_interface();
  }

  /**
   * Read an array. In OMG specification is written that if the data does not
   * fit into the holder value field, that array must be resized. The
   * implementation follows this rule. If the holder value field contains null,
   * it is newly instantiated.
   */
  public void read_char_array(CharSeqHolder holder, int offset, int length)
  {
    holder.value = ensureArray(holder.value, offset, length);
    read_char_array(holder.value, offset, length);
  }

  /**
   * Read an array. In OMG specification is written that if the data does not
   * fit into the holder value field, that array must be resized. The
   * implementation follows this rule. If the holder value field contains null,
   * it is newly instantiated.
   */
  public void read_wchar_array(WCharSeqHolder holder, int offset, int length)
  {
    holder.value = ensureArray(holder.value, offset, length);
    read_wchar_array(holder.value, offset, length);
  }

  /**
   * If required, allocate or resize the char array to fit the newly read
   * values.
   *
   * @param holder_value the existing char array, may be null.
   * @param offset the required offset to read.
   * @param length the length of the new sequence.
   *
   * @return the allocated or resized array, same array if no such operations
   * are required.
   */
  private char[] ensureArray(char[] holder_value, int offset, int length)
  {
    if (holder_value == null)
      return new char[offset + length];
    else if (holder_value.length < offset + length)
      {
        char[] value = new char[offset + length];
        System.arraycopy(holder_value, 0, value, 0, holder_value.length);
        return value;
      }
    else
      return holder_value;
  }

  /**
   * Read an array. In OMG specification is written that if the data does not
   * fit into the holder value field, that array must be resized. The
   * implementation follows this rule. If the holder value field contains null,
   * it is newly instantiated.
   */
  public void read_ulong_array(ULongSeqHolder holder, int offset, int length)
  {
    holder.value = ensureArray(holder.value, offset, length);
    read_ulong_array(holder.value, offset, length);
  }

  /**
   * Read an array. In OMG specification is written that if the data does not
   * fit into the holder value field, that array must be resized. The
   * implementation follows this rule. If the holder value field contains null,
   * it is newly instantiated.
   */
  public void read_long_array(LongSeqHolder holder, int offset, int length)
  {
    holder.value = ensureArray(holder.value, offset, length);
    read_ulong_array(holder.value, offset, length);
  }

  /**
   * If required, allocate or resize the int array to fit the newly read values.
   *
   * @param holder_value the existing int array, may be null.
   * @param offset the required offset to read.
   * @param length the length of the new sequence.
   *
   * @return the allocated or resized array, same array if no such operations
   * are required.
   */
  private int[] ensureArray(int[] holder_value, int offset, int length)
  {
    if (holder_value == null)
      return new int[offset + length];
    else if (holder_value.length < offset + length)
      {
        int[] value = new int[offset + length];
        System.arraycopy(holder_value, 0, value, 0, holder_value.length);
        return value;
      }
    else
      return holder_value;
  }

  /**
   * Read an array. In OMG specification is written that if the data does not
   * fit into the holder value field, that array must be resized. The
   * implementation follows this rule. If the holder value field contains null,
   * it is newly instantiated.
   */
  public void read_float_array(FloatSeqHolder holder, int offset, int length)
  {
    holder.value = ensureArray(holder.value, offset, length);
    read_float_array(holder.value, offset, length);
  }

  /**
   * If required, allocate or resize the float array to fit the newly read
   * values.
   *
   * @param holder_value the existing float array, may be null.
   * @param offset the required offset to read.
   * @param length the length of the new sequence.
   *
   * @return the allocated or resized array, same array if no such operations
   * are required.
   */
  private float[] ensureArray(float[] holder_value, int offset, int length)
  {
    if (holder_value == null)
      return new float[offset + length];
    else if (holder_value.length < offset + length)
      {
        float[] value = new float[offset + length];
        System.arraycopy(holder_value, 0, value, 0, holder_value.length);
        return value;
      }
    else
      return holder_value;
  }

  /**
   * Read an array. In OMG specification is written that if the data does not
   * fit into the holder value field, that array must be resized. The
   * implementation follows this rule. If the holder value field contains null,
   * it is newly instantiated.
   */
  public void read_double_array(DoubleSeqHolder holder, int offset, int length)
  {
    holder.value = ensureArray(holder.value, offset, length);
    read_double_array(holder.value, offset, length);
  }

  /**
   * If required, allocate or resize the double array to fit the newly read
   * values.
   *
   * @param holder_value the existing double array, may be null.
   * @param offset the required offset to read.
   * @param length the length of the new sequence.
   *
   * @return the allocated or resized array, same array if no such operations
   * are required.
   */
  private double[] ensureArray(double[] holder_value, int offset, int length)
  {
    if (holder_value == null)
      return new double[offset + length];
    else if (holder_value.length < offset + length)
      {
        double[] value = new double[offset + length];
        System.arraycopy(holder_value, 0, value, 0, holder_value.length);
        return value;
      }
    else
      return holder_value;
  }

  /**
   * Read an array. In OMG specification is written that if the data does not
   * fit into the holder value field, that array must be resized. The
   * implementation follows this rule. If the holder value field contains null,
   * it is newly instantiated.
   */
  public void read_short_array(ShortSeqHolder holder, int offset, int length)
  {
    holder.value = ensureArray(holder.value, offset, length);
    read_short_array(holder.value, offset, length);
  }

  /** {@inheritDoc} */
  public void read_ushort_array(UShortSeqHolder holder, int offset, int length)
  {
    holder.value = ensureArray(holder.value, offset, length);
    read_ushort_array(holder.value, offset, length);
  }

  /**
   * If required, allocate or resize the short array to fit the newly read
   * values.
   *
   * @param holder_value the existing short array, may be null.
   * @param offset the required offset to read.
   * @param length the length of the new sequence.
   *
   * @return the allocated or resized array, same array if no such operations
   * are required.
   */
  private short[] ensureArray(short[] holder_value, int offset, int length)
  {
    if (holder_value == null)
      return new short[offset + length];
    else if (holder_value.length < offset + length)
      {
        short[] value = new short[offset + length];
        System.arraycopy(holder_value, 0, value, 0, holder_value.length);
        return value;
      }
    else
      return holder_value;
  }

  /**
   * Read an array. In OMG specification is written that if the data does not
   * fit into the holder value field, that array must be resized. The
   * implementation follows this rule. If the holder value field contains null,
   * it is newly instantiated.
   */
  public void read_octet_array(OctetSeqHolder holder, int offset, int length)
  {
    holder.value = ensureArray(holder.value, offset, length);
    read_octet_array(holder.value, offset, length);
  }

  /**
   * If required, allocate or resize the byte array to fit the newly read
   * values.
   *
   * @param holder_value the existing byte array, may be null.
   * @param offset the required offset to read.
   * @param length the length of the new sequence.
   *
   * @return the allocated or resized array, same array if no such operations
   * are required.
   */
  private byte[] ensureArray(byte[] holder_value, int offset, int length)
  {
    if (holder_value == null)
      return new byte[offset + length];
    else if (holder_value.length < offset + length)
      {
        byte[] value = new byte[offset + length];
        System.arraycopy(holder_value, 0, value, 0, holder_value.length);
        return value;
      }
    else
      return holder_value;
  }

  /**
   * Read an array. In OMG specification is written that if the data does not
   * fit into the holder value field, that array must be resized. The
   * implementation follows this rule. If the holder value field contains null,
   * it is newly instantiated.
   */
  public void read_longlong_array(LongLongSeqHolder holder, int offset,
    int length)
  {
    holder.value = ensureArray(holder.value, offset, length);
    read_longlong_array(holder.value, offset, length);
  }

  /**
   * Read an array. In OMG specification is written that if the data does not
   * fit into the holder value field, that array must be resized. The
   * implementation follows this rule. If the holder value field contains null,
   * it is newly instantiated.
   */
  public void read_ulonglong_array(ULongLongSeqHolder holder, int offset,
    int length)
  {
    holder.value = ensureArray(holder.value, offset, length);
    read_ulonglong_array(holder.value, offset, length);
  }

  /**
   * If required, allocate or resize the array of longs to fit the newly read
   * values.
   *
   * @param holder_value the existing array, may be null.
   * @param offset the required offset to read.
   * @param length the length of the new sequence.
   *
   * @return the allocated or resized array, same array if no such operations
   * are required.
   */
  private long[] ensureArray(long[] holder_value, int offset, int length)
  {
    if (holder_value == null)
      return new long[offset + length];
    else if (holder_value.length < offset + length)
      {
        long[] value = new long[offset + length];
        System.arraycopy(holder_value, 0, value, 0, holder_value.length);
        return value;
      }
    else
      return holder_value;
  }

  /**
   * Read an array. In OMG specification is written that if the data does not
   * fit into the holder value field, that array must be resized. The
   * implementation follows this rule. If the holder value field contains null,
   * it is newly instantiated.
   */
  public void read_boolean_array(BooleanSeqHolder holder, int offset, int length)
  {
    holder.value = ensureArray(holder.value, offset, length);
    read_boolean_array(holder.value, offset, length);
  }

  /**
   * If required, allocate or resize the array of booleans to fit the newly read
   * values.
   *
   * @param holder_value the existing array of booleans, may be null.
   * @param offset the required offset to read.
   * @param length the length of the new sequence.
   *
   * @return the allocated or resized array, same array if no such operations
   * are required.
   */
  private boolean[] ensureArray(boolean[] holder_value, int offset, int length)
  {
    if (holder_value == null)
      return new boolean[offset + length];
    else if (holder_value.length < offset + length)
      {
        boolean[] value = new boolean[offset + length];
        System.arraycopy(holder_value, 0, value, 0, holder_value.length);
        return value;
      }
    else
      return holder_value;
  }

  /**
   * Read an array. In OMG specification is written that if the data does not
   * fit into the holder value field, that array must be resized. The
   * implementation follows this rule. If the holder value field contains null,
   * it is newly instantiated.
   */
  public void read_any_array(AnySeqHolder holder, int offset, int length)
  {
    holder.value = ensureArray(holder.value, offset, length);
    for (int i = offset; i < offset + length; i++)
      {
        holder.value[i] = read_any();
      }
  }

  /**
   * If required, allocate or resize the array of Anys to fit the newly read
   * values.
   *
   * @param holder_value the existing array of Anys, may be null.
   * @param offset the required offset to read.
   * @param length the length of the new sequence.
   *
   * @return the allocated or resized array, same array if no such operations
   * are required.
   */
  private Any[] ensureArray(Any[] holder_value, int offset, int length)
  {
    if (holder_value == null)
      return new Any[offset + length];
    else if (holder_value.length < offset + length)
      {
        Any[] value = new Any[offset + length];
        System.arraycopy(holder_value, 0, value, 0, holder_value.length);
        return value;
      }
    else
      return holder_value;
  }

  /**
   * This method is required to represent the DataInputStream as a value type
   * object.
   *
   * @return a single entity "IDL:omg.org/CORBA/DataInputStream:1.0", always.
   */
  public String[] _truncatable_ids()
  {
    return new String[] { "IDL:omg.org/CORBA/DataInputStream:1.0" };
  }
}
