content: // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
  // for details. All rights reserved. Use of this source code is governed by a
  // BSD-style license that can be found in the LICENSE file.
  
  part of dart.io;
  
  const SystemEncoding SYSTEM_ENCODING = const SystemEncoding();
  
  /**
   * The system encoding is the current code page on Windows and UTF-8 on
   * Linux and Mac.
   */
  class SystemEncoding extends Encoding {
    const SystemEncoding();
  
    String get name => 'system';
  
    List<int> encode(String input) => encoder.convert(input);
    String decode(List<int> encoded) => decoder.convert(encoded);
  
    Converter<String, List<int>> get encoder {
      if (Platform.operatingSystem == "windows") {
        return const _WindowsCodePageEncoder();
      } else {
        return const Utf8Encoder();
      }
    }
  
    Converter<List<int>, String> get decoder {
      if (Platform.operatingSystem == "windows") {
        return const _WindowsCodePageDecoder();
      } else {
        return const Utf8Decoder();
      }
    }
  }
  
  class _WindowsCodePageEncoder extends Converter<String, List<int>> {
  
    const _WindowsCodePageEncoder();
  
    List<int> convert(String input) {
      List<int> encoded = _encodeString(input);
      if (encoded == null) {
        throw new FormatException("Invalid character for encoding");
      }
      return encoded;
    }
  
    /**
     * Starts a chunked conversion.
     */
    StringConversionSink startChunkedConversion(
        ChunkedConversionSink<List<int>> sink) {
      return new _WindowsCodePageEncoderSink(sink);
    }
  
    // Override the base-class' bind, to provide a better type.
    Stream<List<int>> bind(Stream<String> stream) => super.bind(stream);
  
    external static List<int> _encodeString(String string);
  }
  
  class _WindowsCodePageEncoderSink extends StringConversionSinkBase {
    // TODO(floitsch): provide more efficient conversions when the input is
    // not a String.
  
    final ChunkedConversionSink<List<int>> _sink;
  
    _WindowsCodePageEncoderSink(this._sink);
  
    void close() {
      _sink.close();
    }
  
    void add(String string) {
      List<int> encoded = _WindowsCodePageEncoder._encodeString(string);
      if (encoded == null) {
        throw new FormatException("Invalid character for encoding");
      }
      _sink.add(encoded);
    }
  
    void addSlice(String source, int start, int end, bool isLast) {
      if (start != 0 || end != source.length) {
        source = source.substring(start, end);
      }
      add(source);
      if (isLast) close();
    }
  }
  
  
  class _WindowsCodePageDecoder extends Converter<List<int>, String> {
  
    const _WindowsCodePageDecoder();
  
    String convert(List<int> input) {
      return _decodeBytes(input);
    }
  
    /**
     * Starts a chunked conversion.
     */
    ByteConversionSink startChunkedConversion(
        ChunkedConversionSink<String> sink) {
      return new _WindowsCodePageDecoderSink(sink);
    }
  
    // Override the base-class' bind, to provide a better type.
    Stream<String> bind(Stream<List<int>> stream) => super.bind(stream);
  
    external static String _decodeBytes(List<int> bytes);
  }
  
  class _WindowsCodePageDecoderSink extends ByteConversionSinkBase {
    // TODO(floitsch): provide more efficient conversions when the input is
    // a slice.
  
    final ChunkedConversionSink<String> _sink;
  
    _WindowsCodePageDecoderSink(this._sink);
  
    void close() {
      _sink.close();
    }
  
    void add(List<int> bytes) {
      _sink.add(_WindowsCodePageDecoder._decodeBytes(bytes));
    }
  }
  