aboutsummaryrefslogtreecommitdiff
path: root/libjava/gnu/gcj/convert/CharsetToBytesAdaptor.java
blob: 4e9bcd5b4619d197645268544303be42c4eb1fcd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/* Copyright (C) 2005, 2006  Free Software Foundation

This file is part of libgcj.

This software is copyrighted work licensed under the terms of the
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
details.  */

package gnu.gcj.convert; 

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.CoderResult;
import gnu.java.nio.charset.EncodingHelper;

/**
 * Adaptor class that allow any {@link Charset} to be used
 * as a UnicodeToBytes converter.
 */
public class CharsetToBytesAdaptor extends UnicodeToBytes
{
  /**
   * The CharsetEncoder that does all the work.
   */
  private final CharsetEncoder encoder;

  /**
   * ByteBuffer wrapper for this.buf.
   */
  private ByteBuffer outBuf;

  /**
   * True if we've told the CharsetEncoder that there are no more
   * characters available.
   */
  private boolean closedEncoder;

  /**
   * True if we're finished.
   */
  private boolean finished;

  /**
   * Create a new CharsetToBytesAdaptor for the given Charset.
   *
   * @param cs The Charset.
   */
  public CharsetToBytesAdaptor(Charset cs)
  {
    this(cs.newEncoder());
  }

  /**
   * Create a new CharsetToBytesAdaptor for the given CharsetEncoder.
   *
   * @param enc The CharsetEncoder.
   */
  public CharsetToBytesAdaptor(CharsetEncoder enc)
  {
    encoder = enc;
    // Use default replacments on bad input so that we don't have to
    // deal with errors.
    encoder.onMalformedInput(CodingErrorAction.REPLACE);
    encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
  }

  /**
   * Return the encoder's name.  The backing Charset's name is
   * returned.
   *
   * @return The name.
   */
  public String getName()
  {
    return EncodingHelper.getOldCanonical(encoder.charset().name());
  }

  public int write (char[] inbuffer, int inpos, int inlength)
  {
    // Wrap the char array so it can be used by the encoder.
    CharBuffer b = CharBuffer.wrap(inbuffer, inpos, inlength);
    write(b);
    return b.position() - inpos; // Number of chars consumed.
  }

  public int write (String str, int inpos, int inlength, char work)
  {
    // Wrap the String so it can be used by the encoder.
    CharBuffer b = CharBuffer.wrap(str, inpos, inlength);
    write(b);
    return b.position() - inpos; // Number of chars consumed.
  }

  /**
   * Encode as much of inBuf as will fit in buf.  The number of
   * chars consumed is reflected by the new position of inBuf.  The
   * output is put in buf and count is incremented by the number of
   * bytes written.
   *
   * @param inBuf The input.
   */
  private void write(CharBuffer inBuf)
  {
    // Reuse existing outBuf if it is still wrapping the same array
    // it was created with.
    if (outBuf == null || !outBuf.hasArray() || outBuf.array() != buf)
      outBuf = ByteBuffer.wrap(buf);

    // Set the current position.
    outBuf.position(count);

    // If we've already said that there is no more input available,
    // then we simply try to flush again.
    if (closedEncoder)
      {
	CoderResult result = encoder.flush(outBuf);
	if (result == CoderResult.UNDERFLOW)
	  finished = true;
       }
    else
      {
	// Do the conversion.  If there are no characters to write,
	// then we are finished.
	closedEncoder = ! inBuf.hasRemaining();
	encoder.encode(inBuf, outBuf, closedEncoder);
      }

    // Mark the new end of buf.
    count = outBuf.position();
  }

  /**
   * Check for cached output in the converter.
   *
   * @return true if there is cached output that has not been
   * written to buf.
   */
  public boolean havePendingBytes()
  {
    return ! finished;
  }

  // These aren't cached.
  public void done()
  {
  }
}