// 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.convert;

/**
 * An instance of the default implementation of the [AsciiCodec].
 *
 * This instance provides a convenient access to the most common ASCII
 * use cases.
 *
 * Examples:
 *
 *     var encoded = ASCII.encode("This is ASCII!");
 *     var decoded = ASCII.decode([0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
 *                                 0x20, 0x41, 0x53, 0x43, 0x49, 0x49, 0x21]);
 */
const AsciiCodec ASCII = const AsciiCodec();

const int _ASCII_MASK = 0x7F;

/**
 * An [AsciiCodec] allows encoding strings as ASCII bytes
 * and decoding ASCII bytes to strings.
 */
class AsciiCodec extends Encoding {
  final bool _allowInvalid;
  /**
   * Instantiates a new [AsciiCodec].
   *
   * If [allowInvalid] is true, the [decode] method and the converter
   * returned by [decoder] will default to allowing invalid values.
   * If allowing invalid values, the values will be decoded into the Unicode
   * Replacement character (U+FFFD). If not, an exception will be thrown.
   * Calls to the [decode] method can choose to override this default.
   *
   * Encoders will not accept invalid (non Latin-1) characters.
   */
  const AsciiCodec({bool allowInvalid: false}) : _allowInvalid = allowInvalid;

  String get name => "us-ascii";

  /**
   * Decodes the ASCII [bytes] (a list of unsigned 7-bit integers) to the
   * corresponding string.
   *
   * If [bytes] contains values that are not in the range 0 .. 127, the decoder
   * will eventually throw a [FormatException].
   *
   * If [allowInvalid] is not provided, it defaults to the value used to create
   * this [AsciiCodec].
   */
  String decode(List<int> bytes, { bool allowInvalid }) {
    if (allowInvalid == null) allowInvalid = _allowInvalid;
    if (allowInvalid) {
      return const AsciiDecoder(allowInvalid: true).convert(bytes);
    } else {
      return const AsciiDecoder(allowInvalid: false).convert(bytes);
    }
  }

  AsciiEncoder get encoder => const AsciiEncoder();

  AsciiDecoder get decoder =>
      _allowInvalid ? const AsciiDecoder(allowInvalid: true)
                    : const AsciiDecoder(allowInvalid: false);
}

// Superclass for [AsciiEncoder] and [Latin1Encoder].
// Generalizes common operations that only differ by a mask;
class _UnicodeSubsetEncoder extends Converter<String, List<int>>
    implements ChunkedConverter<String, List<int>, String, List<int>> {

  final int _subsetMask;

  const _UnicodeSubsetEncoder(this._subsetMask);

  /**
   * Converts the [String] into a list of its code units.
   *
   * If [start] and [end] are provided, only the substring
   * `string.substring(start, end)` is used as input to the conversion.
   */
  List<int> convert(String string, [int start = 0, int end]) {
    int stringLength = string.length;
    RangeError.checkValidRange(start, end, stringLength);
    if (end == null) end = stringLength;
    int length = end - start;
    List<int> result = new Uint8List(length);
    for (int i = 0; i < length; i++) {
      var codeUnit = string.codeUnitAt(start + i);
      if ((codeUnit & ~_subsetMask) != 0) {
        throw new ArgumentError("String contains invalid characters.");
      }
      result[i] = codeUnit;
    }
    return result;
  }

  /**
   * Starts a chunked conversion.
   *
   * The converter works more efficiently if the given [sink] is a
   * [ByteConversionSink].
   */
  StringConversionSink startChunkedConversion(Sink<List<int>> sink) {
    if (sink is! ByteConversionSink) {
      sink = new ByteConversionSink.from(sink);
    }
    return new _UnicodeSubsetEncoderSink(_subsetMask, sink);
  }

  // Override the base-class' bind, to provide a better type.
  Stream<List<int>> bind(Stream<String> stream) => super.bind(stream);
}

/**
 * This class converts strings of only ASCII characters to bytes.
 */
class AsciiEncoder extends _UnicodeSubsetEncoder {
  const AsciiEncoder() : super(_ASCII_MASK);
}

/**
 * This class encodes chunked strings to bytes (unsigned 8-bit
 * integers).
 */
class _UnicodeSubsetEncoderSink extends StringConversionSinkBase {
  final ByteConversionSink _sink;
  final int _subsetMask;

  _UnicodeSubsetEncoderSink(this._subsetMask, this._sink);

  void close() {
    _sink.close();
  }

  void addSlice(String source, int start, int end, bool isLast) {
    RangeError.checkValidRange(start, end, source.length);
    for (int i = start; i < end; i++) {
      int codeUnit = source.codeUnitAt(i);
      if ((codeUnit & ~_subsetMask) != 0) {
        throw new ArgumentError(
            "Source contains invalid character with code point: $codeUnit.");
      }
    }
    _sink.add(source.codeUnits.sublist(start, end));
    if (isLast) {
      close();
    }
  }
}

/**
 * This class converts Latin-1 bytes (lists of unsigned 8-bit integers)
 * to a string.
 */
