//===-- BreakpointOptions.cpp -----------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/BreakpointOptions.h"

#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Value.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadSpec.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StringList.h"

#include "llvm/ADT/STLExtras.h"

using namespace lldb;
using namespace lldb_private;

const char
    *BreakpointOptions::CommandData::g_option_names[static_cast<uint32_t>(
        BreakpointOptions::CommandData::OptionNames::LastOptionName)]{
        "UserSource", "ScriptSource", "StopOnError"};

StructuredData::ObjectSP
BreakpointOptions::CommandData::SerializeToStructuredData() {
  size_t num_strings = user_source.GetSize();
  if (num_strings == 0 && script_source.empty()) {
    // We shouldn't serialize commands if there aren't any, return an empty sp
    // to indicate this.
    return StructuredData::ObjectSP();
  }

  StructuredData::DictionarySP options_dict_sp(
      new StructuredData::Dictionary());
  options_dict_sp->AddBooleanItem(GetKey(OptionNames::StopOnError),
                                  stop_on_error);

  StructuredData::ArraySP user_source_sp(new StructuredData::Array());
  for (size_t i = 0; i < num_strings; i++) {
    StructuredData::StringSP item_sp(
        new StructuredData::String(user_source[i]));
    user_source_sp->AddItem(item_sp);
    options_dict_sp->AddItem(GetKey(OptionNames::UserSource), user_source_sp);
  }

  options_dict_sp->AddStringItem(
      GetKey(OptionNames::Interpreter),
      ScriptInterpreter::LanguageToString(interpreter));
  return options_dict_sp;
}

std::unique_ptr<BreakpointOptions::CommandData>
BreakpointOptions::CommandData::CreateFromStructuredData(
    const StructuredData::Dictionary &options_dict, Status &error) {
  std::unique_ptr<CommandData> data_up(new CommandData());
  bool found_something = false;

  bool success = options_dict.GetValueForKeyAsBoolean(
      GetKey(OptionNames::StopOnError), data_up->stop_on_error);

  if (success)
    found_something = true;

  llvm::StringRef interpreter_str;
  ScriptLanguage interp_language;
  success = options_dict.GetValueForKeyAsString(
      GetKey(OptionNames::Interpreter), interpreter_str);

  if (!success) {
    error.SetErrorString("Missing command language value.");
    return data_up;
  }

  found_something = true;
  interp_language = ScriptInterpreter::StringToLanguage(interpreter_str);
  if (interp_language == eScriptLanguageUnknown) {
    error.SetErrorStringWithFormatv("Unknown breakpoint command language: {0}.",
                                    interpreter_str);
    return data_up;
  }
  data_up->interpreter = interp_language;

  StructuredData::Array *user_source;
  success = options_dict.GetValueForKeyAsArray(GetKey(OptionNames::UserSource),
                                               user_source);
  if (success) {
    found_something = true;
    size_t num_elems = user_source->GetSize();
    for (size_t i = 0; i < num_elems; i++) {
      llvm::StringRef elem_string;
      success = user_source->GetItemAtIndexAsString(i, elem_string);
      if (success)
        data_up->user_source.AppendString(elem_string);
    }
  }

  if (found_something)
    return data_up;
  else
    return std::unique_ptr<BreakpointOptions::CommandData>();
}

const char *BreakpointOptions::g_option_names[(
    size_t)BreakpointOptions::OptionNames::LastOptionName]{
    "ConditionText", "IgnoreCount", 
    "EnabledState", "OneShotState", "AutoContinue"};

bool BreakpointOptions::NullCallback(void *baton,
                                     StoppointCallbackContext *context,
                                     lldb::user_id_t break_id,
                                     lldb::user_id_t break_loc_id) {
  return true;
}

//----------------------------------------------------------------------
// BreakpointOptions constructor
//----------------------------------------------------------------------
BreakpointOptions::BreakpointOptions(bool all_flags_set)
    : m_callback(BreakpointOptions::NullCallback), m_callback_baton_sp(),
      m_baton_is_command_baton(false), m_callback_is_synchronous(false),
      m_enabled(true), m_one_shot(false), m_ignore_count(0), m_thread_spec_ap(),
      m_condition_text(), m_condition_text_hash(0), m_auto_continue(false),
      m_set_flags(0) {
        if (all_flags_set)
          m_set_flags.Set(~((Flags::ValueType) 0));
      }

