/* 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" };
  }
}