/*
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "modules/encoding/TextDecoder.h"

#include "bindings/core/v8/ExceptionState.h"
#include "core/dom/DOMArrayBuffer.h"
#include "core/dom/DOMArrayBufferView.h"
#include "modules/encoding/Encoding.h"
#include "wtf/StringExtras.h"
#include "wtf/text/TextEncodingRegistry.h"

namespace blink {

TextDecoder* TextDecoder::create(const String& label,
                                 const TextDecoderOptions& options,
                                 ExceptionState& exceptionState) {
  WTF::TextEncoding encoding(
      label.stripWhiteSpace(&Encoding::isASCIIWhiteSpace));
  // The replacement encoding is not valid, but the Encoding API also
  // rejects aliases of the replacement encoding.
  if (!encoding.isValid() || !strcasecmp(encoding.name(), "replacement")) {
    exceptionState.throwRangeError("The encoding label provided ('" + label +
                                   "') is invalid.");
    return 0;
  }

  return new TextDecoder(encoding, options.fatal(), options.ignoreBOM());
}

TextDecoder::TextDecoder(const WTF::TextEncoding& encoding,
                         bool fatal,
                         bool ignoreBOM)
    : m_encoding(encoding),
      m_codec(newTextCodec(encoding)),
      m_fatal(fatal),
      m_ignoreBOM(ignoreBOM),
      m_bomSeen(false) {}

TextDecoder::~TextDecoder() {}

String TextDecoder::encoding() const {
  String name = String(m_encoding.name()).lower();
  // Where possible, encoding aliases should be handled by changes to Chromium's
  // ICU or Blink's WTF.  The same codec is used, but WTF maintains a different
  // name/identity for these.
  if (name == "iso-8859-1" || name == "us-ascii")
    return "windows-1252";
  return name;
}

String TextDecoder::decode(const BufferSource& input,
                           const TextDecodeOptions& options,
                           ExceptionState& exceptionState) {
  ASSERT(!input.isNull());
  if (input.isArrayBufferView()) {
    const char* start =
        static_cast<const char*>(input.getAsArrayBufferView()->baseAddress());
    size_t length = input.getAsArrayBufferView()->byteLength();
    return decode(start, length, options, exceptionState);
  }
  ASSERT(input.isArrayBuffer());
  const char* start =
      static_cast<const char*>(input.getAsArrayBuffer()->data());
  size_t length = input.getAsArrayBuffer()->byteLength();
  return decode(start, length, options, exceptionState);
}

String TextDecoder::decode(const char* start,
                           size_t length,
                           const TextDecodeOptions& options,
                           ExceptionState& exceptionState) {
  WTF::FlushBehavior flush = options.stream() ? WTF::DoNotFlush : WTF::DataEOF;

  bool sawError = false;
  String s = m_codec->decode(start, length, flush, m_fatal, sawError);

  if (m_fatal && sawError) {
    exceptionState.throwTypeError("The encoded data was not valid.");
    return String();
  }

  if (!m_ignoreBOM && !m_bomSeen && !s.isEmpty()) {
    m_bomSeen = true;
    String name(m_encoding.name());
    if ((name == "UTF-8" || name == "UTF-16LE" || name == "UTF-16BE") &&
        s[0] == 0xFEFF)
      s.remove(0);
  }

  if (flush)
    m_bomSeen = false;

  return s;
}

String TextDecoder::decode(ExceptionState& exceptionState) {
  TextDecodeOptions options;
  return decode(nullptr, 0, options, exceptionState);
}

}  // namespace blink
