001/* PrintStream.java -- OutputStream for printing output
002   Copyright (C) 1998, 1999, 2001, 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010 
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package java.io;
040
041import java.util.Formatter;
042import java.util.Locale;
043
044import gnu.gcj.convert.UnicodeToBytes;
045
046/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
047 * "The Java Language Specification", ISBN 0-201-63451-1
048 * Status:  Believed complete and correct to 1.3
049 */
050
051/**
052 * This class prints Java primitive values and object to a stream as
053 * text.  None of the methods in this class throw an exception.  However,
054 * errors can be detected by calling the <code>checkError()</code> method.
055 * Additionally, this stream can be designated as "autoflush" when 
056 * created so that any writes are automatically flushed to the underlying
057 * output sink when the current line is terminated.
058 * <p>
059 * This class converts char's into byte's using the system default encoding.
060 *
061 * @author Aaron M. Renn (arenn@urbanophile.com)
062 * @author Tom Tromey (tromey@cygnus.com)
063 */
064public class PrintStream extends FilterOutputStream implements Appendable
065{
066  /* Notice the implementation is quite similar to OutputStreamWriter.
067   * This leads to some minor duplication, because neither inherits
068   * from the other, and we want to maximize performance. */
069
070  // Line separator string.
071  private static final char[] line_separator
072    = System.getProperty("line.separator").toCharArray();
073  
074  UnicodeToBytes converter;
075
076  // Work buffer of characters for converter.
077  char[] work = new char[100];
078  // Work buffer of bytes where we temporarily keep converter output.
079  byte[] work_bytes = new byte[100];
080
081  /**
082   * This boolean indicates whether or not an error has ever occurred
083   * on this stream.
084   */
085  private boolean error_occurred = false;
086
087  /**
088   * This is <code>true</code> if auto-flush is enabled, 
089   * <code>false</code> otherwise
090   */
091  private boolean auto_flush;
092
093  /**
094   * This method intializes a new <code>PrintStream</code> object to write
095   * to the specified output sink.
096   *
097   * @param out The <code>OutputStream</code> to write to.
098   */
099  public PrintStream (OutputStream out)
100  {
101    this (out, false);
102  }
103
104  /**
105   * This method intializes a new <code>PrintStream</code> object to write
106   * to the specified output sink.  This constructor also allows "auto-flush"
107   * functionality to be specified where the stream will be flushed after
108   * every <code>print</code> or <code>println</code> call, when the 
109   * <code>write</code> methods with array arguments are called, or when a 
110   * single new-line character is written.
111   * <p>
112   *
113   * @param out The <code>OutputStream</code> to write to.
114   * @param auto_flush <code>true</code> to flush the stream after every 
115   * line, <code>false</code> otherwise
116   */
117  public PrintStream (OutputStream out, boolean auto_flush)
118  {
119    super (out);
120
121    converter = UnicodeToBytes.getDefaultEncoder();
122    this.auto_flush = auto_flush;
123  }
124
125  /**
126   * This method intializes a new <code>PrintStream</code> object to write
127   * to the specified output sink.  This constructor also allows "auto-flush"
128   * functionality to be specified where the stream will be flushed after
129   * every <code>print</code> or <code>println</code> call, when the 
130   * <code>write</code> methods with array arguments are called, or when a 
131   * single new-line character is written.
132   * <p>
133   *
134   * @param out The <code>OutputStream</code> to write to.
135   * @param auto_flush <code>true</code> to flush the stream after every 
136   * line, <code>false</code> otherwise
137   * @param encoding The name of the character encoding to use for this
138   * object.
139   */
140  public PrintStream (OutputStream out, boolean auto_flush, String encoding)
141    throws UnsupportedEncodingException
142  {
143    super (out);
144
145    converter = UnicodeToBytes.getEncoder (encoding);
146    this.auto_flush = auto_flush;
147  }
148
149  /**
150   * This method checks to see if an error has occurred on this stream.  Note
151   * that once an error has occurred, this method will continue to report
152   * <code>true</code> forever for this stream.  Before checking for an
153   * error condition, this method flushes the stream.
154   *
155   * @return <code>true</code> if an error has occurred, 
156   * <code>false</code> otherwise
157   */
158  public boolean checkError ()
159  {
160    flush ();
161    return error_occurred;
162  }
163
164  /**
165   * This method can be called by subclasses to indicate that an error
166   * has occurred and should be reported by <code>checkError</code>.
167   */
168  protected void setError ()
169  {
170    error_occurred = true;
171  }
172
173  /**
174   * This method closes this stream and all underlying streams.
175   */
176  public void close ()
177  {
178    try
179      {
180        converter.setFinished();
181        writeChars(new char[0], 0, 0);
182        flush();
183        out.close();
184      }
185    catch (InterruptedIOException iioe)
186      {
187        Thread.currentThread().interrupt();
188      }
189    catch (IOException e)
190      {
191        setError ();
192      }
193  }
194
195  /**
196   * This method flushes any buffered bytes to the underlying stream and
197   * then flushes that stream as well.
198   */
199  public void flush ()
200  {
201    try
202      {
203        out.flush();
204      }
205    catch (InterruptedIOException iioe)
206      {
207        Thread.currentThread().interrupt();
208      }
209    catch (IOException e)
210      {
211        setError ();
212      }
213  }
214
215  private synchronized void print (String str, boolean println)
216  {
217    try
218      {
219        writeChars(str, 0, str.length());
220        if (println)
221          writeChars(line_separator, 0, line_separator.length);
222        if (auto_flush)
223          flush();
224      }
225    catch (InterruptedIOException iioe)
226      {
227        Thread.currentThread().interrupt();
228      }
229    catch (IOException e)
230      {
231        setError ();
232      }
233  }
234
235  private synchronized void print (char[] chars, int pos, int len,
236                                   boolean println)
237  {
238    try
239      {
240        writeChars(chars, pos, len);
241        if (println)
242          writeChars(line_separator, 0, line_separator.length);
243        if (auto_flush)
244          flush();
245      }
246    catch (InterruptedIOException iioe)
247      {
248        Thread.currentThread().interrupt();
249      }
250    catch (IOException e)
251      {
252        setError ();
253      }
254  }
255
256  private void writeChars(char[] buf, int offset, int count)
257    throws IOException
258  {
259    do
260      {
261        converter.setOutput(work_bytes, 0);
262        int converted = converter.write(buf, offset, count);
263        offset += converted;
264        count -= converted;
265        out.write(work_bytes, 0, converter.count);
266      }
267    while (count > 0 || converter.havePendingBytes());
268  }
269
270  private void writeChars(String str, int offset, int count)
271    throws IOException
272  {
273    do
274      {
275        converter.setOutput(work_bytes, 0);
276        int converted = converter.write(str, offset, count, work);
277        offset += converted;
278        count -= converted;
279        out.write(work_bytes, 0, converter.count);
280      }
281    while (count > 0 || converter.havePendingBytes());
282  }
283
284  /**
285   * This methods prints a boolean value to the stream.  <code>true</code>
286   * values are printed as "true" and <code>false</code> values are printed
287   * as "false".
288   *
289   * @param bool The <code>boolean</code> value to print
290   */
291  public void print (boolean bool)
292  {
293    print(String.valueOf(bool), false);
294  }
295
296  /**
297   * This method prints an integer to the stream.  The value printed is
298   * determined using the <code>String.valueOf()</code> method.
299   *
300   * @param inum The <code>int</code> value to be printed
301   */
302  public void print (int inum)
303  {
304    print(String.valueOf(inum), false);
305  }
306
307  /**
308   * This method prints a long to the stream.  The value printed is
309   * determined using the <code>String.valueOf()</code> method.
310   *
311   * @param lnum The <code>long</code> value to be printed
312   */
313  public void print (long lnum)
314  {
315    print(String.valueOf(lnum), false);
316  }
317
318  /**
319   * This method prints a float to the stream.  The value printed is
320   * determined using the <code>String.valueOf()</code> method.
321   *
322   * @param fnum The <code>float</code> value to be printed
323   */
324  public void print (float fnum)
325  {
326    print(String.valueOf(fnum), false);
327  }
328
329  /**
330   * This method prints a double to the stream.  The value printed is
331   * determined using the <code>String.valueOf()</code> method.
332   *
333   * @param dnum The <code>double</code> value to be printed
334   */
335  public void print (double dnum)
336  {
337    print(String.valueOf(dnum), false);
338  }
339
340  /**
341   * This method prints an <code>Object</code> to the stream.  The actual
342   * value printed is determined by calling the <code>String.valueOf()</code>
343   * method.
344   *
345   * @param obj The <code>Object</code> to print.
346   */
347  public void print (Object obj)
348  {
349    print(obj == null ? "null" : obj.toString(), false);
350  }
351
352  /**
353   * This method prints a <code>String</code> to the stream.  The actual
354   * value printed depends on the system default encoding.
355   *
356   * @param str The <code>String</code> to print.
357   */
358  public void print (String str)
359  {
360    print(str == null ? "null" : str, false);
361  }
362
363  /**
364   * This method prints a char to the stream.  The actual value printed is
365   * determined by the character encoding in use.
366   *
367   * @param ch The <code>char</code> value to be printed
368   */
369  public synchronized void print (char ch)
370  {
371    work[0] = ch;
372    print(work, 0, 1, false);
373  }
374
375  /**
376   * This method prints an array of characters to the stream.  The actual
377   * value printed depends on the system default encoding.
378   *
379   * @param charArray The array of characters to print.
380   */
381  public void print (char[] charArray)
382  {
383    print(charArray, 0, charArray.length, false);
384  }
385
386  /**
387   * This method prints a line separator sequence to the stream.  The value
388   * printed is determined by the system property <xmp>line.separator</xmp>
389   * and is not necessarily the Unix '\n' newline character.
390   */
391  public void println ()
392  {
393    print(line_separator, 0, line_separator.length, false);
394  }
395
396  /**
397   * This methods prints a boolean value to the stream.  <code>true</code>
398   * values are printed as "true" and <code>false</code> values are printed
399   * as "false".
400   * <p>
401   * This method prints a line termination sequence after printing the value.
402   *
403   * @param bool The <code>boolean</code> value to print
404   */
405  public void println (boolean bool)
406  {
407    print(String.valueOf(bool), true);
408  }
409
410  /**
411   * This method prints an integer to the stream.  The value printed is
412   * determined using the <code>String.valueOf()</code> method.
413   * <p>
414   * This method prints a line termination sequence after printing the value.
415   *
416   * @param inum The <code>int</code> value to be printed
417   */
418  public void println (int inum)
419  {
420    print(String.valueOf(inum), true);
421  }
422
423  /**
424   * This method prints a long to the stream.  The value printed is
425   * determined using the <code>String.valueOf()</code> method.
426   * <p>
427   * This method prints a line termination sequence after printing the value.
428   *
429   * @param lnum The <code>long</code> value to be printed
430   */
431  public void println (long lnum)
432  {
433    print(String.valueOf(lnum), true);
434  }
435
436  /**
437   * This method prints a float to the stream.  The value printed is
438   * determined using the <code>String.valueOf()</code> method.
439   * <p>
440   * This method prints a line termination sequence after printing the value.
441   *
442   * @param fnum The <code>float</code> value to be printed
443   */
444  public void println (float fnum)
445  {
446    print(String.valueOf(fnum), true);
447  }
448
449  /**
450   * This method prints a double to the stream.  The value printed is
451   * determined using the <code>String.valueOf()</code> method.
452   * <p>
453   * This method prints a line termination sequence after printing the value.
454   *
455   * @param dnum The <code>double</code> value to be printed
456   */
457  public void println (double dnum)
458  {
459    print(String.valueOf(dnum), true);
460  }
461
462  /**
463   * This method prints an <code>Object</code> to the stream.  The actual
464   * value printed is determined by calling the <code>String.valueOf()</code>
465   * method.
466   * <p>
467   * This method prints a line termination sequence after printing the value.
468   *
469   * @param obj The <code>Object</code> to print.
470   */
471  public void println (Object obj)
472  {
473    print(obj == null ? "null" : obj.toString(), true);
474  }
475
476  /**
477   * This method prints a <code>String</code> to the stream.  The actual
478   * value printed depends on the system default encoding.
479   * <p>
480   * This method prints a line termination sequence after printing the value.
481   *
482   * @param str The <code>String</code> to print.
483   */
484  public void println (String str)
485  {
486    print (str == null ? "null" : str, true);
487  }
488
489  /**
490   * This method prints a char to the stream.  The actual value printed is
491   * determined by the character encoding in use.
492   * <p>
493   * This method prints a line termination sequence after printing the value.
494   *
495   * @param ch The <code>char</code> value to be printed
496   */
497  public synchronized void println (char ch)
498  {
499    work[0] = ch;
500    print(work, 0, 1, true);
501  }
502
503  /**
504   * This method prints an array of characters to the stream.  The actual
505   * value printed depends on the system default encoding.
506   * <p>
507   * This method prints a line termination sequence after printing the value.
508   *
509   * @param charArray The array of characters to print.
510   */
511  public void println (char[] charArray)
512  {
513    print(charArray, 0, charArray.length, true);
514  }
515
516  /**
517   * This method writes a byte of data to the stream.  If auto-flush is
518   * enabled, printing a newline character will cause the stream to be
519   * flushed after the character is written.
520   * 
521   * @param oneByte The byte to be written
522   */
523  public void write (int oneByte)
524  {
525    try
526      {
527        out.write (oneByte & 0xff);
528        
529        if (auto_flush && (oneByte == '\n'))
530          flush ();
531      }
532    catch (InterruptedIOException iioe)
533      {
534        Thread.currentThread ().interrupt ();
535      }
536    catch (IOException e)
537      {
538        setError ();
539      }
540  }
541
542  /**
543   * This method writes <code>len</code> bytes from the specified array
544   * starting at index <code>offset</code> into the array.
545   *
546   * @param buffer The array of bytes to write
547   * @param offset The index into the array to start writing from
548   * @param len The number of bytes to write
549   */
550  public void write (byte[] buffer, int offset, int len)
551  {
552    try
553      {
554        out.write (buffer, offset, len);
555        
556        if (auto_flush)
557          flush ();
558      }
559    catch (InterruptedIOException iioe)
560      {
561        Thread.currentThread ().interrupt ();
562      }
563    catch (IOException e)
564      {
565        setError ();
566      }
567  }
568
569  /** @since 1.5 */
570  public PrintStream append(char c)
571  {
572    print(c);
573    return this;
574  }
575
576  /** @since 1.5 */
577  public PrintStream append(CharSequence cs)
578  {
579    print(cs == null ? "null" : cs.toString());
580    return this;
581  }
582
583  /** @since 1.5 */
584  public PrintStream append(CharSequence cs, int start, int end)
585  {
586    print(cs == null ? "null" : cs.subSequence(start, end).toString());
587    return this;
588  }
589
590  /** @since 1.5 */
591  public PrintStream printf(String format, Object... args)
592  {
593    return format(format, args);
594  }
595
596  /** @since 1.5 */
597  public PrintStream printf(Locale locale, String format, Object... args)
598  {
599    return format(locale, format, args);
600  }
601
602  /** @since 1.5 */
603  public PrintStream format(String format, Object... args)
604  {
605    return format(Locale.getDefault(), format, args);
606  }
607
608  /** @since 1.5 */
609  public PrintStream format(Locale locale, String format, Object... args)
610  {
611    Formatter f = new Formatter(this, locale);
612    f.format(format, args);
613    return this;
614  }
615} // class PrintStream
616