1cfca06d7SDimitry Andric //===-- StringList.cpp ----------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
974a628f7SDimitry Andric #include "lldb/Utility/StringList.h"
10f034231aSEd Maste
1174a628f7SDimitry Andric #include "lldb/Utility/Log.h"
1294994d37SDimitry Andric #include "lldb/Utility/Stream.h"
1374a628f7SDimitry Andric #include "lldb/Utility/StreamString.h"
1494994d37SDimitry Andric #include "llvm/ADT/ArrayRef.h"
15f034231aSEd Maste
1694994d37SDimitry Andric #include <algorithm>
17344a3780SDimitry Andric #include <cstdint>
18344a3780SDimitry Andric #include <cstring>
19f034231aSEd Maste
20f034231aSEd Maste using namespace lldb_private;
21f034231aSEd Maste
StringList()2214f1b3e8SDimitry Andric StringList::StringList() : m_strings() {}
23f034231aSEd Maste
StringList(const char * str)2414f1b3e8SDimitry Andric StringList::StringList(const char *str) : m_strings() {
25f034231aSEd Maste if (str)
26f034231aSEd Maste m_strings.push_back(str);
27f034231aSEd Maste }
28f034231aSEd Maste
StringList(const char ** strv,int strc)2914f1b3e8SDimitry Andric StringList::StringList(const char **strv, int strc) : m_strings() {
3014f1b3e8SDimitry Andric for (int i = 0; i < strc; ++i) {
31f034231aSEd Maste if (strv[i])
32f034231aSEd Maste m_strings.push_back(strv[i]);
33f034231aSEd Maste }
34f034231aSEd Maste }
35f034231aSEd Maste
36344a3780SDimitry Andric StringList::~StringList() = default;
37f034231aSEd Maste
AppendString(const char * str)3814f1b3e8SDimitry Andric void StringList::AppendString(const char *str) {
39f034231aSEd Maste if (str)
40f034231aSEd Maste m_strings.push_back(str);
41f034231aSEd Maste }
42f034231aSEd Maste
AppendString(const std::string & s)4314f1b3e8SDimitry Andric void StringList::AppendString(const std::string &s) { m_strings.push_back(s); }
44f034231aSEd Maste
AppendString(std::string && s)456f8fc217SDimitry Andric void StringList::AppendString(std::string &&s) {
466f8fc217SDimitry Andric m_strings.push_back(std::move(s));
476f8fc217SDimitry Andric }
48866dcdacSEd Maste
AppendString(const char * str,size_t str_len)4914f1b3e8SDimitry Andric void StringList::AppendString(const char *str, size_t str_len) {
50f034231aSEd Maste if (str)
51f034231aSEd Maste m_strings.push_back(std::string(str, str_len));
52f034231aSEd Maste }
53f034231aSEd Maste
AppendString(llvm::StringRef str)5414f1b3e8SDimitry Andric void StringList::AppendString(llvm::StringRef str) {
555e95aa85SEd Maste m_strings.push_back(str.str());
565e95aa85SEd Maste }
575e95aa85SEd Maste
AppendString(const llvm::Twine & str)586f8fc217SDimitry Andric void StringList::AppendString(const llvm::Twine &str) {
596f8fc217SDimitry Andric m_strings.push_back(str.str());
606f8fc217SDimitry Andric }
616f8fc217SDimitry Andric
AppendList(const char ** strv,int strc)6214f1b3e8SDimitry Andric void StringList::AppendList(const char **strv, int strc) {
6314f1b3e8SDimitry Andric for (int i = 0; i < strc; ++i) {
64f034231aSEd Maste if (strv[i])
65f034231aSEd Maste m_strings.push_back(strv[i]);
66f034231aSEd Maste }
67f034231aSEd Maste }
68f034231aSEd Maste
AppendList(StringList strings)6914f1b3e8SDimitry Andric void StringList::AppendList(StringList strings) {
70ead24645SDimitry Andric m_strings.reserve(m_strings.size() + strings.GetSize());
71ead24645SDimitry Andric m_strings.insert(m_strings.end(), strings.begin(), strings.end());
72f034231aSEd Maste }
73f034231aSEd Maste
GetSize() const7414f1b3e8SDimitry Andric size_t StringList::GetSize() const { return m_strings.size(); }
75f034231aSEd Maste
GetMaxStringLength() const7614f1b3e8SDimitry Andric size_t StringList::GetMaxStringLength() const {
77866dcdacSEd Maste size_t max_length = 0;
7814f1b3e8SDimitry Andric for (const auto &s : m_strings) {
79866dcdacSEd Maste const size_t len = s.size();
80866dcdacSEd Maste if (max_length < len)
81866dcdacSEd Maste max_length = len;
82866dcdacSEd Maste }
83866dcdacSEd Maste return max_length;
84866dcdacSEd Maste }
85866dcdacSEd Maste
GetStringAtIndex(size_t idx) const8614f1b3e8SDimitry Andric const char *StringList::GetStringAtIndex(size_t idx) const {
87f034231aSEd Maste if (idx < m_strings.size())
88f034231aSEd Maste return m_strings[idx].c_str();
8994994d37SDimitry Andric return nullptr;
90f034231aSEd Maste }
91f034231aSEd Maste
Join(const char * separator,Stream & strm)9214f1b3e8SDimitry Andric void StringList::Join(const char *separator, Stream &strm) {
93f034231aSEd Maste size_t size = GetSize();
94f034231aSEd Maste
95f034231aSEd Maste if (size == 0)
96f034231aSEd Maste return;
97f034231aSEd Maste
9814f1b3e8SDimitry Andric for (uint32_t i = 0; i < size; ++i) {
99f034231aSEd Maste if (i > 0)
100f034231aSEd Maste strm.PutCString(separator);
101f034231aSEd Maste strm.PutCString(GetStringAtIndex(i));
102f034231aSEd Maste }
103f034231aSEd Maste }
104f034231aSEd Maste
Clear()10514f1b3e8SDimitry Andric void StringList::Clear() { m_strings.clear(); }
106f034231aSEd Maste
LongestCommonPrefix()107ead24645SDimitry Andric std::string StringList::LongestCommonPrefix() {
10814f1b3e8SDimitry Andric if (m_strings.empty())
109ead24645SDimitry Andric return {};
110866dcdacSEd Maste
111e3b55780SDimitry Andric auto args = llvm::ArrayRef(m_strings);
11214f1b3e8SDimitry Andric llvm::StringRef prefix = args.front();
11314f1b3e8SDimitry Andric for (auto arg : args.drop_front()) {
11414f1b3e8SDimitry Andric size_t count = 0;
11514f1b3e8SDimitry Andric for (count = 0; count < std::min(prefix.size(), arg.size()); ++count) {
11614f1b3e8SDimitry Andric if (prefix[count] != arg[count])
117f034231aSEd Maste break;
118f034231aSEd Maste }
11914f1b3e8SDimitry Andric prefix = prefix.take_front(count);
12014f1b3e8SDimitry Andric }
121ead24645SDimitry Andric return prefix.str();
122f034231aSEd Maste }
123f034231aSEd Maste
InsertStringAtIndex(size_t idx,const char * str)12414f1b3e8SDimitry Andric void StringList::InsertStringAtIndex(size_t idx, const char *str) {
12514f1b3e8SDimitry Andric if (str) {
126f034231aSEd Maste if (idx < m_strings.size())
127f034231aSEd Maste m_strings.insert(m_strings.begin() + idx, str);
128f034231aSEd Maste else
129f034231aSEd Maste m_strings.push_back(str);
130f034231aSEd Maste }
131f034231aSEd Maste }
132f034231aSEd Maste
InsertStringAtIndex(size_t idx,const std::string & str)13314f1b3e8SDimitry Andric void StringList::InsertStringAtIndex(size_t idx, const std::string &str) {
134866dcdacSEd Maste if (idx < m_strings.size())
135866dcdacSEd Maste m_strings.insert(m_strings.begin() + idx, str);
136866dcdacSEd Maste else
137866dcdacSEd Maste m_strings.push_back(str);
138866dcdacSEd Maste }
139866dcdacSEd Maste
InsertStringAtIndex(size_t idx,std::string && str)14014f1b3e8SDimitry Andric void StringList::InsertStringAtIndex(size_t idx, std::string &&str) {
141866dcdacSEd Maste if (idx < m_strings.size())
1426f8fc217SDimitry Andric m_strings.insert(m_strings.begin() + idx, std::move(str));
143866dcdacSEd Maste else
1446f8fc217SDimitry Andric m_strings.push_back(std::move(str));
145866dcdacSEd Maste }
146866dcdacSEd Maste
DeleteStringAtIndex(size_t idx)14714f1b3e8SDimitry Andric void StringList::DeleteStringAtIndex(size_t idx) {
148f034231aSEd Maste if (idx < m_strings.size())
149f034231aSEd Maste m_strings.erase(m_strings.begin() + idx);
150f034231aSEd Maste }
151f034231aSEd Maste
SplitIntoLines(const std::string & lines)15214f1b3e8SDimitry Andric size_t StringList::SplitIntoLines(const std::string &lines) {
153866dcdacSEd Maste return SplitIntoLines(lines.c_str(), lines.size());
154866dcdacSEd Maste }
155866dcdacSEd Maste
SplitIntoLines(const char * lines,size_t len)15614f1b3e8SDimitry Andric size_t StringList::SplitIntoLines(const char *lines, size_t len) {
157f034231aSEd Maste const size_t orig_size = m_strings.size();
158f034231aSEd Maste
159f034231aSEd Maste if (len == 0)
160f034231aSEd Maste return 0;
161f034231aSEd Maste
162f034231aSEd Maste const char *k_newline_chars = "\r\n";
163f034231aSEd Maste const char *p = lines;
164f034231aSEd Maste const char *end = lines + len;
16514f1b3e8SDimitry Andric while (p < end) {
166f034231aSEd Maste size_t count = strcspn(p, k_newline_chars);
16714f1b3e8SDimitry Andric if (count == 0) {
168f034231aSEd Maste if (p[count] == '\r' || p[count] == '\n')
169f034231aSEd Maste m_strings.push_back(std::string());
170f034231aSEd Maste else
171f034231aSEd Maste break;
17214f1b3e8SDimitry Andric } else {
173f034231aSEd Maste if (p + count > end)
174f034231aSEd Maste count = end - p;
175f034231aSEd Maste m_strings.push_back(std::string(p, count));
176f034231aSEd Maste }
177f034231aSEd Maste if (p[count] == '\r' && p[count + 1] == '\n')
178f034231aSEd Maste count++; // Skip an extra newline char for the DOS newline
179f034231aSEd Maste count++; // Skip the newline character
180f034231aSEd Maste p += count;
181f034231aSEd Maste }
182f034231aSEd Maste return m_strings.size() - orig_size;
183f034231aSEd Maste }
184f034231aSEd Maste
RemoveBlankLines()18514f1b3e8SDimitry Andric void StringList::RemoveBlankLines() {
186f034231aSEd Maste if (GetSize() == 0)
187f034231aSEd Maste return;
188f034231aSEd Maste
189f034231aSEd Maste size_t idx = 0;
19014f1b3e8SDimitry Andric while (idx < m_strings.size()) {
191f034231aSEd Maste if (m_strings[idx].empty())
192f034231aSEd Maste DeleteStringAtIndex(idx);
193f034231aSEd Maste else
194f034231aSEd Maste idx++;
195f034231aSEd Maste }
196f034231aSEd Maste }
197f034231aSEd Maste
CopyList(const char * item_preamble,const char * items_sep) const19814f1b3e8SDimitry Andric std::string StringList::CopyList(const char *item_preamble,
19914f1b3e8SDimitry Andric const char *items_sep) const {
200f034231aSEd Maste StreamString strm;
20114f1b3e8SDimitry Andric for (size_t i = 0; i < GetSize(); i++) {
202f034231aSEd Maste if (i && items_sep && items_sep[0])
203f034231aSEd Maste strm << items_sep;
204f034231aSEd Maste if (item_preamble)
205f034231aSEd Maste strm << item_preamble;
206f034231aSEd Maste strm << GetStringAtIndex(i);
207f034231aSEd Maste }
208cfca06d7SDimitry Andric return std::string(strm.GetString());
209f034231aSEd Maste }
210f034231aSEd Maste
operator <<(const char * str)21114f1b3e8SDimitry Andric StringList &StringList::operator<<(const char *str) {
212f034231aSEd Maste AppendString(str);
213f034231aSEd Maste return *this;
214f034231aSEd Maste }
215f034231aSEd Maste
operator <<(const std::string & str)21614f1b3e8SDimitry Andric StringList &StringList::operator<<(const std::string &str) {
2179e6d3549SDimitry Andric AppendString(str);
2189e6d3549SDimitry Andric return *this;
2199e6d3549SDimitry Andric }
2209e6d3549SDimitry Andric
operator <<(const StringList & strings)221b60736ecSDimitry Andric StringList &StringList::operator<<(const StringList &strings) {
222f034231aSEd Maste AppendList(strings);
223f034231aSEd Maste return *this;
224f034231aSEd Maste }
225f034231aSEd Maste
operator =(const std::vector<std::string> & rhs)22614f1b3e8SDimitry Andric StringList &StringList::operator=(const std::vector<std::string> &rhs) {
22774a628f7SDimitry Andric m_strings.assign(rhs.begin(), rhs.end());
2289e6d3549SDimitry Andric
2299e6d3549SDimitry Andric return *this;
2309e6d3549SDimitry Andric }
2319e6d3549SDimitry Andric
LogDump(Log * log,const char * name)23214f1b3e8SDimitry Andric void StringList::LogDump(Log *log, const char *name) {
2339e6d3549SDimitry Andric if (!log)
2349e6d3549SDimitry Andric return;
2359e6d3549SDimitry Andric
2369e6d3549SDimitry Andric StreamString strm;
2379e6d3549SDimitry Andric if (name)
2389e6d3549SDimitry Andric strm.Printf("Begin %s:\n", name);
2399e6d3549SDimitry Andric for (const auto &s : m_strings) {
2409e6d3549SDimitry Andric strm.Indent();
2419e6d3549SDimitry Andric strm.Printf("%s\n", s.c_str());
2429e6d3549SDimitry Andric }
2439e6d3549SDimitry Andric if (name)
2449e6d3549SDimitry Andric strm.Printf("End %s.\n", name);
2459e6d3549SDimitry Andric
24674a628f7SDimitry Andric LLDB_LOGV(log, "{0}", strm.GetData());
2479e6d3549SDimitry Andric }
248