// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "util.h"

#include <cctype>
#include <cinttypes>

#include <zircon/status.h>

#include "garnet/lib/debugger_utils/byte_block.h"
#include "garnet/lib/debugger_utils/util.h"

#include "lib/fxl/logging.h"
#include "lib/fxl/strings/string_number_conversions.h"
#include "lib/fxl/strings/string_printf.h"

namespace debugserver {
namespace util {

std::string BuildErrorPacket(ErrorCode error_code) {
  std::string errstr =
      fxl::NumberToString<unsigned int>(static_cast<unsigned int>(error_code));
  if (errstr.length() == 1)
    errstr = "0" + errstr;
  return "E" + errstr;
}

bool ParseThreadId(const fxl::StringView& bytes,
                   bool* out_has_pid,
                   int64_t* out_pid,
                   int64_t* out_tid) {
  FXL_DCHECK(out_tid);
  FXL_DCHECK(out_has_pid);
  FXL_DCHECK(out_pid);

  if (bytes.empty())
    return false;

  if (bytes[0] != 'p') {
    *out_has_pid = false;
    return fxl::StringToNumberWithError<int64_t>(bytes, out_tid,
                                                 fxl::Base::k16);
  }

  *out_has_pid = true;

  // The pid and the tid are separated by a ".".
  size_t dot;
  bool found_dot = false;
  for (size_t i = 1; i < bytes.size(); i++) {
    if (bytes[i] != '.')
      continue;
    dot = i;
    found_dot = true;
    break;
  }

  // If there's no dot then tid is set to -1 (meaning all threads).
  if (!found_dot) {
    *out_tid = -1;
    return fxl::StringToNumberWithError<int64_t>(bytes.substr(1, dot - 1),
                                                 out_pid, fxl::Base::k16);
  }

  if (!fxl::StringToNumberWithError<int64_t>(bytes.substr(1, dot - 1), out_pid,
                                             fxl::Base::k16))
    return false;

  return fxl::StringToNumberWithError<int64_t>(bytes.substr(dot + 1), out_tid,
                                               fxl::Base::k16);
}

std::string EncodeThreadId(zx_koid_t pid, zx_koid_t tid) {
  std::string pid_string = fxl::NumberToString<zx_koid_t>(pid, fxl::Base::k16);
  std::string tid_string = fxl::NumberToString<zx_koid_t>(tid, fxl::Base::k16);

  return fxl::StringPrintf("p%s.%s", pid_string.c_str(), tid_string.c_str());
}

bool FindUnescapedChar(const char val,
                       const fxl::StringView& packet,
                       size_t* out_index) {
  FXL_DCHECK(out_index);

  size_t i;
  bool found = false;
  bool in_escape = false;
  for (i = 0; i < packet.size(); ++i) {
    // The previous character was the escape character. Exit the escape sequence
    // and continue.
    if (in_escape) {
      in_escape = false;
      continue;
    }

    if (packet[i] == kEscapeChar) {
      in_escape = true;
      continue;
    }

    if (packet[i] == val) {
      found = true;
      break;
    }
  }

  if (found)
    *out_index = i;

  return found;
}

// We take |packet| by copying since we modify it internally while processing
// it.
bool VerifyPacket(fxl::StringView packet, fxl::StringView* out_packet_data) {
  FXL_DCHECK(out_packet_data);

  if (packet.empty()) {
    FXL_LOG(ERROR) << "Empty packet";
    return false;
  }

  // Loop through the packet until we get to '$'. Ignore all other characters.
  // To quote the protocol specification "There are no notifications defined for
  // gdb to send at the moment", thus we ignore everything until the first '$'.
  // (see
  // https://sourceware.org/gdb/current/onlinedocs/gdb/Notification-Packets.html)
  size_t dollar_sign;
  if (!FindUnescapedChar('$', packet, &dollar_sign)) {
    FXL_LOG(ERROR) << "Packet does not start with \"$\": " << packet;
    return false;
  }

  packet.remove_prefix(dollar_sign);
  FXL_DCHECK(packet[0] == '$');

  // The packet should contain at least 4 bytes ($, #, 2-digit checksum).
  if (packet.size() < 4) {
    FXL_LOG(ERROR) << "Malformed packet: " << packet;
    return false;
  }

  size_t pound;
  if (!FindUnescapedChar('#', packet, &pound)) {
    FXL_LOG(ERROR) << "Packet does not contain \"#\"";
    return false;
  }

  fxl::StringView packet_data(packet.data() + 1, pound - 1);

  // Extract the packet checksum

  // First check if the packet contains the 2 digit checksum. The difference
  // between the payload size and the full packet size should exactly match the
  // number of required characters (i.e. '$', '#', and checksum).
  if (packet.size() - packet_data.size() != 4) {
    FXL_LOG(ERROR) << "Packet does not contain 2 digit checksum";
    return false;
  }

  // TODO(armansito): Ignore the checksum if we're in no-acknowledgment mode.

  uint8_t received_checksum;
  if (!util::DecodeByteString(packet.data() + pound + 1, &received_checksum)) {
    FXL_LOG(ERROR) << "Malformed packet checksum received";
    return false;
  }

  // Compute the checksum over packet payload
  uint8_t local_checksum = 0;
  for (char byte : packet_data)
    local_checksum += (uint8_t)byte;

  if (local_checksum != received_checksum) {
    FXL_LOG(ERROR) << "Bad checksum: computed = " << (unsigned)local_checksum
                   << ", received = " << (unsigned)received_checksum
                   << ", packet: " << packet;
    return false;
  }

  *out_packet_data = packet_data;

  return true;
}

void ExtractParameters(const fxl::StringView& packet,
                       fxl::StringView* out_prefix,
                       fxl::StringView* out_params) {
  FXL_DCHECK(!packet.empty());
  FXL_DCHECK(out_prefix);
  FXL_DCHECK(out_params);

  // Both query and set packets use can have parameters followed by a ':'
  // character.
  size_t colon;
  for (colon = 0; colon < packet.size(); colon++) {
    if (packet[colon] == ':')
      break;
  }

  // Everything up to |colon| is the prefix. If |colon| == |packet_size|,
  // then there are no parameters. If |colon| == (|packet_size| - 1) then
  // there is a ':' but no parameters following it.
  *out_prefix = packet.substr(0, colon);
  *out_params = packet.substr(
      colon + 1, packet.size() == colon ? 0 : packet.size() - colon - 1);
}

}  // namespace util
}  // namespace debugserver
