1//===-- CommandHistory.cpp ------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include <cinttypes>
10#include <optional>
11
12#include "lldb/Interpreter/CommandHistory.h"
13
14using namespace lldb;
15using namespace lldb_private;
16
17size_t CommandHistory::GetSize() const {
18  std::lock_guard<std::recursive_mutex> guard(m_mutex);
19  return m_history.size();
20}
21
22bool CommandHistory::IsEmpty() const {
23  std::lock_guard<std::recursive_mutex> guard(m_mutex);
24  return m_history.empty();
25}
26
27std::optional<llvm::StringRef>
28CommandHistory::FindString(llvm::StringRef input_str) const {
29  std::lock_guard<std::recursive_mutex> guard(m_mutex);
30  if (input_str.size() < 2)
31    return std::nullopt;
32
33  if (input_str[0] != g_repeat_char)
34    return std::nullopt;
35
36  if (input_str[1] == g_repeat_char) {
37    if (m_history.empty())
38      return std::nullopt;
39    return llvm::StringRef(m_history.back());
40  }
41
42  input_str = input_str.drop_front();
43
44  size_t idx = 0;
45  if (input_str.front() == '-') {
46    if (input_str.drop_front(1).getAsInteger(0, idx))
47      return std::nullopt;
48    if (idx >= m_history.size())
49      return std::nullopt;
50    idx = m_history.size() - idx;
51  } else {
52    if (input_str.getAsInteger(0, idx))
53      return std::nullopt;
54    if (idx >= m_history.size())
55      return std::nullopt;
56  }
57
58  return llvm::StringRef(m_history[idx]);
59}
60
61llvm::StringRef CommandHistory::GetStringAtIndex(size_t idx) const {
62  std::lock_guard<std::recursive_mutex> guard(m_mutex);
63  if (idx < m_history.size())
64    return m_history[idx];
65  return "";
66}
67
68llvm::StringRef CommandHistory::operator[](size_t idx) const {
69  return GetStringAtIndex(idx);
70}
71
72llvm::StringRef CommandHistory::GetRecentmostString() const {
73  std::lock_guard<std::recursive_mutex> guard(m_mutex);
74  if (m_history.empty())
75    return "";
76  return m_history.back();
77}
78
79void CommandHistory::AppendString(llvm::StringRef str, bool reject_if_dupe) {
80  std::lock_guard<std::recursive_mutex> guard(m_mutex);
81  if (reject_if_dupe) {
82    if (!m_history.empty()) {
83      if (str == m_history.back())
84        return;
85    }
86  }
87  m_history.push_back(std::string(str));
88}
89
90void CommandHistory::Clear() {
91  std::lock_guard<std::recursive_mutex> guard(m_mutex);
92  m_history.clear();
93}
94
95void CommandHistory::Dump(Stream &stream, size_t start_idx,
96                          size_t stop_idx) const {
97  std::lock_guard<std::recursive_mutex> guard(m_mutex);
98  stop_idx = std::min(stop_idx + 1, m_history.size());
99  for (size_t counter = start_idx; counter < stop_idx; counter++) {
100    const std::string hist_item = m_history[counter];
101    if (!hist_item.empty()) {
102      stream.Indent();
103      stream.Printf("%4" PRIu64 ": %s\n", (uint64_t)counter, hist_item.c_str());
104    }
105  }
106}
107