BreakpointOptions::BreakpointOptions(const char *condition, bool enabled,
                                     int32_t ignore, bool one_shot, 
                                     bool auto_continue)
    : m_callback(nullptr), m_baton_is_command_baton(false),
      m_callback_is_synchronous(false), m_enabled(enabled),
      m_one_shot(one_shot), m_ignore_count(ignore),
      m_condition_text_hash(0), m_auto_continue(auto_continue)
{
    m_set_flags.Set(eEnabled | eIgnoreCount | eOneShot 
                   | eAutoContinue);
    if (condition && *condition != '\0') {
      SetCondition(condition);
    }
}

//----------------------------------------------------------------------
// BreakpointOptions copy constructor
//----------------------------------------------------------------------
BreakpointOptions::BreakpointOptions(const BreakpointOptions &rhs)
    : m_callback(rhs.m_callback), m_callback_baton_sp(rhs.m_callback_baton_sp),
      m_baton_is_command_baton(rhs.m_baton_is_command_baton),
      m_callback_is_synchronous(rhs.m_callback_is_synchronous),
      m_enabled(rhs.m_enabled), m_one_shot(rhs.m_one_shot),
      m_ignore_count(rhs.m_ignore_count), m_thread_spec_ap(),
      m_auto_continue(rhs.m_auto_continue),
      m_set_flags(rhs.m_set_flags) {
  if (rhs.m_thread_spec_ap.get() != nullptr)
    m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
  m_condition_text = rhs.m_condition_text;
  m_condition_text_hash = rhs.m_condition_text_hash;
}

//----------------------------------------------------------------------
// BreakpointOptions assignment operator
//----------------------------------------------------------------------
const BreakpointOptions &BreakpointOptions::
operator=(const BreakpointOptions &rhs) {
  m_callback = rhs.m_callback;
  m_callback_baton_sp = rhs.m_callback_baton_sp;
  m_baton_is_command_baton = rhs.m_baton_is_command_baton;
  m_callback_is_synchronous = rhs.m_callback_is_synchronous;
  m_enabled = rhs.m_enabled;
  m_one_shot = rhs.m_one_shot;
  m_ignore_count = rhs.m_ignore_count;
  if (rhs.m_thread_spec_ap.get() != nullptr)
    m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
  m_condition_text = rhs.m_condition_text;
  m_condition_text_hash = rhs.m_condition_text_hash;
  m_auto_continue = rhs.m_auto_continue;
  m_set_flags = rhs.m_set_flags;
  return *this;
}

