// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.

#ifndef COBALT_DOM_DATA_VIEW_H_
#define COBALT_DOM_DATA_VIEW_H_

#include <algorithm>

#include "build/build_config.h"
#include "cobalt/dom/array_buffer.h"
#include "cobalt/script/exception_state.h"
#include "cobalt/script/wrappable.h"

namespace cobalt {
namespace dom {

// DataView is used to access the underlying ArrayBuffer with support of common
// types and endianness.
//   https://www.khronos.org/registry/typedarray/specs/latest/#8
class DataView : public script::Wrappable {
 public:
  // Web API: DataView
  //
  DataView(const scoped_refptr<ArrayBuffer>& buffer,
           script::ExceptionState* exception_state);
  DataView(const scoped_refptr<ArrayBuffer>& buffer, uint32 byte_offset,
           script::ExceptionState* exception_state);
  DataView(const scoped_refptr<ArrayBuffer>& buffer, uint32 byte_offset,
           uint32 byte_length, script::ExceptionState* exception_state);

// C++ macro to generate accessor for each supported types.
#define DATA_VIEW_ACCESSOR_FOR_EACH(MacroOp)                                \
  MacroOp(Int8, int8) MacroOp(Uint8, uint8) MacroOp(Int16, int16)           \
      MacroOp(Uint16, uint16) MacroOp(Int32, int32) MacroOp(Uint32, uint32) \
      MacroOp(Float32, float) MacroOp(Float64, double)

// The following macro generates the accessors for each types listed above.
// According to the spec, For getter without an endianness parameter it is
// default to big endian.  Note that it may generate extra accessors for
// int8/uint8 which has an 'little_endian' parameter, this is redundant but
// should work as int8/uint8 behalf the same when accessed in any endian mode.
#define DEFINE_DATA_VIEW_ACCESSOR(DomType, CppType)                          \
  CppType Get##DomType(uint32 byte_offset,                                   \
                       script::ExceptionState* exception_state) const {      \
    return Get##DomType(byte_offset, false, exception_state);                \
  }                                                                          \
  CppType Get##DomType(uint32 byte_offset, bool little_endian,               \
                       script::ExceptionState* exception_state) const {      \
    return GetElement<CppType>(byte_offset, little_endian, exception_state); \
  }                                                                          \
  void Set##DomType(uint32 byte_offset, CppType value,                       \
                    script::ExceptionState* exception_state) {               \
    Set##DomType(byte_offset, value, false, exception_state);                \
  }                                                                          \
  void Set##DomType(uint32 byte_offset, CppType value, bool little_endian,   \
                    script::ExceptionState* exception_state) {               \
    SetElement<CppType>(byte_offset, value, little_endian, exception_state); \
  }

  DATA_VIEW_ACCESSOR_FOR_EACH(DEFINE_DATA_VIEW_ACCESSOR)
#undef DEFINE_DATA_VIEW_ACCESSOR

  // Web API: ArrayBufferView (implements)
  //
  const scoped_refptr<ArrayBuffer>& buffer() { return buffer_; }
  uint32 byte_offset() const { return byte_offset_; }
  uint32 byte_length() const { return byte_length_; }

  DEFINE_WRAPPABLE_TYPE(DataView);

 private:
  static void CopyBytes(const uint8* src, size_t size, bool little_endian,
                        uint8* dest) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
    bool need_reverse = !little_endian;
#else   // defined(ARCH_CPU_LITTLE_ENDIAN)
    bool need_reverse = little_endian;
#endif  // defined(ARCH_CPU_LITTLE_ENDIAN)
    if (need_reverse) {
#if defined(COMPILER_MSVC)
      std::reverse_copy(src, src + size,
                        stdext::checked_array_iterator<uint8*>(dest, size));
#else  // defined(COMPILER_MSVC)
      std::reverse_copy(src, src + size, dest);
#endif  // defined(COMPILER_MSVC)
    } else {
      memcpy(dest, src, size);
    }
  }

  template <typename ElementType>
  ElementType GetElement(uint32 byte_offset, bool little_endian,
                         script::ExceptionState* exception_state) const {
    if (byte_offset + sizeof(ElementType) > byte_length_) {
      exception_state->SetSimpleException(script::kOutsideBounds);
      // The return value will be ignored.
      return ElementType();
    }
    ElementType value;
    CopyBytes(buffer_->data() + byte_offset_ + byte_offset, sizeof(value),
              little_endian, reinterpret_cast<uint8*>(&value));
    return value;
  }

  template <typename ElementType>
  void SetElement(uint32 byte_offset, ElementType value, bool little_endian,
                  script::ExceptionState* exception_state) {
    if (byte_offset + sizeof(ElementType) > byte_length_) {
      exception_state->SetSimpleException(script::kOutsideBounds);
      return;
    }
    CopyBytes(reinterpret_cast<uint8*>(&value), sizeof(value), little_endian,
              buffer_->data() + byte_offset_ + byte_offset);
  }

  const scoped_refptr<ArrayBuffer> buffer_;
  const uint32 byte_offset_;
  const uint32 byte_length_;

  DISALLOW_COPY_AND_ASSIGN(DataView);
};

}  // namespace dom
}  // namespace cobalt

#endif  // COBALT_DOM_DATA_VIEW_H_
