// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/strings/utf_offset_string_conversions.h"

#include <algorithm>

#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversion_utils.h"

namespace base {

// Converts the given source Unicode character type to the given destination
// Unicode character type as a STL string. The given input buffer and size
// determine the source, and the given output STL string will be replaced by
// the result.
template<typename SrcChar, typename DestStdString>
bool ConvertUnicode(const SrcChar* src,
                    size_t src_len,
                    DestStdString* output,
                    std::vector<size_t>* offsets_for_adjustment) {
  if (offsets_for_adjustment) {
    std::for_each(offsets_for_adjustment->begin(),
                  offsets_for_adjustment->end(),
                  LimitOffset<DestStdString>(src_len));
  }

  // ICU requires 32-bit numbers.
  bool success = true;
  OffsetAdjuster offset_adjuster(offsets_for_adjustment);
  int32 src_len32 = static_cast<int32>(src_len);
  for (int32 i = 0; i < src_len32; i++) {
    uint32 code_point;
    size_t original_i = i;
    size_t chars_written = 0;
    if (ReadUnicodeCharacter(src, src_len32, &i, &code_point)) {
      chars_written = WriteUnicodeCharacter(code_point, output);
    } else {
      chars_written = WriteUnicodeCharacter(0xFFFD, output);
      success = false;
    }
    if (offsets_for_adjustment) {
      // NOTE: ReadUnicodeCharacter() adjusts |i| to point _at_ the last
      // character read, not after it (so that incrementing it in the loop
      // increment will place it at the right location), so we need to account
      // for that in determining the amount that was read.
      offset_adjuster.Add(OffsetAdjuster::Adjustment(original_i,
          i - original_i + 1, chars_written));
    }
  }
  return success;
}

bool UTF8ToUTF16AndAdjustOffset(const char* src,
                                size_t src_len,
                                string16* output,
                                size_t* offset_for_adjustment) {
  std::vector<size_t> offsets;
  if (offset_for_adjustment)
    offsets.push_back(*offset_for_adjustment);
  PrepareForUTF16Or32Output(src, src_len, output);
  bool ret = ConvertUnicode(src, src_len, output, &offsets);
  if (offset_for_adjustment)
    *offset_for_adjustment = offsets[0];
  return ret;
}

bool UTF8ToUTF16AndAdjustOffsets(const char* src,
                                 size_t src_len,
                                 string16* output,
                                 std::vector<size_t>* offsets_for_adjustment) {
  PrepareForUTF16Or32Output(src, src_len, output);
  return ConvertUnicode(src, src_len, output, offsets_for_adjustment);
}

string16 UTF8ToUTF16AndAdjustOffset(const base::StringPiece& utf8,
                                        size_t* offset_for_adjustment) {
  std::vector<size_t> offsets;
  if (offset_for_adjustment)
    offsets.push_back(*offset_for_adjustment);
  string16 result;
  UTF8ToUTF16AndAdjustOffsets(utf8.data(), utf8.length(), &result,
                              &offsets);
  if (offset_for_adjustment)
    *offset_for_adjustment = offsets[0];
  return result;
}

string16 UTF8ToUTF16AndAdjustOffsets(
    const base::StringPiece& utf8,
    std::vector<size_t>* offsets_for_adjustment) {
  string16 result;
  UTF8ToUTF16AndAdjustOffsets(utf8.data(), utf8.length(), &result,
                              offsets_for_adjustment);
  return result;
}

std::string UTF16ToUTF8AndAdjustOffset(
    const base::StringPiece16& utf16,
    size_t* offset_for_adjustment) {
  std::vector<size_t> offsets;
  if (offset_for_adjustment)
    offsets.push_back(*offset_for_adjustment);
  std::string result = UTF16ToUTF8AndAdjustOffsets(utf16, &offsets);
  if (offset_for_adjustment)
    *offset_for_adjustment = offsets[0];
  return result;
}

std::string UTF16ToUTF8AndAdjustOffsets(
    const base::StringPiece16& utf16,
    std::vector<size_t>* offsets_for_adjustment) {
  std::string result;
  PrepareForUTF8Output(utf16.data(), utf16.length(), &result);
  ConvertUnicode(utf16.data(), utf16.length(), &result, offsets_for_adjustment);
  return result;
}

OffsetAdjuster::Adjustment::Adjustment(size_t original_offset,
                                       size_t original_length,
                                       size_t output_length)
    : original_offset(original_offset),
      original_length(original_length),
      output_length(output_length) {
}

OffsetAdjuster::OffsetAdjuster(std::vector<size_t>* offsets_for_adjustment)
    : offsets_for_adjustment_(offsets_for_adjustment) {
}

OffsetAdjuster::~OffsetAdjuster() {
  if (!offsets_for_adjustment_ || adjustments_.empty())
    return;
  for (std::vector<size_t>::iterator i(offsets_for_adjustment_->begin());
       i != offsets_for_adjustment_->end(); ++i)
    AdjustOffset(i);
}

void OffsetAdjuster::Add(const Adjustment& adjustment) {
  adjustments_.push_back(adjustment);
}

void OffsetAdjuster::AdjustOffset(std::vector<size_t>::iterator offset) {
  if (*offset == string16::npos)
    return;
  size_t adjustment = 0;
  for (std::vector<Adjustment>::const_iterator i = adjustments_.begin();
       i != adjustments_.end(); ++i) {
    if (*offset <= i->original_offset)
      break;
    if (*offset < (i->original_offset + i->original_length)) {
      *offset = string16::npos;
      return;
    }
    adjustment += (i->original_length - i->output_length);
  }
  *offset -= adjustment;
}

}  // namespace base
