StringList.cpp revision 317027
1//===-- StringList.cpp ------------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Utility/StringList.h"
11
12#include "lldb/Utility/Log.h"
13#include "lldb/Utility/Stream.h" // for Stream
14#include "lldb/Utility/StreamString.h"
15#include "llvm/ADT/ArrayRef.h" // for ArrayRef, makeArrayRef
16
17#include <algorithm> // for min
18#include <stdint.h>  // for SIZE_MAX, uint32_t
19#include <string.h>  // for size_t, strcspn, NULL
20
21using namespace lldb_private;
22
23StringList::StringList() : m_strings() {}
24
25StringList::StringList(const char *str) : m_strings() {
26  if (str)
27    m_strings.push_back(str);
28}
29
30StringList::StringList(const char **strv, int strc) : m_strings() {
31  for (int i = 0; i < strc; ++i) {
32    if (strv[i])
33      m_strings.push_back(strv[i]);
34  }
35}
36
37StringList::~StringList() {}
38
39void StringList::AppendString(const char *str) {
40  if (str)
41    m_strings.push_back(str);
42}
43
44void StringList::AppendString(const std::string &s) { m_strings.push_back(s); }
45
46void StringList::AppendString(std::string &&s) { m_strings.push_back(s); }
47
48void StringList::AppendString(const char *str, size_t str_len) {
49  if (str)
50    m_strings.push_back(std::string(str, str_len));
51}
52
53void StringList::AppendString(llvm::StringRef str) {
54  m_strings.push_back(str.str());
55}
56
57void StringList::AppendList(const char **strv, int strc) {
58  for (int i = 0; i < strc; ++i) {
59    if (strv[i])
60      m_strings.push_back(strv[i]);
61  }
62}
63
64void StringList::AppendList(StringList strings) {
65  size_t len = strings.GetSize();
66
67  for (size_t i = 0; i < len; ++i)
68    m_strings.push_back(strings.GetStringAtIndex(i));
69}
70
71size_t StringList::GetSize() const { return m_strings.size(); }
72
73size_t StringList::GetMaxStringLength() const {
74  size_t max_length = 0;
75  for (const auto &s : m_strings) {
76    const size_t len = s.size();
77    if (max_length < len)
78      max_length = len;
79  }
80  return max_length;
81}
82
83const char *StringList::GetStringAtIndex(size_t idx) const {
84  if (idx < m_strings.size())
85    return m_strings[idx].c_str();
86  return NULL;
87}
88
89void StringList::Join(const char *separator, Stream &strm) {
90  size_t size = GetSize();
91
92  if (size == 0)
93    return;
94
95  for (uint32_t i = 0; i < size; ++i) {
96    if (i > 0)
97      strm.PutCString(separator);
98    strm.PutCString(GetStringAtIndex(i));
99  }
100}
101
102void StringList::Clear() { m_strings.clear(); }
103
104void StringList::LongestCommonPrefix(std::string &common_prefix) {
105  common_prefix.clear();
106  if (m_strings.empty())
107    return;
108
109  auto args = llvm::makeArrayRef(m_strings);
110  llvm::StringRef prefix = args.front();
111  for (auto arg : args.drop_front()) {
112    size_t count = 0;
113    for (count = 0; count < std::min(prefix.size(), arg.size()); ++count) {
114      if (prefix[count] != arg[count])
115        break;
116    }
117    prefix = prefix.take_front(count);
118  }
119  common_prefix = prefix;
120}
121
122void StringList::InsertStringAtIndex(size_t idx, const char *str) {
123  if (str) {
124    if (idx < m_strings.size())
125      m_strings.insert(m_strings.begin() + idx, str);
126    else
127      m_strings.push_back(str);
128  }
129}
130
131void StringList::InsertStringAtIndex(size_t idx, const std::string &str) {
132  if (idx < m_strings.size())
133    m_strings.insert(m_strings.begin() + idx, str);
134  else
135    m_strings.push_back(str);
136}
137
138void StringList::InsertStringAtIndex(size_t idx, std::string &&str) {
139  if (idx < m_strings.size())
140    m_strings.insert(m_strings.begin() + idx, str);
141  else
142    m_strings.push_back(str);
143}
144
145void StringList::DeleteStringAtIndex(size_t idx) {
146  if (idx < m_strings.size())
147    m_strings.erase(m_strings.begin() + idx);
148}
149
150size_t StringList::SplitIntoLines(const std::string &lines) {
151  return SplitIntoLines(lines.c_str(), lines.size());
152}
153
154size_t StringList::SplitIntoLines(const char *lines, size_t len) {
155  const size_t orig_size = m_strings.size();
156
157  if (len == 0)
158    return 0;
159
160  const char *k_newline_chars = "\r\n";
161  const char *p = lines;
162  const char *end = lines + len;
163  while (p < end) {
164    size_t count = strcspn(p, k_newline_chars);
165    if (count == 0) {
166      if (p[count] == '\r' || p[count] == '\n')
167        m_strings.push_back(std::string());
168      else
169        break;
170    } else {
171      if (p + count > end)
172        count = end - p;
173      m_strings.push_back(std::string(p, count));
174    }
175    if (p[count] == '\r' && p[count + 1] == '\n')
176      count++; // Skip an extra newline char for the DOS newline
177    count++;   // Skip the newline character
178    p += count;
179  }
180  return m_strings.size() - orig_size;
181}
182
183void StringList::RemoveBlankLines() {
184  if (GetSize() == 0)
185    return;
186
187  size_t idx = 0;
188  while (idx < m_strings.size()) {
189    if (m_strings[idx].empty())
190      DeleteStringAtIndex(idx);
191    else
192      idx++;
193  }
194}
195
196std::string StringList::CopyList(const char *item_preamble,
197                                 const char *items_sep) const {
198  StreamString strm;
199  for (size_t i = 0; i < GetSize(); i++) {
200    if (i && items_sep && items_sep[0])
201      strm << items_sep;
202    if (item_preamble)
203      strm << item_preamble;
204    strm << GetStringAtIndex(i);
205  }
206  return strm.GetString();
207}
208
209StringList &StringList::operator<<(const char *str) {
210  AppendString(str);
211  return *this;
212}
213
214StringList &StringList::operator<<(const std::string &str) {
215  AppendString(str);
216  return *this;
217}
218
219StringList &StringList::operator<<(StringList strings) {
220  AppendList(strings);
221  return *this;
222}
223
224StringList &StringList::operator=(const std::vector<std::string> &rhs) {
225  m_strings.assign(rhs.begin(), rhs.end());
226
227  return *this;
228}
229
230size_t StringList::AutoComplete(llvm::StringRef s, StringList &matches,
231                                size_t &exact_idx) const {
232  matches.Clear();
233  exact_idx = SIZE_MAX;
234  if (s.empty()) {
235    // No string, so it matches everything
236    matches = *this;
237    return matches.GetSize();
238  }
239
240  const size_t s_len = s.size();
241  const size_t num_strings = m_strings.size();
242
243  for (size_t i = 0; i < num_strings; ++i) {
244    if (m_strings[i].find(s) == 0) {
245      if (exact_idx == SIZE_MAX && m_strings[i].size() == s_len)
246        exact_idx = matches.GetSize();
247      matches.AppendString(m_strings[i]);
248    }
249  }
250  return matches.GetSize();
251}
252
253void StringList::LogDump(Log *log, const char *name) {
254  if (!log)
255    return;
256
257  StreamString strm;
258  if (name)
259    strm.Printf("Begin %s:\n", name);
260  for (const auto &s : m_strings) {
261    strm.Indent();
262    strm.Printf("%s\n", s.c_str());
263  }
264  if (name)
265    strm.Printf("End %s.\n", name);
266
267  LLDB_LOGV(log, "{0}", strm.GetData());
268}
269