/* Write one character (given as a Unicode value) to a stream.
This is called by both the one-byte and four-byte character APIs.
428189
function gli_put_char(str, ch) {
    if (!str || !str.writable)
        throw('gli_put_char: invalid stream');

    if (!str.unicode) {
        if (ch < 0 || ch >= 0x100)
            ch = 63;  // '?'
    }

    str.writecount += 1;
    
    switch (str.type) {
    case strtype_File:
        if (str.streaming) {
            if (!str.unicode) {
                str.buffer4[0] = ch;
                str.fstream.fwrite(str.buffer4, 1);
            }
            else {
                if (!str.isbinary) {
                    /* cheap UTF-8 stream */
                    var len;
                    if (ch < 0x10000) {
                        len = str.buffer4.write(String.fromCharCode(ch));
                        str.fstream.fwrite(str.buffer4, len); // utf8
                    }
                    else {
                        /* String.fromCharCode chokes on astral characters;
                           do it the hard way */
                        var arr8 = UniArrayToUTF8([ch]);
                        var buf = new str.fstream.BufferClass(arr8);
                        str.fstream.fwrite(buf);
                    }
                }
                else {
                    /* cheap big-endian stream */
                    str.buffer4.writeUInt32BE(ch, 0, true);
                    str.fstream.fwrite(str.buffer4, 4);
                }
            }
        }
        else {
            /* non-streaming... */
            gli_stream_dirty_file(str);
            if (!str.unicode || (ch < 0x80 && !str.isbinary)) {
                if (str.bufpos < str.buflen) {
                    str.buf[str.bufpos] = ch;
                    str.bufpos += 1;
                    if (str.bufpos > str.bufeof)
                        str.bufeof = str.bufpos;
                }
            }
            else {
                var arr;
                if (!str.isbinary)
                    arr = UniArrayToUTF8([ch]);
                else
                    arr = UniArrayToBE32([ch]);
                var len = arr.length;
                if (len > str.buflen-str.bufpos)
                    len = str.buflen-str.bufpos;
                for (ix=0; ix<len; ix++)
                    str.buf[str.bufpos+ix] = arr[ix];
                str.bufpos += len;
                if (str.bufpos > str.bufeof)
                    str.bufeof = str.bufpos;
            }
        }
        break;
    case strtype_Memory:
        if (str.bufpos < str.buflen) {
            str.buf[str.bufpos] = ch;
            str.bufpos += 1;
            if (str.bufpos > str.bufeof)
                str.bufeof = str.bufpos;
        }
        break;
    case strtype_Window:
        if (str.win.line_request)
            throw('gli_put_char: window has pending line request');
        gli_window_put_string(str.win, CharToString(ch));
        if (str.win.echostr)
            gli_put_char(str.win.echostr, ch);
        break;
    }
}
780703
public void write(byte []buf, int offset, int length, boolean isEnd)
    throws IOException
  {
    int end = offset + length;
    while (offset < end) {
      int ch1 = buf[offset++] & 0xff;

      if (ch1 < 0x80)
        os.write(ch1);
      else if ((ch1 & 0xe0) == 0xc0) {
        if (offset >= end)
          throw new EOFException("unexpected end of file in utf8 character");
        
        int ch2 = buf[offset++] & 0xff;
        if ((ch2 & 0xc0) != 0x80)
          throw new CharConversionException("illegal utf8 encoding");
      
        os.write(((ch1 & 0x1f) << 6) + (ch2 & 0x3f));
      }
      else if ((ch1 & 0xf0) == 0xe0) {
        if (offset + 1 >= end)
          throw new EOFException("unexpected end of file in utf8 character");
        
        int ch2 = buf[offset++] & 0xff;
        int ch3 = buf[offset++] & 0xff;
      
        if ((ch2 & 0xc0) != 0x80)
          throw new CharConversionException("illegal utf8 encoding");
      
        if ((ch3 & 0xc0) != 0x80)
          throw new CharConversionException("illegal utf8 encoding");
      
        os.write(((ch1 & 0x1f) << 12) + ((ch2 & 0x3f) << 6) + (ch3 & 0x3f));
      }
      else
        throw new CharConversionException("illegal utf8 encoding at (" +
                                          (int) ch1 + ")");
    }
  }
