180814287SRaphael Isemann //===-- StringList.cpp ----------------------------------------------------===//
2573ab909SZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6573ab909SZachary Turner //
7573ab909SZachary Turner //===----------------------------------------------------------------------===//
8573ab909SZachary Turner 
9573ab909SZachary Turner #include "lldb/Utility/StringList.h"
10573ab909SZachary Turner 
11573ab909SZachary Turner #include "lldb/Utility/Log.h"
12672d2c12SJonas Devlieghere #include "lldb/Utility/Stream.h"
13573ab909SZachary Turner #include "lldb/Utility/StreamString.h"
14672d2c12SJonas Devlieghere #include "llvm/ADT/ArrayRef.h"
15573ab909SZachary Turner 
16672d2c12SJonas Devlieghere #include <algorithm>
17672d2c12SJonas Devlieghere #include <stdint.h>
18672d2c12SJonas Devlieghere #include <string.h>
19573ab909SZachary Turner 
20573ab909SZachary Turner using namespace lldb_private;
21573ab909SZachary Turner 
22573ab909SZachary Turner StringList::StringList() : m_strings() {}
23573ab909SZachary Turner 
24573ab909SZachary Turner StringList::StringList(const char *str) : m_strings() {
25573ab909SZachary Turner   if (str)
26573ab909SZachary Turner     m_strings.push_back(str);
27573ab909SZachary Turner }
28573ab909SZachary Turner 
29573ab909SZachary Turner StringList::StringList(const char **strv, int strc) : m_strings() {
30573ab909SZachary Turner   for (int i = 0; i < strc; ++i) {
31573ab909SZachary Turner     if (strv[i])
32573ab909SZachary Turner       m_strings.push_back(strv[i]);
33573ab909SZachary Turner   }
34573ab909SZachary Turner }
35573ab909SZachary Turner 
36573ab909SZachary Turner StringList::~StringList() {}
37573ab909SZachary Turner 
38573ab909SZachary Turner void StringList::AppendString(const char *str) {
39573ab909SZachary Turner   if (str)
40573ab909SZachary Turner     m_strings.push_back(str);
41573ab909SZachary Turner }
42573ab909SZachary Turner 
43573ab909SZachary Turner void StringList::AppendString(const std::string &s) { m_strings.push_back(s); }
44573ab909SZachary Turner 
45573ab909SZachary Turner void StringList::AppendString(std::string &&s) { m_strings.push_back(s); }
46573ab909SZachary Turner 
47573ab909SZachary Turner void StringList::AppendString(const char *str, size_t str_len) {
48573ab909SZachary Turner   if (str)
49573ab909SZachary Turner     m_strings.push_back(std::string(str, str_len));
50573ab909SZachary Turner }
51573ab909SZachary Turner 
52573ab909SZachary Turner void StringList::AppendString(llvm::StringRef str) {
53573ab909SZachary Turner   m_strings.push_back(str.str());
54573ab909SZachary Turner }
55573ab909SZachary Turner 
56573ab909SZachary Turner void StringList::AppendList(const char **strv, int strc) {
57573ab909SZachary Turner   for (int i = 0; i < strc; ++i) {
58573ab909SZachary Turner     if (strv[i])
59573ab909SZachary Turner       m_strings.push_back(strv[i]);
60573ab909SZachary Turner   }
61573ab909SZachary Turner }
62573ab909SZachary Turner 
63573ab909SZachary Turner void StringList::AppendList(StringList strings) {
6421599876SRaphael Isemann   m_strings.reserve(m_strings.size() + strings.GetSize());
654c78b788SRaphael Isemann   m_strings.insert(m_strings.end(), strings.begin(), strings.end());
66573ab909SZachary Turner }
67573ab909SZachary Turner 
68573ab909SZachary Turner size_t StringList::GetSize() const { return m_strings.size(); }
69573ab909SZachary Turner 
70573ab909SZachary Turner size_t StringList::GetMaxStringLength() const {
71573ab909SZachary Turner   size_t max_length = 0;
72573ab909SZachary Turner   for (const auto &s : m_strings) {
73573ab909SZachary Turner     const size_t len = s.size();
74573ab909SZachary Turner     if (max_length < len)
75573ab909SZachary Turner       max_length = len;
76573ab909SZachary Turner   }
77573ab909SZachary Turner   return max_length;
78573ab909SZachary Turner }
79573ab909SZachary Turner 
80573ab909SZachary Turner const char *StringList::GetStringAtIndex(size_t idx) const {
81573ab909SZachary Turner   if (idx < m_strings.size())
82573ab909SZachary Turner     return m_strings[idx].c_str();
8365e5e278SJonas Devlieghere   return nullptr;
84573ab909SZachary Turner }
85573ab909SZachary Turner 
86573ab909SZachary Turner void StringList::Join(const char *separator, Stream &strm) {
87573ab909SZachary Turner   size_t size = GetSize();
88573ab909SZachary Turner 
89573ab909SZachary Turner   if (size == 0)
90573ab909SZachary Turner     return;
91573ab909SZachary Turner 
92573ab909SZachary Turner   for (uint32_t i = 0; i < size; ++i) {
93573ab909SZachary Turner     if (i > 0)
94573ab909SZachary Turner       strm.PutCString(separator);
95573ab909SZachary Turner     strm.PutCString(GetStringAtIndex(i));
96573ab909SZachary Turner   }
97573ab909SZachary Turner }
98573ab909SZachary Turner 
99573ab909SZachary Turner void StringList::Clear() { m_strings.clear(); }
100573ab909SZachary Turner 
101175f0930SJonas Devlieghere std::string StringList::LongestCommonPrefix() {
102573ab909SZachary Turner   if (m_strings.empty())
103175f0930SJonas Devlieghere     return {};
104573ab909SZachary Turner 
105573ab909SZachary Turner   auto args = llvm::makeArrayRef(m_strings);
106573ab909SZachary Turner   llvm::StringRef prefix = args.front();
107573ab909SZachary Turner   for (auto arg : args.drop_front()) {
108573ab909SZachary Turner     size_t count = 0;
109573ab909SZachary Turner     for (count = 0; count < std::min(prefix.size(), arg.size()); ++count) {
110573ab909SZachary Turner       if (prefix[count] != arg[count])
111573ab909SZachary Turner         break;
112573ab909SZachary Turner     }
113573ab909SZachary Turner     prefix = prefix.take_front(count);
114573ab909SZachary Turner   }
115175f0930SJonas Devlieghere   return prefix.str();
116573ab909SZachary Turner }
117573ab909SZachary Turner 
118573ab909SZachary Turner void StringList::InsertStringAtIndex(size_t idx, const char *str) {
119573ab909SZachary Turner   if (str) {
120573ab909SZachary Turner     if (idx < m_strings.size())
121573ab909SZachary Turner       m_strings.insert(m_strings.begin() + idx, str);
122573ab909SZachary Turner     else
123573ab909SZachary Turner       m_strings.push_back(str);
124573ab909SZachary Turner   }
125573ab909SZachary Turner }
126573ab909SZachary Turner 
127573ab909SZachary Turner void StringList::InsertStringAtIndex(size_t idx, const std::string &str) {
128573ab909SZachary Turner   if (idx < m_strings.size())
129573ab909SZachary Turner     m_strings.insert(m_strings.begin() + idx, str);
130573ab909SZachary Turner   else
131573ab909SZachary Turner     m_strings.push_back(str);
132573ab909SZachary Turner }
133573ab909SZachary Turner 
134573ab909SZachary Turner void StringList::InsertStringAtIndex(size_t idx, std::string &&str) {
135573ab909SZachary Turner   if (idx < m_strings.size())
136573ab909SZachary Turner     m_strings.insert(m_strings.begin() + idx, str);
137573ab909SZachary Turner   else
138573ab909SZachary Turner     m_strings.push_back(str);
139573ab909SZachary Turner }
140573ab909SZachary Turner 
141573ab909SZachary Turner void StringList::DeleteStringAtIndex(size_t idx) {
142573ab909SZachary Turner   if (idx < m_strings.size())
143573ab909SZachary Turner     m_strings.erase(m_strings.begin() + idx);
144573ab909SZachary Turner }
145573ab909SZachary Turner 
146573ab909SZachary Turner size_t StringList::SplitIntoLines(const std::string &lines) {
147573ab909SZachary Turner   return SplitIntoLines(lines.c_str(), lines.size());
148573ab909SZachary Turner }
149573ab909SZachary Turner 
150573ab909SZachary Turner size_t StringList::SplitIntoLines(const char *lines, size_t len) {
151573ab909SZachary Turner   const size_t orig_size = m_strings.size();
152573ab909SZachary Turner 
153573ab909SZachary Turner   if (len == 0)
154573ab909SZachary Turner     return 0;
155573ab909SZachary Turner 
156573ab909SZachary Turner   const char *k_newline_chars = "\r\n";
157573ab909SZachary Turner   const char *p = lines;
158573ab909SZachary Turner   const char *end = lines + len;
159573ab909SZachary Turner   while (p < end) {
160573ab909SZachary Turner     size_t count = strcspn(p, k_newline_chars);
161573ab909SZachary Turner     if (count == 0) {
162573ab909SZachary Turner       if (p[count] == '\r' || p[count] == '\n')
163573ab909SZachary Turner         m_strings.push_back(std::string());
164573ab909SZachary Turner       else
165573ab909SZachary Turner         break;
166573ab909SZachary Turner     } else {
167573ab909SZachary Turner       if (p + count > end)
168573ab909SZachary Turner         count = end - p;
169573ab909SZachary Turner       m_strings.push_back(std::string(p, count));
170573ab909SZachary Turner     }
171573ab909SZachary Turner     if (p[count] == '\r' && p[count + 1] == '\n')
172573ab909SZachary Turner       count++; // Skip an extra newline char for the DOS newline
173573ab909SZachary Turner     count++;   // Skip the newline character
174573ab909SZachary Turner     p += count;
175573ab909SZachary Turner   }
176573ab909SZachary Turner   return m_strings.size() - orig_size;
177573ab909SZachary Turner }
178573ab909SZachary Turner 
179573ab909SZachary Turner void StringList::RemoveBlankLines() {
180573ab909SZachary Turner   if (GetSize() == 0)
181573ab909SZachary Turner     return;
182573ab909SZachary Turner 
183573ab909SZachary Turner   size_t idx = 0;
184573ab909SZachary Turner   while (idx < m_strings.size()) {
185573ab909SZachary Turner     if (m_strings[idx].empty())
186573ab909SZachary Turner       DeleteStringAtIndex(idx);
187573ab909SZachary Turner     else
188573ab909SZachary Turner       idx++;
189573ab909SZachary Turner   }
190573ab909SZachary Turner }
191573ab909SZachary Turner 
192573ab909SZachary Turner std::string StringList::CopyList(const char *item_preamble,
193573ab909SZachary Turner                                  const char *items_sep) const {
194573ab909SZachary Turner   StreamString strm;
195573ab909SZachary Turner   for (size_t i = 0; i < GetSize(); i++) {
196573ab909SZachary Turner     if (i && items_sep && items_sep[0])
197573ab909SZachary Turner       strm << items_sep;
198573ab909SZachary Turner     if (item_preamble)
199573ab909SZachary Turner       strm << item_preamble;
200573ab909SZachary Turner     strm << GetStringAtIndex(i);
201573ab909SZachary Turner   }
202*adcd0268SBenjamin Kramer   return std::string(strm.GetString());
203573ab909SZachary Turner }
204573ab909SZachary Turner 
205573ab909SZachary Turner StringList &StringList::operator<<(const char *str) {
206573ab909SZachary Turner   AppendString(str);
207573ab909SZachary Turner   return *this;
208573ab909SZachary Turner }
209573ab909SZachary Turner 
210573ab909SZachary Turner StringList &StringList::operator<<(const std::string &str) {
211573ab909SZachary Turner   AppendString(str);
212573ab909SZachary Turner   return *this;
213573ab909SZachary Turner }
214573ab909SZachary Turner 
215573ab909SZachary Turner StringList &StringList::operator<<(StringList strings) {
216573ab909SZachary Turner   AppendList(strings);
217573ab909SZachary Turner   return *this;
218573ab909SZachary Turner }
219573ab909SZachary Turner 
220573ab909SZachary Turner StringList &StringList::operator=(const std::vector<std::string> &rhs) {
221573ab909SZachary Turner   m_strings.assign(rhs.begin(), rhs.end());
222573ab909SZachary Turner 
223573ab909SZachary Turner   return *this;
224573ab909SZachary Turner }
225573ab909SZachary Turner 
226573ab909SZachary Turner void StringList::LogDump(Log *log, const char *name) {
227573ab909SZachary Turner   if (!log)
228573ab909SZachary Turner     return;
229573ab909SZachary Turner 
230573ab909SZachary Turner   StreamString strm;
231573ab909SZachary Turner   if (name)
232573ab909SZachary Turner     strm.Printf("Begin %s:\n", name);
233573ab909SZachary Turner   for (const auto &s : m_strings) {
234573ab909SZachary Turner     strm.Indent();
235573ab909SZachary Turner     strm.Printf("%s\n", s.c_str());
236573ab909SZachary Turner   }
237573ab909SZachary Turner   if (name)
238573ab909SZachary Turner     strm.Printf("End %s.\n", name);
239573ab909SZachary Turner 
240573ab909SZachary Turner   LLDB_LOGV(log, "{0}", strm.GetData());
241573ab909SZachary Turner }
242