abstract class _UnicodeSubsetDecoder extends Converter<List<int>, String>
    implements ChunkedConverter<List<int>, String, List<int>, String> {

  final bool _allowInvalid;
  final int _subsetMask;

  /**
   * Instantiates a new decoder.
   *
   * The [_allowInvalid] argument defines how [convert] deals
   * with invalid bytes.
   *
   * The [_subsetMask] argument is a bit mask used to define the subset
   * of Unicode being decoded. Use [_LATIN1_MASK] for Latin-1 (8-bit) or
   * [_ASCII_MASK] for ASCII (7-bit).
   *
   * If [_allowInvalid] is `true`, [convert] replaces invalid bytes with the
   * Unicode Replacement character `U+FFFD` (�).
   * Otherwise it throws a [FormatException].
   */
  const _UnicodeSubsetDecoder(this._allowInvalid, this._subsetMask);

  /**
   * Converts the [bytes] (a list of unsigned 7- or 8-bit integers) to the
   * corresponding string.
   *
   * If [start] and [end] are provided, only the sub-list of bytes from
   * `start` to `end` (`end` not inclusive) is used as input to the conversion.
   */
  String convert(List<int> bytes, [int start = 0, int end]) {
    int byteCount = bytes.length;
    RangeError.checkValidRange(start, end, byteCount);
    if (end == null) end = byteCount;

    for (int i = start; i < end; i++) {
      int byte = bytes[i];
      if ((byte & ~_subsetMask) != 0) {
        if (!_allowInvalid) {
          throw new FormatException("Invalid value in input: $byte");
        }
        return _convertInvalid(bytes, start, end);
      }
    }
    return new String.fromCharCodes(bytes, start, end);
  }

  String _convertInvalid(List<int> bytes, int start, int end) {
    StringBuffer buffer = new StringBuffer();
    for (int i = start; i < end; i++) {
      int value = bytes[i];
      if ((value & ~_subsetMask) != 0) value = 0xFFFD;
      buffer.writeCharCode(value);
    }
    return buffer.toString();
  }

  /**
   * Starts a chunked conversion.
   *
   * The converter works more efficiently if the given [sink] is a
   * [StringConversionSink].
   */
  ByteConversionSink startChunkedConversion(Sink<String> sink);

  // Override the base-class's bind, to provide a better type.
  Stream<String> bind(Stream<List<int>> stream) => super.bind(stream);
}

class AsciiDecoder extends _UnicodeSubsetDecoder {
  const AsciiDecoder({bool allowInvalid: false})
      : super(allowInvalid, _ASCII_MASK);

  /**
   * Starts a chunked conversion.
   *
   * The converter works more efficiently if the given [sink] is a
   * [StringConversionSink].
   */
  ByteConversionSink startChunkedConversion(Sink<String> sink) {
    StringConversionSink stringSink;
    if (sink is StringConversionSink) {
      stringSink = sink;
    } else {
      stringSink = new StringConversionSink.from(sink);
    }
    // TODO(lrn): Use asUtf16Sink when it becomes available. It
    // works just as well, is likely to have less decoding overhead,
    // and make adding U+FFFD easier.
    // At that time, merge this with _Latin1DecoderSink;
    if (_allowInvalid) {
      return new _ErrorHandlingAsciiDecoderSink(stringSink.asUtf8Sink(false));
    } else {
      return new _SimpleAsciiDecoderSink(stringSink);
    }
  }
}

class _ErrorHandlingAsciiDecoderSink extends ByteConversionSinkBase {
  ByteConversionSink _utf8Sink;
  _ErrorHandlingAsciiDecoderSink(this._utf8Sink);

  void close() {
    _utf8Sink.close();
  }

  void add(List<int> source) {
    addSlice(source, 0, source.length, false);
  }

  void addSlice(List<int> source, int start, int end, bool isLast) {
    RangeError.checkValidRange(start, end, source.length);
    for (int i = start; i < end; i++) {
      if ((source[i] & ~_ASCII_MASK) != 0) {
        if (i > start) _utf8Sink.addSlice(source, start, i, false);
        // Add UTF-8 encoding of U+FFFD.
        _utf8Sink.add(const<int>[0xEF, 0xBF, 0xBD]);
        start = i + 1;
      }
    }
    if (start < end) {
      _utf8Sink.addSlice(source, start, end, isLast);
    } else if (isLast) {
      close();
    }
  }
}

class _SimpleAsciiDecoderSink extends ByteConversionSinkBase {
  Sink _sink;
  _SimpleAsciiDecoderSink(this._sink);

  void close() {
    _sink.close();
  }

  void add(List<int> source) {
    for (int i = 0; i < source.length; i++) {
      if ((source[i] & ~_ASCII_MASK) != 0) {
        throw new FormatException("Source contains non-ASCII bytes.");
      }
    }
    _sink.add(new String.fromCharCodes(source));
  }

  void addSlice(List<int> source, int start, int end, bool isLast) {
    final int length = source.length;
    RangeError.checkValidRange(start, end, length);
    if (start < end) {
      if (start != 0 || end != length) {
        source = source.sublist(start, end);
      }
      add(source);
    }
    if (isLast) close();
  }
}