394301
public void writeUtf8(CharSequence string) {
    for (int i = 0, len = string.length(); i < len; i++) {
      char ch = string.charAt(i);
      if (ch < 0x80) { // 7-bit ASCII character
        writeByte(ch);
        // This could be an ASCII run, or possibly entirely ASCII
        while (i < len - 1) {
          ch = string.charAt(i + 1);
          if (ch >= 0x80) break;
          i++;
          writeByte(ch); // another 7-bit ASCII character
        }
      } else if (ch < 0x800) { // 11-bit character
        writeByte(0xc0 | (ch >> 6));
        writeByte(0x80 | (ch & 0x3f));
      } else if (ch < 0xd800 || ch > 0xdfff) { // 16-bit character
        writeByte(0xe0 | (ch >> 12));
        writeByte(0x80 | ((ch >> 6) & 0x3f));
        writeByte(0x80 | (ch & 0x3f));
      } else { // Possibly a 21-bit character
        if (!Character.isHighSurrogate(ch)) { // Malformed or not UTF-8
          writeByte('?');
          continue;
        }
        if (i == len - 1) { // Truncated or not UTF-8
          writeByte('?');
          break;
        }
        char low = string.charAt(++i);
        if (!Character.isLowSurrogate(low)) { // Malformed or not UTF-8
          writeByte('?');
          writeByte(Character.isHighSurrogate(low) ? '?' : low);
          continue;
        }
        // Write the 21-bit character using 4 bytes
        // See http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G2630
        int codePoint = Character.toCodePoint(ch, low);
        writeByte(0xf0 | (codePoint >> 18));
        writeByte(0x80 | ((codePoint >> 12) & 0x3f));
        writeByte(0x80 | ((codePoint >> 6) & 0x3f));
        writeByte(0x80 | (codePoint & 0x3f));
      }
    }
  }
955101
function eatCharacter(stream) {
        var first = stream.next();
        // Read special literals: backspace, newline, space, return.
        // Just read all lowercase letters.
        if (first.match(/[a-z]/) && stream.match(/[a-z]+/, true)) {
            return;
        }
        // Read unicode character: \u1000 \uA0a1
        if (first === "u") {
            stream.match(/[0-9a-z]{4}/i, true);
        }
    }
761227
function serializeStream(stream) {
      // 1. Let token be the result of reading from stream.
      // (Done in-place on array, rather than as a stream)

      // 2. If encoding is UTF-8, UTF-16BE, or UTF-16LE, and ignore
      // BOM flag and BOM seen flag are unset, run these subsubsteps:
      if (includes(['UTF-8', 'UTF-16LE', 'UTF-16BE'], this._encoding.name) &&
          !this._ignoreBOM && !this._BOMseen) {
        if (stream.length > 0 && stream[0] === 0xFEFF) {
          // 1. If token is U+FEFF, set BOM seen flag.
          this._BOMseen = true;
          stream.shift();
        } else if (stream.length > 0) {
          // 2. Otherwise, if token is not end-of-stream, set BOM seen
          // flag and append token to stream.
          this._BOMseen = true;
        } else {
          // 3. Otherwise, if token is not end-of-stream, append token
          // to output.
          // (no-op)
        }
      }
      // 4. Otherwise, return output.
      return codePointsToString(stream);
    }
1228085
@Override
    public Writer append(char c) throws IOException {
        singleCharBuffer[0]=(char)c;
        encodedAppender.append(encoder, null, singleCharBuffer, 0, 1);
        return this;
    }
627738
@Override
    public void write(char[] data, int offset, int length) throws IOException {
        while (true) {
            ensureBufferAvailable();
            if (buffer.remaining() > length) {
                buffer.backingBuffer().put(data, offset, length);
                break;
            } else if (buffer.remaining() == length) {
                buffer.backingBuffer().put(data, offset, length);
                flush(false);
                break;
            } else {
                int chunkSize = buffer.remaining();
                buffer.backingBuffer().put(data, offset, chunkSize);
                flush(false);
                length -= chunkSize;
                offset += chunkSize;
            }
        }
    }
139008
@Override
    public void write(int oneByte) {
        if (count == buf.length) {
            expand(1);
        }
        buf[count++] = (byte) oneByte;
    }
