1254721Semaste//===-- OptionValueFileSpec.cpp ---------------------------------*- C++ -*-===//
2254721Semaste//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6254721Semaste//
7254721Semaste//===----------------------------------------------------------------------===//
8254721Semaste
9254721Semaste#include "lldb/Interpreter/OptionValueFileSpec.h"
10254721Semaste
11254721Semaste#include "lldb/DataFormatters/FormatManager.h"
12314564Sdim#include "lldb/Host/FileSystem.h"
13254721Semaste#include "lldb/Interpreter/CommandCompletions.h"
14314564Sdim#include "lldb/Interpreter/CommandInterpreter.h"
15341825Sdim#include "lldb/Utility/Args.h"
16344779Sdim#include "lldb/Utility/State.h"
17254721Semaste
18254721Semasteusing namespace lldb;
19254721Semasteusing namespace lldb_private;
20254721Semaste
21314564SdimOptionValueFileSpec::OptionValueFileSpec(bool resolve)
22314564Sdim    : OptionValue(), m_current_value(), m_default_value(), m_data_sp(),
23314564Sdim      m_data_mod_time(),
24314564Sdim      m_completion_mask(CommandCompletions::eDiskFileCompletion),
25314564Sdim      m_resolve(resolve) {}
26254721Semaste
27314564SdimOptionValueFileSpec::OptionValueFileSpec(const FileSpec &value, bool resolve)
28314564Sdim    : OptionValue(), m_current_value(value), m_default_value(value),
29314564Sdim      m_data_sp(), m_data_mod_time(),
30314564Sdim      m_completion_mask(CommandCompletions::eDiskFileCompletion),
31314564Sdim      m_resolve(resolve) {}
32254721Semaste
33314564SdimOptionValueFileSpec::OptionValueFileSpec(const FileSpec &current_value,
34314564Sdim                                         const FileSpec &default_value,
35314564Sdim                                         bool resolve)
36314564Sdim    : OptionValue(), m_current_value(current_value),
37314564Sdim      m_default_value(default_value), m_data_sp(), m_data_mod_time(),
38314564Sdim      m_completion_mask(CommandCompletions::eDiskFileCompletion),
39314564Sdim      m_resolve(resolve) {}
40254721Semaste
41314564Sdimvoid OptionValueFileSpec::DumpValue(const ExecutionContext *exe_ctx,
42314564Sdim                                    Stream &strm, uint32_t dump_mask) {
43314564Sdim  if (dump_mask & eDumpOptionType)
44314564Sdim    strm.Printf("(%s)", GetTypeAsCString());
45314564Sdim  if (dump_mask & eDumpOptionValue) {
46254721Semaste    if (dump_mask & eDumpOptionType)
47314564Sdim      strm.PutCString(" = ");
48254721Semaste
49314564Sdim    if (m_current_value) {
50314564Sdim      strm << '"' << m_current_value.GetPath().c_str() << '"';
51254721Semaste    }
52314564Sdim  }
53254721Semaste}
54254721Semaste
55321369SdimStatus OptionValueFileSpec::SetValueFromString(llvm::StringRef value,
56321369Sdim                                               VarSetOperationType op) {
57321369Sdim  Status error;
58314564Sdim  switch (op) {
59314564Sdim  case eVarSetOperationClear:
60314564Sdim    Clear();
61314564Sdim    NotifyValueChanged();
62314564Sdim    break;
63314564Sdim
64314564Sdim  case eVarSetOperationReplace:
65314564Sdim  case eVarSetOperationAssign:
66314564Sdim    if (value.size() > 0) {
67314564Sdim      // The setting value may have whitespace, double-quotes, or single-quotes
68341825Sdim      // around the file path to indicate that internal spaces are not word
69341825Sdim      // breaks.  Strip off any ws & quotes from the start and end of the file
70341825Sdim      // path - we aren't doing any word // breaking here so the quoting is
71341825Sdim      // unnecessary.  NB this will cause a problem if someone tries to specify
72314564Sdim      // a file path that legitimately begins or ends with a " or ' character,
73314564Sdim      // or whitespace.
74314564Sdim      value = value.trim("\"' \t");
75314564Sdim      m_value_was_set = true;
76344779Sdim      m_current_value.SetFile(value.str(), FileSpec::Style::native);
77344779Sdim      if (m_resolve)
78344779Sdim        FileSystem::Instance().Resolve(m_current_value);
79314564Sdim      m_data_sp.reset();
80314564Sdim      m_data_mod_time = llvm::sys::TimePoint<>();
81314564Sdim      NotifyValueChanged();
82314564Sdim    } else {
83314564Sdim      error.SetErrorString("invalid value string");
84254721Semaste    }
85314564Sdim    break;
86314564Sdim
87314564Sdim  case eVarSetOperationInsertBefore:
88314564Sdim  case eVarSetOperationInsertAfter:
89314564Sdim  case eVarSetOperationRemove:
90314564Sdim  case eVarSetOperationAppend:
91314564Sdim  case eVarSetOperationInvalid:
92314564Sdim    error = OptionValue::SetValueFromString(value, op);
93314564Sdim    break;
94314564Sdim  }
95314564Sdim  return error;
96254721Semaste}
97254721Semaste
98314564Sdimlldb::OptionValueSP OptionValueFileSpec::DeepCopy() const {
99314564Sdim  return OptionValueSP(new OptionValueFileSpec(*this));
100254721Semaste}
101254721Semaste
102360784Sdimvoid OptionValueFileSpec::AutoComplete(CommandInterpreter &interpreter,
103360784Sdim                                       CompletionRequest &request) {
104314564Sdim  CommandCompletions::InvokeCommonCompletionCallbacks(
105341825Sdim      interpreter, m_completion_mask, request, nullptr);
106254721Semaste}
107254721Semaste
108327952Sdimconst lldb::DataBufferSP &OptionValueFileSpec::GetFileContents() {
109314564Sdim  if (m_current_value) {
110344779Sdim    const auto file_mod_time = FileSystem::Instance().GetModificationTime(m_current_value);
111314564Sdim    if (m_data_sp && m_data_mod_time == file_mod_time)
112314564Sdim      return m_data_sp;
113344779Sdim    m_data_sp =
114344779Sdim        FileSystem::Instance().CreateDataBuffer(m_current_value.GetPath());
115314564Sdim    m_data_mod_time = file_mod_time;
116314564Sdim  }
117314564Sdim  return m_data_sp;
118254721Semaste}
119