// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_SNAPSHOT_SNAPSHOT_SOURCE_SINK_H_
#define V8_SNAPSHOT_SNAPSHOT_SOURCE_SINK_H_

#include <utility>

#include "src/base/atomicops.h"
#include "src/base/logging.h"
#include "src/common/globals.h"
#include "src/snapshot/snapshot-utils.h"
#include "src/utils/utils.h"

namespace v8 {
namespace internal {


/**
 * Source to read snapshot and builtins files from.
 *
 * Note: Memory ownership remains with callee.
 */
class SnapshotByteSource final {
 public:
  SnapshotByteSource(const char* data, int length)
      : data_(reinterpret_cast<const byte*>(data)),
        length_(length),
        position_(0) {}

  explicit SnapshotByteSource(Vector<const byte> payload)
      : data_(payload.begin()), length_(payload.length()), position_(0) {}

  ~SnapshotByteSource() = default;
  SnapshotByteSource(const SnapshotByteSource&) = delete;
  SnapshotByteSource& operator=(const SnapshotByteSource&) = delete;

  bool HasMore() { return position_ < length_; }

  byte Get() {
    DCHECK(position_ < length_);
    return data_[position_++];
  }

  byte Peek() const {
    DCHECK(position_ < length_);
    return data_[position_];
  }

  void Advance(int by) { position_ += by; }

  void CopyRaw(void* to, int number_of_bytes) {
    memcpy(to, data_ + position_, number_of_bytes);
    position_ += number_of_bytes;
  }

  void CopySlots(Address* dest, int number_of_slots) {
    base::AtomicWord* start = reinterpret_cast<base::AtomicWord*>(dest);
    base::AtomicWord* end = start + number_of_slots;
    for (base::AtomicWord* p = start; p < end;
         ++p, position_ += sizeof(base::AtomicWord)) {
      base::AtomicWord val;
      memcpy(&val, data_ + position_, sizeof(base::AtomicWord));
      base::Relaxed_Store(p, val);
    }
  }

#ifdef V8_COMPRESS_POINTERS
  void CopySlots(Tagged_t* dest, int number_of_slots) {
    AtomicTagged_t* start = reinterpret_cast<AtomicTagged_t*>(dest);
    AtomicTagged_t* end = start + number_of_slots;
    for (AtomicTagged_t* p = start; p < end;
         ++p, position_ += sizeof(AtomicTagged_t)) {
      AtomicTagged_t val;
      memcpy(&val, data_ + position_, sizeof(AtomicTagged_t));
      base::Relaxed_Store(p, val);
    }
  }
#endif

  inline int GetInt() {
    // This way of decoding variable-length encoded integers does not
    // suffer from branch mispredictions.
    DCHECK(position_ + 3 < length_);
    uint32_t answer = data_[position_];
    answer |= data_[position_ + 1] << 8;
    answer |= data_[position_ + 2] << 16;
    answer |= data_[position_ + 3] << 24;
    int bytes = (answer & 3) + 1;
    Advance(bytes);
    uint32_t mask = 0xffffffffu;
    mask >>= 32 - (bytes << 3);
    answer &= mask;
    answer >>= 2;
    return answer;
  }

  // Returns length.
  int GetBlob(const byte** data);

  int position() { return position_; }
  void set_position(int position) { position_ = position; }

  uint32_t GetChecksum() const {
    return Checksum(Vector<const byte>(data_, length_));
  }

 private:
  const byte* data_;
  int length_;
  int position_;
};

/**
 * Sink to write snapshot files to.
 *
 * Users must implement actual storage or i/o.
 */
class SnapshotByteSink {
 public:
  SnapshotByteSink() = default;
  explicit SnapshotByteSink(int initial_size) : data_(initial_size) {}

  ~SnapshotByteSink() = default;

  void Put(byte b, const char* description) { data_.push_back(b); }

  void PutInt(uintptr_t integer, const char* description);
  void PutRaw(const byte* data, int number_of_bytes, const char* description);

  void Append(const SnapshotByteSink& other);
  int Position() const { return static_cast<int>(data_.size()); }

  const std::vector<byte>* data() const { return &data_; }

 private:
  std::vector<byte> data_;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_SNAPSHOT_SNAPSHOT_SOURCE_SINK_H_