void BreakpointOptions::CopyOverSetOptions(const BreakpointOptions &incoming)
{
  if (incoming.m_set_flags.Test(eEnabled))
  {
    m_enabled = incoming.m_enabled;
    m_set_flags.Set(eEnabled);
  }
  if (incoming.m_set_flags.Test(eOneShot))
  {
    m_one_shot = incoming.m_one_shot;
    m_set_flags.Set(eOneShot);
  }
  if (incoming.m_set_flags.Test(eCallback))
  {
    m_callback = incoming.m_callback;
    m_callback_baton_sp = incoming.m_callback_baton_sp;
    m_callback_is_synchronous = incoming.m_callback_is_synchronous;
    m_baton_is_command_baton = incoming.m_baton_is_command_baton;
    m_set_flags.Set(eCallback);
  }
  if (incoming.m_set_flags.Test(eIgnoreCount))
  {
    m_ignore_count = incoming.m_ignore_count;
    m_set_flags.Set(eIgnoreCount);
  }
  if (incoming.m_set_flags.Test(eCondition))
  {
    // If we're copying over an empty condition, mark it as unset.
    if (incoming.m_condition_text.empty()) {
      m_condition_text.clear();
      m_condition_text_hash = 0;
      m_set_flags.Clear(eCondition);
    } else {
      m_condition_text = incoming.m_condition_text;
      m_condition_text_hash = incoming.m_condition_text_hash;
      m_set_flags.Set(eCondition);
    }
  }
  if (incoming.m_set_flags.Test(eAutoContinue))
  {
    m_auto_continue = incoming.m_auto_continue;
    m_set_flags.Set(eAutoContinue);
  }
  if (incoming.m_set_flags.Test(eThreadSpec) && incoming.m_thread_spec_ap)
  {
    if (!m_thread_spec_ap)
      m_thread_spec_ap.reset(new ThreadSpec(*incoming.m_thread_spec_ap.get()));
    else
      *m_thread_spec_ap.get() = *incoming.m_thread_spec_ap.get();
    m_set_flags.Set(eThreadSpec);
  }
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
BreakpointOptions::~BreakpointOptions() = default;

std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData(
    Target &target, const StructuredData::Dictionary &options_dict,
    Status &error) {
  bool enabled = true;
  bool one_shot = false;
  bool auto_continue = false;
  int32_t ignore_count = 0;
  llvm::StringRef condition_ref("");
  Flags set_options;

  const char *key = GetKey(OptionNames::EnabledState);
  bool success;
  if (key) {
    success = options_dict.GetValueForKeyAsBoolean(key, enabled);
    if (!success) {
      error.SetErrorStringWithFormat("%s key is not a boolean.",
                                   GetKey(OptionNames::EnabledState));
      return nullptr;
    }
    set_options.Set(eEnabled);
  }

  key = GetKey(OptionNames::OneShotState);
  if (key) {
    success = options_dict.GetValueForKeyAsBoolean(key, one_shot);
    if (!success) {
      error.SetErrorStringWithFormat("%s key is not a boolean.",
                                     GetKey(OptionNames::OneShotState));
      return nullptr;
      }
      set_options.Set(eOneShot);
  }
  
  key = GetKey(OptionNames::AutoContinue);
  if (key) {
    success = options_dict.GetValueForKeyAsBoolean(key, auto_continue);
    if (!success) {
      error.SetErrorStringWithFormat("%s key is not a boolean.",
                                     GetKey(OptionNames::AutoContinue));
      return nullptr;
      }
      set_options.Set(eAutoContinue);
  }
  
  key = GetKey(OptionNames::IgnoreCount);
  if (key) {
    success = options_dict.GetValueForKeyAsInteger(key, ignore_count);
    if (!success) {
      error.SetErrorStringWithFormat("%s key is not an integer.",
                                     GetKey(OptionNames::IgnoreCount));
      return nullptr;
    }
    set_options.Set(eIgnoreCount);
  }

  key = GetKey(OptionNames::ConditionText);
  if (key) {
    success = options_dict.GetValueForKeyAsString(key, condition_ref);
    if (!success) {
      error.SetErrorStringWithFormat("%s key is not an string.",
                                     GetKey(OptionNames::ConditionText));
      return nullptr;
    }
    set_options.Set(eCondition);
  }

  std::unique_ptr<CommandData> cmd_data_up;
  StructuredData::Dictionary *cmds_dict;
  success = options_dict.GetValueForKeyAsDictionary(
      CommandData::GetSerializationKey(), cmds_dict);
  if (success && cmds_dict) {
    Status cmds_error;
    cmd_data_up = CommandData::CreateFromStructuredData(*cmds_dict, cmds_error);
    if (cmds_error.Fail()) {
      error.SetErrorStringWithFormat(
          "Failed to deserialize breakpoint command options: %s.",
          cmds_error.AsCString());
      return nullptr;
    }
  }

  auto bp_options = llvm::make_unique<BreakpointOptions>(
      condition_ref.str().c_str(), enabled, 
      ignore_count, one_shot, auto_continue);
  if (cmd_data_up.get()) {
    if (cmd_data_up->interpreter == eScriptLanguageNone)
      bp_options->SetCommandDataCallback(cmd_data_up);
    else {
      ScriptInterpreter *interp =
          target.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
      if (!interp) {
        error.SetErrorStringWithFormat(
            "Can't set script commands - no script interpreter");
        return nullptr;
      }
      if (interp->GetLanguage() != cmd_data_up->interpreter) {
        error.SetErrorStringWithFormat(
            "Current script language doesn't match breakpoint's language: %s",
            ScriptInterpreter::LanguageToString(cmd_data_up->interpreter)
                .c_str());
        return nullptr;
      }
      Status script_error;
      script_error =
          interp->SetBreakpointCommandCallback(bp_options.get(), cmd_data_up);
      if (script_error.Fail()) {
        error.SetErrorStringWithFormat("Error generating script callback: %s.",
                                       error.AsCString());
        return nullptr;
      }
    }
  }

  StructuredData::Dictionary *thread_spec_dict;
  success = options_dict.GetValueForKeyAsDictionary(
      ThreadSpec::GetSerializationKey(), thread_spec_dict);
  if (success) {
    Status thread_spec_error;
    std::unique_ptr<ThreadSpec> thread_spec_up =
        ThreadSpec::CreateFromStructuredData(*thread_spec_dict,
                                             thread_spec_error);
    if (thread_spec_error.Fail()) {
      error.SetErrorStringWithFormat(
          "Failed to deserialize breakpoint thread spec options: %s.",
          thread_spec_error.AsCString());
      return nullptr;
    }
    bp_options->SetThreadSpec(thread_spec_up);
  }
  return bp_options;
}

StructuredData::ObjectSP BreakpointOptions::SerializeToStructuredData() {
  StructuredData::DictionarySP options_dict_sp(
      new StructuredData::Dictionary());
  if (m_set_flags.Test(eEnabled))
    options_dict_sp->AddBooleanItem(GetKey(OptionNames::EnabledState),
                                    m_enabled);
  if (m_set_flags.Test(eOneShot))
    options_dict_sp->AddBooleanItem(GetKey(OptionNames::OneShotState),
                               m_one_shot);
  if (m_set_flags.Test(eAutoContinue))
    options_dict_sp->AddBooleanItem(GetKey(OptionNames::AutoContinue),
                               m_auto_continue);
  if (m_set_flags.Test(eIgnoreCount))
    options_dict_sp->AddIntegerItem(GetKey(OptionNames::IgnoreCount),
                                    m_ignore_count);
  if (m_set_flags.Test(eCondition))
    options_dict_sp->AddStringItem(GetKey(OptionNames::ConditionText),
                                   m_condition_text);
         
  if (m_set_flags.Test(eCallback) && m_baton_is_command_baton) {
    auto cmd_baton =
        std::static_pointer_cast<CommandBaton>(m_callback_baton_sp);
    StructuredData::ObjectSP commands_sp =
        cmd_baton->getItem()->SerializeToStructuredData();
    if (commands_sp) {
      options_dict_sp->AddItem(
          BreakpointOptions::CommandData::GetSerializationKey(), commands_sp);
    }
  }
  if (m_set_flags.Test(eThreadSpec) && m_thread_spec_ap) {
    StructuredData::ObjectSP thread_spec_sp =
        m_thread_spec_ap->SerializeToStructuredData();
    options_dict_sp->AddItem(ThreadSpec::GetSerializationKey(), thread_spec_sp);
  }

  return options_dict_sp;
}

//------------------------------------------------------------------
// Callbacks
//------------------------------------------------------------------
void BreakpointOptions::SetCallback(BreakpointHitCallback callback,
                                    const lldb::BatonSP &callback_baton_sp,
                                    bool callback_is_synchronous) {
  // FIXME: This seems unsafe.  If BatonSP actually *is* a CommandBaton, but
  // in a shared_ptr<Baton> instead of a shared_ptr<CommandBaton>, then we will
  // set m_baton_is_command_baton to false, which is incorrect. One possible
  // solution is to make the base Baton class provide a method such as:
  //     virtual StringRef getBatonId() const { return ""; }
  // and have CommandBaton override this to return something unique, and then
  // check for it here.  Another option might be to make Baton using the llvm
  // casting infrastructure, so that we could write something like:
  //     if (llvm::isa<CommandBaton>(callback_baton_sp))
  // at relevant callsites instead of storing a boolean.
  m_callback_is_synchronous = callback_is_synchronous;
  m_callback = callback;
  m_callback_baton_sp = callback_baton_sp;
  m_baton_is_command_baton = false;
  m_set_flags.Set(eCallback);
}

void BreakpointOptions::SetCallback(
    BreakpointHitCallback callback,
    const BreakpointOptions::CommandBatonSP &callback_baton_sp,
    bool callback_is_synchronous) {
  m_callback_is_synchronous = callback_is_synchronous;
  m_callback = callback;
  m_callback_baton_sp = callback_baton_sp;
  m_baton_is_command_baton = true;
  m_set_flags.Set(eCallback);
}

void BreakpointOptions::ClearCallback() {
  m_callback = BreakpointOptions::NullCallback;
  m_callback_is_synchronous = false;
  m_callback_baton_sp.reset();
  m_baton_is_command_baton = false;
  m_set_flags.Clear(eCallback);
}

Baton *BreakpointOptions::GetBaton() { return m_callback_baton_sp.get(); }

const Baton *BreakpointOptions::GetBaton() const {
  return m_callback_baton_sp.get();
}

bool BreakpointOptions::InvokeCallback(StoppointCallbackContext *context,
                                       lldb::user_id_t break_id,
                                       lldb::user_id_t break_loc_id) {
  if (m_callback) {
    if (context->is_synchronous == IsCallbackSynchronous()) {
        return m_callback(m_callback_baton_sp ? m_callback_baton_sp->data()
                                          : nullptr,
                      context, break_id, break_loc_id);
    } else if (IsCallbackSynchronous()) {
      // If a synchronous callback is called at async time, it should not say
      // to stop.
      return false;
    }
  }
  return true;
}

bool BreakpointOptions::HasCallback() const {
  return m_callback != BreakpointOptions::NullCallback;
}

bool BreakpointOptions::GetCommandLineCallbacks(StringList &command_list) {
  if (!HasCallback())
    return false;
  if (!m_baton_is_command_baton)
    return false;

  auto cmd_baton = std::static_pointer_cast<CommandBaton>(m_callback_baton_sp);
  CommandData *data = cmd_baton->getItem();
  if (!data)
    return false;
  command_list = data->user_source;
  return true;
}

void BreakpointOptions::SetCondition(const char *condition) {
  if (!condition || condition[0] == '\0') {
    condition = "";
    m_set_flags.Clear(eCondition);
  }
  else
    m_set_flags.Set(eCondition);

  m_condition_text.assign(condition);
  std::hash<std::string> hasher;
  m_condition_text_hash = hasher(m_condition_text);
}

const char *BreakpointOptions::GetConditionText(size_t *hash) const {
  if (!m_condition_text.empty()) {
    if (hash)
      *hash = m_condition_text_hash;

    return m_condition_text.c_str();
  } else {
    return nullptr;
  }
}

const ThreadSpec *BreakpointOptions::GetThreadSpecNoCreate() const {
  return m_thread_spec_ap.get();
}

ThreadSpec *BreakpointOptions::GetThreadSpec() {
  if (m_thread_spec_ap.get() == nullptr)
  {
    m_set_flags.Set(eThreadSpec);
    m_thread_spec_ap.reset(new ThreadSpec());
  }

  return m_thread_spec_ap.get();
}

void BreakpointOptions::SetThreadID(lldb::tid_t thread_id) {
  GetThreadSpec()->SetTID(thread_id);
  m_set_flags.Set(eThreadSpec);
}

void BreakpointOptions::SetThreadSpec(
    std::unique_ptr<ThreadSpec> &thread_spec_up) {
  m_thread_spec_ap = std::move(thread_spec_up);
  m_set_flags.Set(eThreadSpec);
}

void BreakpointOptions::GetDescription(Stream *s,
                                       lldb::DescriptionLevel level) const {
  // Figure out if there are any options not at their default value, and only
  // print anything if there are:

  if (m_ignore_count != 0 || !m_enabled || m_one_shot || m_auto_continue ||
      (GetThreadSpecNoCreate() != nullptr &&
       GetThreadSpecNoCreate()->HasSpecification())) {
    if (level == lldb::eDescriptionLevelVerbose) {
      s->EOL();
      s->IndentMore();
      s->Indent();
      s->PutCString("Breakpoint Options:\n");
      s->IndentMore();
      s->Indent();
    } else
      s->PutCString(" Options: ");

    if (m_ignore_count > 0)
      s->Printf("ignore: %d ", m_ignore_count);
    s->Printf("%sabled ", m_enabled ? "en" : "dis");

    if (m_one_shot)
      s->Printf("one-shot ");

    if (m_auto_continue)
      s->Printf("auto-continue ");

    if (m_thread_spec_ap.get())
      m_thread_spec_ap->GetDescription(s, level);

    if (level == lldb::eDescriptionLevelFull) {
      s->IndentLess();
      s->IndentMore();
    }
  }

  if (m_callback_baton_sp.get()) {
    if (level != eDescriptionLevelBrief) {
      s->EOL();
      m_callback_baton_sp->GetDescription(s, level);
    }
  }
  if (!m_condition_text.empty()) {
    if (level != eDescriptionLevelBrief) {
      s->EOL();
      s->Printf("Condition: %s\n", m_condition_text.c_str());
    }
  }
}

void BreakpointOptions::CommandBaton::GetDescription(
    Stream *s, lldb::DescriptionLevel level) const {
  const CommandData *data = getItem();

  if (level == eDescriptionLevelBrief) {
    s->Printf(", commands = %s",
              (data && data->user_source.GetSize() > 0) ? "yes" : "no");
    return;
  }

  s->IndentMore();
  s->Indent("Breakpoint commands");
  if (data->interpreter != eScriptLanguageNone)
    s->Printf(" (%s):\n",
              ScriptInterpreter::LanguageToString(data->interpreter).c_str());
  else
    s->PutCString(":\n");

  s->IndentMore();
  if (data && data->user_source.GetSize() > 0) {
    const size_t num_strings = data->user_source.GetSize();
    for (size_t i = 0; i < num_strings; ++i) {
      s->Indent(data->user_source.GetStringAtIndex(i));
      s->EOL();
    }
  } else {
    s->PutCString("No commands.\n");
  }
  s->IndentLess();
  s->IndentLess();
}

void BreakpointOptions::SetCommandDataCallback(
    std::unique_ptr<CommandData> &cmd_data) {
  cmd_data->interpreter = eScriptLanguageNone;
  auto baton_sp = std::make_shared<CommandBaton>(std::move(cmd_data));
  SetCallback(BreakpointOptions::BreakpointOptionsCallbackFunction, baton_sp);
  m_set_flags.Set(eCallback);
}

bool BreakpointOptions::BreakpointOptionsCallbackFunction(
    void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id,
    lldb::user_id_t break_loc_id) {
  bool ret_value = true;
  if (baton == nullptr)
    return true;

  CommandData *data = (CommandData *)baton;
  StringList &commands = data->user_source;

  if (commands.GetSize() > 0) {
    ExecutionContext exe_ctx(context->exe_ctx_ref);
    Target *target = exe_ctx.GetTargetPtr();
    if (target) {
      CommandReturnObject result;
      Debugger &debugger = target->GetDebugger();
      // Rig up the results secondary output stream to the debugger's, so the
      // output will come out synchronously if the debugger is set up that way.

      StreamSP output_stream(debugger.GetAsyncOutputStream());
      StreamSP error_stream(debugger.GetAsyncErrorStream());
      result.SetImmediateOutputStream(output_stream);
      result.SetImmediateErrorStream(error_stream);

      CommandInterpreterRunOptions options;
      options.SetStopOnContinue(true);
      options.SetStopOnError(data->stop_on_error);
      options.SetEchoCommands(true);
      options.SetPrintResults(true);
      options.SetAddToHistory(false);

      debugger.GetCommandInterpreter().HandleCommands(commands, &exe_ctx,
                                                      options, result);
      result.GetImmediateOutputStream()->Flush();
      result.GetImmediateErrorStream()->Flush();
    }
  }
  return ret_value;
}

void BreakpointOptions::Clear()
{
  m_set_flags.Clear();
  m_thread_spec_ap.release();
  m_one_shot = false;
  m_ignore_count = 0;
  m_auto_continue = false;
  m_callback = nullptr;
  m_callback_baton_sp.reset();
  m_baton_is_command_baton = false;
  m_callback_is_synchronous = false;
  m_enabled = false;
  m_condition_text.clear();
}
