/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "libcore_util_CharsetUtils.h"

#include <string.h>

#include "dex/utf-inl.h"
#include "handle_scope-inl.h"
#include "jni/jni_internal.h"
#include "mirror/string-inl.h"
#include "mirror/string.h"
#include "native_util.h"
#include "nativehelper/scoped_primitive_array.h"
#include "nativehelper/jni_macros.h"
#include "scoped_fast_native_object_access-inl.h"

namespace art {

static void CharsetUtils_asciiBytesToChars(JNIEnv* env, jclass, jbyteArray javaBytes, jint offset,
                                           jint length, jcharArray javaChars) {
  ScopedByteArrayRO bytes(env, javaBytes);
  if (bytes.get() == nullptr) {
    return;
  }
  ScopedCharArrayRW chars(env, javaChars);
  if (chars.get() == nullptr) {
    return;
  }

  const jbyte* src = &bytes[offset];
  jchar* dst = &chars[0];
  static const jchar REPLACEMENT_CHAR = 0xfffd;
  for (int i = length - 1; i >= 0; --i) {
    jchar ch = static_cast<jchar>(*src++ & 0xff);
    *dst++ = (ch <= 0x7f) ? ch : REPLACEMENT_CHAR;
  }
}

/**
 * Translates the given characters to US-ASCII or ISO-8859-1 bytes, using the fact that
 * Unicode code points between U+0000 and U+007f inclusive are identical to US-ASCII, while
 * U+0000 to U+00ff inclusive are identical to ISO-8859-1.
 */
static jbyteArray charsToBytes(JNIEnv* env, jstring java_string, jint offset, jint length,
                               jchar maxValidChar) {
  ScopedFastNativeObjectAccess soa(env);
  StackHandleScope<1> hs(soa.Self());
  Handle<mirror::String> string(hs.NewHandle(soa.Decode<mirror::String>(java_string)));
  if (string == nullptr) {
    return nullptr;
  }

  ObjPtr<mirror::ByteArray> result = mirror::ByteArray::Alloc(soa.Self(), length);
  if (result == nullptr) {
    return nullptr;
  }

  if (string->IsCompressed()) {
    // All characters in a compressed string are ASCII and therefore do not need a replacement.
    DCHECK_GE(maxValidChar, 0x7f);
    memcpy(result->GetData(), string->GetValueCompressed() + offset, length);
  } else {
    const uint16_t* src = string->GetValue() + offset;
    auto clamp = [maxValidChar](uint16_t c) {
      return static_cast<jbyte>(dchecked_integral_cast<uint8_t>((c > maxValidChar) ? '?' : c));
    };
    std::transform(src, src + length, result->GetData(), clamp);
  }
  return soa.AddLocalReference<jbyteArray>(result);
}

static jbyteArray CharsetUtils_toAsciiBytes(JNIEnv* env, jclass, jstring java_string, jint offset,
                                            jint length) {
    return charsToBytes(env, java_string, offset, length, 0x7f);
}

static jbyteArray CharsetUtils_toIsoLatin1Bytes(JNIEnv* env, jclass, jstring java_string,
                                                jint offset, jint length) {
    return charsToBytes(env, java_string, offset, length, 0xff);
}

static jbyteArray CharsetUtils_toUtf8Bytes(JNIEnv* env, jclass, jstring java_string, jint offset,
                                           jint length) {
  ScopedFastNativeObjectAccess soa(env);
  StackHandleScope<1> hs(soa.Self());
  Handle<mirror::String> string(hs.NewHandle(soa.Decode<mirror::String>(java_string)));
  if (string == nullptr) {
    return nullptr;
  }

  DCHECK_GE(offset, 0);
  DCHECK_LE(offset, string->GetLength());
  DCHECK_GE(length, 0);
  DCHECK_LE(length, string->GetLength() - offset);

  bool compressed = string->IsCompressed();
  size_t utf8_length = 0;
  if (compressed) {
    utf8_length = length;
  } else {
    const uint16_t* utf16 = string->GetValue() + offset;
    auto count_length = [&utf8_length](jbyte c ATTRIBUTE_UNUSED) ALWAYS_INLINE { ++utf8_length; };
    ConvertUtf16ToUtf8</*kUseShortZero=*/ true,
                       /*kUse4ByteSequence=*/ true,
                       /*kReplaceBadSurrogates=*/ true>(utf16, length, count_length);
  }
  ObjPtr<mirror::ByteArray> result =
      mirror::ByteArray::Alloc(soa.Self(), dchecked_integral_cast<int32_t>(utf8_length));
  if (result == nullptr) {
    return nullptr;
  }

  if (compressed) {
    memcpy(result->GetData(), string->GetValueCompressed() + offset, length);
  } else {
    const uint16_t* utf16 = string->GetValue() + offset;
    int8_t* data = result->GetData();
    auto store_data = [&data](jbyte c) ALWAYS_INLINE { *data++ = c; };
    ConvertUtf16ToUtf8</*kUseShortZero=*/ true,
                       /*kUse4ByteSequence=*/ true,
                       /*kReplaceBadSurrogates=*/ true>(utf16, length, store_data);
  }
  return soa.AddLocalReference<jbyteArray>(result);
}

static JNINativeMethod gMethods[] = {
  FAST_NATIVE_METHOD(CharsetUtils, asciiBytesToChars, "([BII[C)V"),
  FAST_NATIVE_METHOD(CharsetUtils, toAsciiBytes, "(Ljava/lang/String;II)[B"),
  FAST_NATIVE_METHOD(CharsetUtils, toIsoLatin1Bytes, "(Ljava/lang/String;II)[B"),
  FAST_NATIVE_METHOD(CharsetUtils, toUtf8Bytes, "(Ljava/lang/String;II)[B"),
};

void register_libcore_util_CharsetUtils(JNIEnv* env) {
  REGISTER_NATIVE_METHODS("libcore/util/CharsetUtils");
}

}  // namespace art