813425
private int readAndWriteText(Writer w)
        throws IOException, XMLStreamException
    {
        mTokenState = TOKEN_FULL_SINGLE; // we'll read it all

        /* We should be able to mostly just use the input buffer at this
         * point; exceptions being two-char linefeeds (when converting
         * to single ones) and entities (which likewise can expand or
         * shrink), both of which require flushing and/or single byte
         * output.
         */
        int start = mInputPtr;
        int count = 0;

        main_loop:
        while (true) {
	    char c;
            // Reached the end of buffer? Need to flush, then
            if (mInputPtr >= mInputEnd) {
                int len = mInputPtr - start;
                if (len > 0) {
                    w.write(mInputBuffer, start, len);
                    count += len;
                }
                c = getNextChar(SUFFIX_IN_TEXT);
                start = mInputPtr-1; // needs to be prior to char we got
            } else {
                c = mInputBuffer[mInputPtr++];
            }
            // Most common case is we don't have a special char, thus:
            if (c < CHAR_FIRST_PURE_TEXT) {
                if (c < CHAR_SPACE) {
                    if (c == '\n') {
                        markLF();
                    } else if (c == '\r') {
                        char d;
                        if (mInputPtr >= mInputEnd) {
                            /* If we can't peek easily, let's flush past stuff
                             * and load more... (have to flush, since new read
                             * will overwrite inbut buffers)
                             */
                            int len = mInputPtr - start;
                            if (len > 0) {
                                w.write(mInputBuffer, start, len);
                                count += len;
                            }
                            d = getNextChar(SUFFIX_IN_TEXT);
                            start = mInputPtr; // to mark 'no past content'
                        } else {
                            d = mInputBuffer[mInputPtr++];
                        }
                        if (d == '\n') {
                            if (mNormalizeLFs) {
                                /* Let's flush content prior to 2-char LF, and
                                 * start the new segment on the second char...
                                 * this way, no mods are needed for the buffer,
                                 * AND it'll also  work on split 2-char lf!
                                 */
                                int len = mInputPtr - 2 - start;
                                if (len > 0) {
                                    w.write(mInputBuffer, start, len);
                                    count += len;
                                }
                                start = mInputPtr-1; // so '\n' is the first char
                            } else {
                                ; // otherwise it's good as is
                            }
                        } else { // not 2-char... need to replace?
                            --mInputPtr;
                            if (mNormalizeLFs) {
                                mInputBuffer[mInputPtr-1] = '\n';
                            }
                        }
                        markLF();
                    } else if (c != '\t') {
                        throwInvalidSpace(c);
                    }
                } else if (c == '<') { // end is nigh!
                    break main_loop;
                } else if (c == '&') {
                    /* Have to flush all stuff, since entities pretty much
                     * force it; input buffer won't be contiguous
                     */
                    int len = mInputPtr - 1 - start; // -1 to remove ampersand
                    if (len > 0) {
                        w.write(mInputBuffer, start, len);
                        count += len;
                    }
                    int ch;
                    if (mCfgReplaceEntities) { // can we expand all entities?
                        if ((mInputEnd - mInputPtr) < 3
                            || (ch = resolveSimpleEntity(true)) == 0) {
                            ch = fullyResolveEntity(true);
                        }
                    } else {
                        ch = resolveCharOnlyEntity(true);
                        if (ch == 0) { // some other entity...
                            /* can't expand, so, let's just bail out... but
                             * let's also ensure no text is added twice, as
                             * all prev text was just flushed, but resolve
                             * may have moved input buffer around.
                             */
                            start = mInputPtr;
                            break main_loop;
                        }
                    }
                    if (ch != 0) {
                        if (ch <= 0xFFFF) {
                            c = (char) ch;
                        } else {
                            ch -= 0x10000;
                            w.write((char) ((ch >> 10)  + 0xD800));
                            c = (char) ((ch & 0x3FF)  + 0xDC00);
                        }
                        w.write(c);
                        ++count;
                    }
                    start = mInputPtr;
                } else if (c == '>') { // did we get ']]>'?
                    /* 21-Apr-2005, TSa: But we can NOT check the output buffer
                     *  (see comments in readTextSecondary() for details)
                     */
                    if (mInputPtr >= 2) { // can we do it here?
                        if (mInputBuffer[mInputPtr-2] == ']'
                            && mInputBuffer[mInputPtr-1] == ']') {
                            // Anything to flush?
                            int len = mInputPtr - start;
                            if (len > 0) {
                                w.write(mInputBuffer, start, len);
                            }
                            throwParseError(ErrorConsts.ERR_BRACKET_IN_TEXT);
                        }
                    } else {
                        ; // !!! TBI: how to check past boundary?
                    }
                } else if (c == CHAR_NULL) {
                    throwNullChar();
                }
            }
        } // while (true)

        /* Need to push back '<' or '&', whichever caused us to
         * get out...
         */
        --mInputPtr;

        // Anything left to flush?
        int len = mInputPtr - start;
        if (len > 0) {
            w.write(mInputBuffer, start, len);
            count += len;
        }
        return count;
    }
1244666
public static void writeUTF8WithLength(OutputStream out, String str) throws IOException {
        byte[] s = str.getBytes(UTF8);
        writeInt4(out, s.length);
        out.write(s);
    }
919786
private void write(final DataInputStream stream, final Writer outputWriter, final int numberOfBytes)
      throws IOException {
    final byte[] buf = new byte[65535];
    int lenRemaining = numberOfBytes;
    while (lenRemaining > 0) {
      final int len = stream.read(buf, 0, lenRemaining > 65535 ? 65535 : lenRemaining);
      if (len > 0) {
        outputWriter.write(new String(buf, 0, len, "UTF-8"));
        lenRemaining -= len;
      } else {
        break;
      }
    }
  }
