// Copyright (c) 2006, 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 <string.h>

#include "common/convert_UTF.h"
#include "common/scoped_ptr.h"
#include "common/string_conversion.h"
#include "common/using_std_string.h"

namespace google_breakpad {

using std::vector;

void UTF8ToUTF16(const char *in, vector<uint16_t> *out) {
  size_t source_length = strlen(in);
  const UTF8 *source_ptr = reinterpret_cast<const UTF8 *>(in);
  const UTF8 *source_end_ptr = source_ptr + source_length;
  // Erase the contents and zero fill to the expected size
  out->clear();
  out->insert(out->begin(), source_length, 0);
  uint16_t *target_ptr = &(*out)[0];
  uint16_t *target_end_ptr = target_ptr + out->capacity();
  ConversionResult result = ConvertUTF8toUTF16(&source_ptr, source_end_ptr,
                                               &target_ptr, target_end_ptr,
                                               strictConversion);

  // Resize to be the size of the # of converted characters + NULL
  out->resize(result == conversionOK ? target_ptr - &(*out)[0] + 1: 0);
}

int UTF8ToUTF16Char(const char *in, int in_length, uint16_t out[2]) {
  const UTF8 *source_ptr = reinterpret_cast<const UTF8 *>(in);
  const UTF8 *source_end_ptr = source_ptr + 1;
  uint16_t *target_ptr = out;
  uint16_t *target_end_ptr = target_ptr + 2;
  out[0] = out[1] = 0;

  // Process one character at a time
  while (1) {
    ConversionResult result = ConvertUTF8toUTF16(&source_ptr, source_end_ptr,
                                                 &target_ptr, target_end_ptr,
                                                 strictConversion);

    if (result == conversionOK)
      return static_cast<int>(source_ptr - reinterpret_cast<const UTF8 *>(in));

    // Add another character to the input stream and try again
    source_ptr = reinterpret_cast<const UTF8 *>(in);
    ++source_end_ptr;

    if (source_end_ptr > reinterpret_cast<const UTF8 *>(in) + in_length)
      break;
  }

  return 0;
}

void UTF32ToUTF16(const wchar_t *in, vector<uint16_t> *out) {
  size_t source_length = wcslen(in);
  const UTF32 *source_ptr = reinterpret_cast<const UTF32 *>(in);
  const UTF32 *source_end_ptr = source_ptr + source_length;
  // Erase the contents and zero fill to the expected size
  out->clear();
  out->insert(out->begin(), source_length, 0);
  uint16_t *target_ptr = &(*out)[0];
  uint16_t *target_end_ptr = target_ptr + out->capacity();
  ConversionResult result = ConvertUTF32toUTF16(&source_ptr, source_end_ptr,
                                                &target_ptr, target_end_ptr,
                                                strictConversion);

  // Resize to be the size of the # of converted characters + NULL
  out->resize(result == conversionOK ? target_ptr - &(*out)[0] + 1: 0);
}

void UTF32ToUTF16Char(wchar_t in, uint16_t out[2]) {
  const UTF32 *source_ptr = reinterpret_cast<const UTF32 *>(&in);
  const UTF32 *source_end_ptr = source_ptr + 1;
  uint16_t *target_ptr = out;
  uint16_t *target_end_ptr = target_ptr + 2;
  out[0] = out[1] = 0;
  ConversionResult result = ConvertUTF32toUTF16(&source_ptr, source_end_ptr,
                                                &target_ptr, target_end_ptr,
                                                strictConversion);

  if (result != conversionOK) {
    out[0] = out[1] = 0;
  }
}

static inline uint16_t Swap(uint16_t value) {
  return (value >> 8) | static_cast<uint16_t>(value << 8);
}

string UTF16ToUTF8(const vector<uint16_t> &in, bool swap) {
  const UTF16 *source_ptr = &in[0];
  scoped_array<uint16_t> source_buffer;

  // If we're to swap, we need to make a local copy and swap each byte pair
  if (swap) {
    int idx = 0;
    source_buffer.reset(new uint16_t[in.size()]);
    UTF16 *source_buffer_ptr = source_buffer.get();
    for (vector<uint16_t>::const_iterator it = in.begin();
         it != in.end(); ++it, ++idx)
      source_buffer_ptr[idx] = Swap(*it);

    source_ptr = source_buffer.get();
  }

  // The maximum expansion would be 4x the size of the input string.
  const UTF16 *source_end_ptr = source_ptr + in.size();
  size_t target_capacity = in.size() * 4;
  scoped_array<UTF8> target_buffer(new UTF8[target_capacity]);
  UTF8 *target_ptr = target_buffer.get();
  UTF8 *target_end_ptr = target_ptr + target_capacity;
  ConversionResult result = ConvertUTF16toUTF8(&source_ptr, source_end_ptr,
                                               &target_ptr, target_end_ptr,
                                               strictConversion);

  if (result == conversionOK) {
    const char *targetPtr = reinterpret_cast<const char *>(target_buffer.get());
    return targetPtr;
  }

  return "";
}

}  // namespace google_breakpad
