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