1208090
public void writeValue(final int length, final int value)
		throws EncodingException
	{
		if (length > 31) {
			throw ErrorFactory.createEncodingException(
					ErrorKeys.DIFFTOOL_ENCODING_VALUE_OUT_OF_RANGE,
					"more than maximum length: " + value);
		}

		for (int i = length - 1; i >= 0; i--) {
			writeBit((value >> i) & 1);
		}
	}
762339
public void write(int b) throws IOException {
    // Take 24-bits from three octets, translate into four encoded chars
    // Break lines at 76 chars
    // If necessary, pad with 0 bits on the right at the end
    // Use = signs as padding at the end to ensure encodedLength % 4 == 0

    // Remove the sign bit,
    // thanks to Christian Schweingruber <chrigu@lorraine.ch>
    if (b < 0) {
      b += 256;
    }

    // First byte use first six bits, save last two bits
    if (charCount % 3 == 0) {
      int lookup = b >> 2;
      carryOver = b & 3; // last two bits
      out.write(chars[lookup]);
    }
    // Second byte use previous two bits and first four new bits,
    // save last four bits
    else if (charCount % 3 == 1) {
      int lookup = ((carryOver << 4) + (b >> 4)) & 63;
      carryOver = b & 15; // last four bits
      out.write(chars[lookup]);
    }
    // Third byte use previous four bits and first two new bits,
    // then use last six new bits
    else if (charCount % 3 == 2) {
      int lookup = ((carryOver << 2) + (b >> 6)) & 63;
      out.write(chars[lookup]);
      lookup = b & 63; // last six bits
      out.write(chars[lookup]);
      carryOver = 0;
    }
    charCount++;

    // Add newline every 76 output chars (that's 57 input chars)
    if (charCount % 57 == 0) {
      out.write('\n');
    }
  }
751289
private static int oneUcs4ToUtf8Char(byte[] utf8Buffer, int ucs4Char) {
        int utf8Length = 1;

        //JS_ASSERT(ucs4Char <= 0x7FFFFFFF);
        if ((ucs4Char & ~0x7F) == 0)
            utf8Buffer[0] = (byte)ucs4Char;
        else {
            int i;
            int a = ucs4Char >>> 11;
            utf8Length = 2;
            while (a != 0) {
                a >>>= 5;
                utf8Length++;
            }
            i = utf8Length;
            while (--i > 0) {
                utf8Buffer[i] = (byte)((ucs4Char & 0x3F) | 0x80);
                ucs4Char >>>= 6;
            }
            utf8Buffer[0] = (byte)(0x100 - (1 << (8-utf8Length)) + ucs4Char);
        }
        return utf8Length;
    }
245149
public void writeChar(char value) throws UnsupportedEncodingException {
    if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(this, tc, "writeChar", Character.valueOf(value));
    getBodyList().add(Character.valueOf(value));
    if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "writeChar");
  }
446969
private int write1(byte b[], int off, int len) throws IOException {
    eventStartWrite();

    try {
      if(count==0 && bytesSentInChunk + len>=buf.length) {
        // local buffer is empty and user data can fill the current chunk
        // checksum and output data
        final int length = buf.length - bytesSentInChunk;
        sum.update(b, off, length);
        writeChecksumChunk(b, off, length, false);
        // start a new chunk
        bytesSentInChunk = 0;
        return length;
      }
    
      // copy user data to local buffer
      int bytesToCopy = buf.length - bytesSentInChunk - count;
      bytesToCopy = (len<bytesToCopy) ? len : bytesToCopy;
      sum.update(b, off, bytesToCopy);
      System.arraycopy(b, off, buf, count, bytesToCopy);
      count += bytesToCopy;
      if (count + bytesSentInChunk == buf.length) {
        // local buffer is full
        flushBuffer(true, shouldKeepPartialChunkData());
      } 
      return bytesToCopy;
    } finally {
      eventEndWrite();
    }
  }
1188755
public static int writeLength(int valueLength, OutputStream out) throws IOException {
        if (valueLength < 128) {
            out.write(valueLength);
            return 1;
        } else if (valueLength < 16384) {
            out.write((valueLength >> 8) | 0x80);
            out.write(valueLength);
            return 2;
        } else if (valueLength < 2097152) {
            out.write((valueLength >> 16) | 0xc0);
            out.write(valueLength >> 8);
            out.write(valueLength);
            return 3;
        } else if (valueLength < 268435456) {
            out.write((valueLength >> 24) | 0xe0);
            out.write(valueLength >> 16);
            out.write(valueLength >> 8);
            out.write(valueLength);
            return 4;
        } else {
            out.write(0xf0);
            out.write(valueLength >> 24);
            out.write(valueLength >> 16);
            out.write(valueLength >> 8);
            out.write(valueLength);
            return 5;
        }
    }