chromium/services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_buffer_android.cc

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_buffer_android.h"

#include "base/check.h"
#include "services/tracing/public/cpp/perfetto/java_heap_profiler/hprof_data_type_android.h"

namespace tracing {

HprofBuffer::HprofBuffer(const unsigned char* data, size_t size)
    : data_(data), size_(size) {}

uint32_t HprofBuffer::GetOneByte() {
  return GetUInt32FromBytes(1);
}

uint32_t HprofBuffer::GetTwoBytes() {
  return GetUInt32FromBytes(2);
}

uint32_t HprofBuffer::GetFourBytes() {
  return GetUInt32FromBytes(4);
}

uint64_t HprofBuffer::GetId() {
  return GetUInt64FromBytes(object_id_size_in_bytes_);
}

uint32_t HprofBuffer::GetUInt32FromBytes(size_t num_bytes) {
  uint32_t val = 0;
  for (size_t i = 0; i < num_bytes; ++i) {
    val = (val << 8) + GetByte();
  }
  return val;
}

uint64_t HprofBuffer::GetUInt64FromBytes(size_t num_bytes) {
  uint64_t val = 0;
  for (size_t i = 0; i < num_bytes; ++i) {
    val = (val << 8) + GetByte();
  }
  return val;
}

bool HprofBuffer::HasRemaining() {
  return offset_ < size_;
}

void HprofBuffer::set_id_size(unsigned id_size) {
  DCHECK(id_size == 4 || id_size == 8);
  object_id_size_in_bytes_ = id_size;
}

void HprofBuffer::set_position(size_t new_position) {
  DCHECK(new_position <= size_ && new_position >= 0);
  offset_ = new_position;
}

// Skips |delta| bytes in the buffer.
void HprofBuffer::Skip(uint32_t delta) {
  set_position(offset_ + delta);
}

void HprofBuffer::SkipBytesByType(DataType type) {
  Skip(SizeOfType(type));
}

void HprofBuffer::SkipId() {
  Skip(object_id_size_in_bytes_);
}

const char* HprofBuffer::DataPosition() {
  return reinterpret_cast<const char*>((data_ + offset_).get());
}

uint32_t HprofBuffer::SizeOfType(uint32_t index) {
  uint32_t object_size = kTypeSizes[index];

  // If type is object, return id_size.
  return object_size == 0 ? object_id_size_in_bytes_ : object_size;
}

unsigned char HprofBuffer::GetByte() {
  DCHECK(HasRemaining());
  unsigned char byte = data_[offset_];
  ++offset_;
  return byte;
}

}  // namespace tracing