/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 <geode/DataInput.hpp>

#include "CacheRegionHelper.hpp"
#include "SerializationRegistry.hpp"
#include "CacheImpl.hpp"
#include "util/string.hpp"
#include "util/JavaModifiedUtf8.hpp"
#include <geode/PoolManager.hpp>

namespace apache {
namespace geode {
namespace client {

DataInput::DataInput(const uint8_t* buffer, size_t len,
                     const CacheImpl* cache, Pool* pool)
    : m_buf(buffer),
      m_bufHead(buffer),
      m_bufLength(len),
      m_pool(pool),
      m_cache(cache) {}

std::shared_ptr<Serializable> DataInput::readObjectInternal(int8_t typeId) {
  return getSerializationRegistry().deserialize(*this, typeId);
}

const SerializationRegistry& DataInput::getSerializationRegistry() const {
  return *m_cache->getSerializationRegistry();
}

Cache* DataInput::getCache() const { return m_cache->getCache(); }

template <class _Traits, class _Allocator>
void DataInput::readJavaModifiedUtf8(
    std::basic_string<char, _Traits, _Allocator>& value) {
  // TODO string OPTIMIZE skip intermediate utf16 string
  std::u16string utf16;
  readJavaModifiedUtf8(utf16);
  value = to_utf8(utf16);
}
template APACHE_GEODE_EXPLICIT_TEMPLATE_EXPORT void
DataInput::readJavaModifiedUtf8(std::string&);

template <class _Traits, class _Allocator>
void DataInput::readJavaModifiedUtf8(
    std::basic_string<char16_t, _Traits, _Allocator>& value) {
  uint16_t length = readInt16();
  _GEODE_CHECK_BUFFER_SIZE(length);
  value =
      JavaModifiedUtf8::decode(reinterpret_cast<const char*>(m_buf), length);
  advanceCursor(length);
}
template APACHE_GEODE_EXPLICIT_TEMPLATE_EXPORT void
DataInput::readJavaModifiedUtf8(std::u16string&);

template <class _Traits, class _Allocator>
void DataInput::readJavaModifiedUtf8(
    std::basic_string<char32_t, _Traits, _Allocator>& value) {
  // TODO string OPTIMIZE convert from UTF-16 to UCS-4 directly
  std::u16string utf16;
  readJavaModifiedUtf8(utf16);
  value = to_ucs4(utf16);
}
template APACHE_GEODE_EXPLICIT_TEMPLATE_EXPORT void
DataInput::readJavaModifiedUtf8(std::u32string&);

template <class _Traits, class _Allocator>
void DataInput::readUtf16Huge(
    std::basic_string<char, _Traits, _Allocator>& value) {
  // TODO string OPTIMIZE skip intermediate utf16 string
  std::u16string utf16;
  readUtf16Huge(utf16);
  value = to_utf8(utf16);
}
template APACHE_GEODE_EXPLICIT_TEMPLATE_EXPORT void DataInput::readUtf16Huge(
    std::string&);

template <class _Traits, class _Allocator>
void DataInput::readUtf16Huge(
    std::basic_string<char32_t, _Traits, _Allocator>& value) {
  // TODO string OPTIMIZE convert from UTF-16 to UCS-4 directly
  std::u16string utf16;
  readUtf16Huge(utf16);
  value = to_ucs4(utf16);
}
template APACHE_GEODE_EXPLICIT_TEMPLATE_EXPORT void DataInput::readUtf16Huge(
    std::u32string&);

}  // namespace client
}  // namespace geode
}  // namespace apache
