StringList.cpp revision 360660
174432Sjedgar//===-- StringList.cpp ------------------------------------------*- C++ -*-===//
290781Sjedgar//
374432Sjedgar// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
474432Sjedgar// See https://llvm.org/LICENSE.txt for license information.
574432Sjedgar// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
674432Sjedgar//
774432Sjedgar//===----------------------------------------------------------------------===//
874432Sjedgar
974432Sjedgar#include "lldb/Utility/StringList.h"
1074432Sjedgar
1174432Sjedgar#include "lldb/Utility/Log.h"
1274432Sjedgar#include "lldb/Utility/Stream.h"
1374432Sjedgar#include "lldb/Utility/StreamString.h"
1474432Sjedgar#include "llvm/ADT/ArrayRef.h"
1574432Sjedgar
1674432Sjedgar#include <algorithm>
1774432Sjedgar#include <stdint.h>
1874432Sjedgar#include <string.h>
1974432Sjedgar
2074432Sjedgarusing namespace lldb_private;
2174432Sjedgar
2274432SjedgarStringList::StringList() : m_strings() {}
2374432Sjedgar
2474432SjedgarStringList::StringList(const char *str) : m_strings() {
2574432Sjedgar  if (str)
2674432Sjedgar    m_strings.push_back(str);
2792986Sobrien}
2892986Sobrien
2992986SobrienStringList::StringList(const char **strv, int strc) : m_strings() {
3074432Sjedgar  for (int i = 0; i < strc; ++i) {
3175185Stmm    if (strv[i])
3274432Sjedgar      m_strings.push_back(strv[i]);
3375185Stmm  }
3474432Sjedgar}
3574432Sjedgar
36194955StraszStringList::~StringList() {}
3774432Sjedgar
38194955Straszvoid StringList::AppendString(const char *str) {
39194955Strasz  if (str)
40194955Strasz    m_strings.push_back(str);
41194955Strasz}
42194955Strasz
43194955Straszvoid StringList::AppendString(const std::string &s) { m_strings.push_back(s); }
44194955Strasz
45194955Straszvoid StringList::AppendString(std::string &&s) { m_strings.push_back(s); }
46194955Strasz
47194955Straszvoid StringList::AppendString(const char *str, size_t str_len) {
48194955Strasz  if (str)
49194955Strasz    m_strings.push_back(std::string(str, str_len));
50194955Strasz}
51194955Strasz
52194955Straszvoid StringList::AppendString(llvm::StringRef str) {
53194955Strasz  m_strings.push_back(str.str());
54194955Strasz}
55194955Strasz
56194955Straszvoid StringList::AppendList(const char **strv, int strc) {
57194955Strasz  for (int i = 0; i < strc; ++i) {
58194955Strasz    if (strv[i])
59194955Strasz      m_strings.push_back(strv[i]);
60194955Strasz  }
61194955Strasz}
62194955Strasz
63194955Straszvoid StringList::AppendList(StringList strings) {
64194955Strasz  size_t len = strings.GetSize();
65194955Strasz
66194955Strasz  for (size_t i = 0; i < len; ++i)
67194955Strasz    m_strings.push_back(strings.GetStringAtIndex(i));
68194955Strasz}
69194955Strasz
7075928Sjedgarsize_t StringList::GetSize() const { return m_strings.size(); }
7175928Sjedgar
7275928Sjedgarsize_t StringList::GetMaxStringLength() const {
7375928Sjedgar  size_t max_length = 0;
7474432Sjedgar  for (const auto &s : m_strings) {
7574432Sjedgar    const size_t len = s.size();
7674432Sjedgar    if (max_length < len)
7775928Sjedgar      max_length = len;
78200992Smarkus  }
79194955Strasz  return max_length;
8074432Sjedgar}
8190781Sjedgar
8274432Sjedgarconst char *StringList::GetStringAtIndex(size_t idx) const {
8390781Sjedgar  if (idx < m_strings.size())
8474432Sjedgar    return m_strings[idx].c_str();
8575928Sjedgar  return nullptr;
8675928Sjedgar}
8775928Sjedgar
88194955Straszvoid StringList::Join(const char *separator, Stream &strm) {
89194955Strasz  size_t size = GetSize();
90194955Strasz
91194955Strasz  if (size == 0)
92194955Strasz    return;
9375928Sjedgar
9475928Sjedgar  for (uint32_t i = 0; i < size; ++i) {
9575928Sjedgar    if (i > 0)
9690781Sjedgar      strm.PutCString(separator);
9775928Sjedgar    strm.PutCString(GetStringAtIndex(i));
98200992Smarkus  }
99200992Smarkus}
100200992Smarkus
101200992Smarkusvoid StringList::Clear() { m_strings.clear(); }
102194955Strasz
103200992Smarkusvoid StringList::LongestCommonPrefix(std::string &common_prefix) {
10474432Sjedgar  common_prefix.clear();
105194955Strasz  if (m_strings.empty())
106194955Strasz    return;
107194955Strasz
10874432Sjedgar  auto args = llvm::makeArrayRef(m_strings);
10975928Sjedgar  llvm::StringRef prefix = args.front();
110194955Strasz  for (auto arg : args.drop_front()) {
11175928Sjedgar    size_t count = 0;
11275928Sjedgar    for (count = 0; count < std::min(prefix.size(), arg.size()); ++count) {
113194955Strasz      if (prefix[count] != arg[count])
114194955Strasz        break;
115194955Strasz    }
116194955Strasz    prefix = prefix.take_front(count);
117194955Strasz  }
11874432Sjedgar  common_prefix = prefix;
11974432Sjedgar}
120194955Strasz
121194955Straszvoid StringList::InsertStringAtIndex(size_t idx, const char *str) {
12274432Sjedgar  if (str) {
12374432Sjedgar    if (idx < m_strings.size())
12490781Sjedgar      m_strings.insert(m_strings.begin() + idx, str);
12574432Sjedgar    else
126194955Strasz      m_strings.push_back(str);
127194955Strasz  }
128194955Strasz}
129194955Strasz
130194955Straszvoid StringList::InsertStringAtIndex(size_t idx, const std::string &str) {
131194955Strasz  if (idx < m_strings.size())
132194955Strasz    m_strings.insert(m_strings.begin() + idx, str);
133194955Strasz  else
134194955Strasz    m_strings.push_back(str);
135194955Strasz}
136194955Strasz
137194955Straszvoid StringList::InsertStringAtIndex(size_t idx, std::string &&str) {
138194955Strasz  if (idx < m_strings.size())
139194955Strasz    m_strings.insert(m_strings.begin() + idx, str);
140194955Strasz  else
141194955Strasz    m_strings.push_back(str);
142194955Strasz}
143194955Strasz
144194955Straszvoid StringList::DeleteStringAtIndex(size_t idx) {
145194955Strasz  if (idx < m_strings.size())
146194955Strasz    m_strings.erase(m_strings.begin() + idx);
147194955Strasz}
148194955Strasz
149194955Straszsize_t StringList::SplitIntoLines(const std::string &lines) {
150194955Strasz  return SplitIntoLines(lines.c_str(), lines.size());
151194955Strasz}
152194955Strasz
153194955Straszsize_t StringList::SplitIntoLines(const char *lines, size_t len) {
154194955Strasz  const size_t orig_size = m_strings.size();
155194955Strasz
156194955Strasz  if (len == 0)
157194955Strasz    return 0;
158194955Strasz
159194955Strasz  const char *k_newline_chars = "\r\n";
160194955Strasz  const char *p = lines;
161194955Strasz  const char *end = lines + len;
162194955Strasz  while (p < end) {
163    size_t count = strcspn(p, k_newline_chars);
164    if (count == 0) {
165      if (p[count] == '\r' || p[count] == '\n')
166        m_strings.push_back(std::string());
167      else
168        break;
169    } else {
170      if (p + count > end)
171        count = end - p;
172      m_strings.push_back(std::string(p, count));
173    }
174    if (p[count] == '\r' && p[count + 1] == '\n')
175      count++; // Skip an extra newline char for the DOS newline
176    count++;   // Skip the newline character
177    p += count;
178  }
179  return m_strings.size() - orig_size;
180}
181
182void StringList::RemoveBlankLines() {
183  if (GetSize() == 0)
184    return;
185
186  size_t idx = 0;
187  while (idx < m_strings.size()) {
188    if (m_strings[idx].empty())
189      DeleteStringAtIndex(idx);
190    else
191      idx++;
192  }
193}
194
195std::string StringList::CopyList(const char *item_preamble,
196                                 const char *items_sep) const {
197  StreamString strm;
198  for (size_t i = 0; i < GetSize(); i++) {
199    if (i && items_sep && items_sep[0])
200      strm << items_sep;
201    if (item_preamble)
202      strm << item_preamble;
203    strm << GetStringAtIndex(i);
204  }
205  return strm.GetString();
206}
207
208StringList &StringList::operator<<(const char *str) {
209  AppendString(str);
210  return *this;
211}
212
213StringList &StringList::operator<<(const std::string &str) {
214  AppendString(str);
215  return *this;
216}
217
218StringList &StringList::operator<<(StringList strings) {
219  AppendList(strings);
220  return *this;
221}
222
223StringList &StringList::operator=(const std::vector<std::string> &rhs) {
224  m_strings.assign(rhs.begin(), rhs.end());
225
226  return *this;
227}
228
229size_t StringList::AutoComplete(llvm::StringRef s, StringList &matches,
230                                size_t &exact_idx) const {
231  matches.Clear();
232  exact_idx = SIZE_MAX;
233  if (s.empty()) {
234    // No string, so it matches everything
235    matches = *this;
236    return matches.GetSize();
237  }
238
239  const size_t s_len = s.size();
240  const size_t num_strings = m_strings.size();
241
242  for (size_t i = 0; i < num_strings; ++i) {
243    if (m_strings[i].find(s) == 0) {
244      if (exact_idx == SIZE_MAX && m_strings[i].size() == s_len)
245        exact_idx = matches.GetSize();
246      matches.AppendString(m_strings[i]);
247    }
248  }
249  return matches.GetSize();
250}
251
252void StringList::LogDump(Log *log, const char *name) {
253  if (!log)
254    return;
255
256  StreamString strm;
257  if (name)
258    strm.Printf("Begin %s:\n", name);
259  for (const auto &s : m_strings) {
260    strm.Indent();
261    strm.Printf("%s\n", s.c_str());
262  }
263  if (name)
264    strm.Printf("End %s.\n", name);
265
266  LLDB_LOGV(log, "{0}", strm.GetData());
267}
268