xref: /freebsd-src/contrib/llvm-project/lldb/source/Utility/StringList.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
15ffd83dbSDimitry Andric //===-- StringList.cpp ----------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Utility/StringList.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
120b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
130b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
140b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include <algorithm>
17fe6060f1SDimitry Andric #include <cstdint>
18fe6060f1SDimitry Andric #include <cstring>
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric using namespace lldb_private;
210b57cec5SDimitry Andric 
StringList()220b57cec5SDimitry Andric StringList::StringList() : m_strings() {}
230b57cec5SDimitry Andric 
StringList(const char * str)240b57cec5SDimitry Andric StringList::StringList(const char *str) : m_strings() {
250b57cec5SDimitry Andric   if (str)
260b57cec5SDimitry Andric     m_strings.push_back(str);
270b57cec5SDimitry Andric }
280b57cec5SDimitry Andric 
StringList(const char ** strv,int strc)290b57cec5SDimitry Andric StringList::StringList(const char **strv, int strc) : m_strings() {
300b57cec5SDimitry Andric   for (int i = 0; i < strc; ++i) {
310b57cec5SDimitry Andric     if (strv[i])
320b57cec5SDimitry Andric       m_strings.push_back(strv[i]);
330b57cec5SDimitry Andric   }
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric 
36fe6060f1SDimitry Andric StringList::~StringList() = default;
370b57cec5SDimitry Andric 
AppendString(const char * str)380b57cec5SDimitry Andric void StringList::AppendString(const char *str) {
390b57cec5SDimitry Andric   if (str)
400b57cec5SDimitry Andric     m_strings.push_back(str);
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric 
AppendString(const std::string & s)430b57cec5SDimitry Andric void StringList::AppendString(const std::string &s) { m_strings.push_back(s); }
440b57cec5SDimitry Andric 
AppendString(std::string && s)4504eeddc0SDimitry Andric void StringList::AppendString(std::string &&s) {
4604eeddc0SDimitry Andric   m_strings.push_back(std::move(s));
4704eeddc0SDimitry Andric }
480b57cec5SDimitry Andric 
AppendString(const char * str,size_t str_len)490b57cec5SDimitry Andric void StringList::AppendString(const char *str, size_t str_len) {
500b57cec5SDimitry Andric   if (str)
510b57cec5SDimitry Andric     m_strings.push_back(std::string(str, str_len));
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric 
AppendString(llvm::StringRef str)540b57cec5SDimitry Andric void StringList::AppendString(llvm::StringRef str) {
550b57cec5SDimitry Andric   m_strings.push_back(str.str());
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric 
AppendString(const llvm::Twine & str)5804eeddc0SDimitry Andric void StringList::AppendString(const llvm::Twine &str) {
5904eeddc0SDimitry Andric   m_strings.push_back(str.str());
6004eeddc0SDimitry Andric }
6104eeddc0SDimitry Andric 
AppendList(const char ** strv,int strc)620b57cec5SDimitry Andric void StringList::AppendList(const char **strv, int strc) {
630b57cec5SDimitry Andric   for (int i = 0; i < strc; ++i) {
640b57cec5SDimitry Andric     if (strv[i])
650b57cec5SDimitry Andric       m_strings.push_back(strv[i]);
660b57cec5SDimitry Andric   }
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric 
AppendList(StringList strings)690b57cec5SDimitry Andric void StringList::AppendList(StringList strings) {
709dba64beSDimitry Andric   m_strings.reserve(m_strings.size() + strings.GetSize());
719dba64beSDimitry Andric   m_strings.insert(m_strings.end(), strings.begin(), strings.end());
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric 
GetSize() const740b57cec5SDimitry Andric size_t StringList::GetSize() const { return m_strings.size(); }
750b57cec5SDimitry Andric 
GetMaxStringLength() const760b57cec5SDimitry Andric size_t StringList::GetMaxStringLength() const {
770b57cec5SDimitry Andric   size_t max_length = 0;
780b57cec5SDimitry Andric   for (const auto &s : m_strings) {
790b57cec5SDimitry Andric     const size_t len = s.size();
800b57cec5SDimitry Andric     if (max_length < len)
810b57cec5SDimitry Andric       max_length = len;
820b57cec5SDimitry Andric   }
830b57cec5SDimitry Andric   return max_length;
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric 
GetStringAtIndex(size_t idx) const860b57cec5SDimitry Andric const char *StringList::GetStringAtIndex(size_t idx) const {
870b57cec5SDimitry Andric   if (idx < m_strings.size())
880b57cec5SDimitry Andric     return m_strings[idx].c_str();
890b57cec5SDimitry Andric   return nullptr;
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
Join(const char * separator,Stream & strm)920b57cec5SDimitry Andric void StringList::Join(const char *separator, Stream &strm) {
930b57cec5SDimitry Andric   size_t size = GetSize();
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   if (size == 0)
960b57cec5SDimitry Andric     return;
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   for (uint32_t i = 0; i < size; ++i) {
990b57cec5SDimitry Andric     if (i > 0)
1000b57cec5SDimitry Andric       strm.PutCString(separator);
1010b57cec5SDimitry Andric     strm.PutCString(GetStringAtIndex(i));
1020b57cec5SDimitry Andric   }
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric 
Clear()1050b57cec5SDimitry Andric void StringList::Clear() { m_strings.clear(); }
1060b57cec5SDimitry Andric 
LongestCommonPrefix()1079dba64beSDimitry Andric std::string StringList::LongestCommonPrefix() {
1080b57cec5SDimitry Andric   if (m_strings.empty())
1099dba64beSDimitry Andric     return {};
1100b57cec5SDimitry Andric 
111*bdd1243dSDimitry Andric   auto args = llvm::ArrayRef(m_strings);
1120b57cec5SDimitry Andric   llvm::StringRef prefix = args.front();
1130b57cec5SDimitry Andric   for (auto arg : args.drop_front()) {
1140b57cec5SDimitry Andric     size_t count = 0;
1150b57cec5SDimitry Andric     for (count = 0; count < std::min(prefix.size(), arg.size()); ++count) {
1160b57cec5SDimitry Andric       if (prefix[count] != arg[count])
1170b57cec5SDimitry Andric         break;
1180b57cec5SDimitry Andric     }
1190b57cec5SDimitry Andric     prefix = prefix.take_front(count);
1200b57cec5SDimitry Andric   }
1219dba64beSDimitry Andric   return prefix.str();
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric 
InsertStringAtIndex(size_t idx,const char * str)1240b57cec5SDimitry Andric void StringList::InsertStringAtIndex(size_t idx, const char *str) {
1250b57cec5SDimitry Andric   if (str) {
1260b57cec5SDimitry Andric     if (idx < m_strings.size())
1270b57cec5SDimitry Andric       m_strings.insert(m_strings.begin() + idx, str);
1280b57cec5SDimitry Andric     else
1290b57cec5SDimitry Andric       m_strings.push_back(str);
1300b57cec5SDimitry Andric   }
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric 
InsertStringAtIndex(size_t idx,const std::string & str)1330b57cec5SDimitry Andric void StringList::InsertStringAtIndex(size_t idx, const std::string &str) {
1340b57cec5SDimitry Andric   if (idx < m_strings.size())
1350b57cec5SDimitry Andric     m_strings.insert(m_strings.begin() + idx, str);
1360b57cec5SDimitry Andric   else
1370b57cec5SDimitry Andric     m_strings.push_back(str);
1380b57cec5SDimitry Andric }
1390b57cec5SDimitry Andric 
InsertStringAtIndex(size_t idx,std::string && str)1400b57cec5SDimitry Andric void StringList::InsertStringAtIndex(size_t idx, std::string &&str) {
1410b57cec5SDimitry Andric   if (idx < m_strings.size())
14204eeddc0SDimitry Andric     m_strings.insert(m_strings.begin() + idx, std::move(str));
1430b57cec5SDimitry Andric   else
14404eeddc0SDimitry Andric     m_strings.push_back(std::move(str));
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric 
DeleteStringAtIndex(size_t idx)1470b57cec5SDimitry Andric void StringList::DeleteStringAtIndex(size_t idx) {
1480b57cec5SDimitry Andric   if (idx < m_strings.size())
1490b57cec5SDimitry Andric     m_strings.erase(m_strings.begin() + idx);
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
SplitIntoLines(const std::string & lines)1520b57cec5SDimitry Andric size_t StringList::SplitIntoLines(const std::string &lines) {
1530b57cec5SDimitry Andric   return SplitIntoLines(lines.c_str(), lines.size());
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric 
SplitIntoLines(const char * lines,size_t len)1560b57cec5SDimitry Andric size_t StringList::SplitIntoLines(const char *lines, size_t len) {
1570b57cec5SDimitry Andric   const size_t orig_size = m_strings.size();
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   if (len == 0)
1600b57cec5SDimitry Andric     return 0;
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric   const char *k_newline_chars = "\r\n";
1630b57cec5SDimitry Andric   const char *p = lines;
1640b57cec5SDimitry Andric   const char *end = lines + len;
1650b57cec5SDimitry Andric   while (p < end) {
1660b57cec5SDimitry Andric     size_t count = strcspn(p, k_newline_chars);
1670b57cec5SDimitry Andric     if (count == 0) {
1680b57cec5SDimitry Andric       if (p[count] == '\r' || p[count] == '\n')
1690b57cec5SDimitry Andric         m_strings.push_back(std::string());
1700b57cec5SDimitry Andric       else
1710b57cec5SDimitry Andric         break;
1720b57cec5SDimitry Andric     } else {
1730b57cec5SDimitry Andric       if (p + count > end)
1740b57cec5SDimitry Andric         count = end - p;
1750b57cec5SDimitry Andric       m_strings.push_back(std::string(p, count));
1760b57cec5SDimitry Andric     }
1770b57cec5SDimitry Andric     if (p[count] == '\r' && p[count + 1] == '\n')
1780b57cec5SDimitry Andric       count++; // Skip an extra newline char for the DOS newline
1790b57cec5SDimitry Andric     count++;   // Skip the newline character
1800b57cec5SDimitry Andric     p += count;
1810b57cec5SDimitry Andric   }
1820b57cec5SDimitry Andric   return m_strings.size() - orig_size;
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric 
RemoveBlankLines()1850b57cec5SDimitry Andric void StringList::RemoveBlankLines() {
1860b57cec5SDimitry Andric   if (GetSize() == 0)
1870b57cec5SDimitry Andric     return;
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   size_t idx = 0;
1900b57cec5SDimitry Andric   while (idx < m_strings.size()) {
1910b57cec5SDimitry Andric     if (m_strings[idx].empty())
1920b57cec5SDimitry Andric       DeleteStringAtIndex(idx);
1930b57cec5SDimitry Andric     else
1940b57cec5SDimitry Andric       idx++;
1950b57cec5SDimitry Andric   }
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric 
CopyList(const char * item_preamble,const char * items_sep) const1980b57cec5SDimitry Andric std::string StringList::CopyList(const char *item_preamble,
1990b57cec5SDimitry Andric                                  const char *items_sep) const {
2000b57cec5SDimitry Andric   StreamString strm;
2010b57cec5SDimitry Andric   for (size_t i = 0; i < GetSize(); i++) {
2020b57cec5SDimitry Andric     if (i && items_sep && items_sep[0])
2030b57cec5SDimitry Andric       strm << items_sep;
2040b57cec5SDimitry Andric     if (item_preamble)
2050b57cec5SDimitry Andric       strm << item_preamble;
2060b57cec5SDimitry Andric     strm << GetStringAtIndex(i);
2070b57cec5SDimitry Andric   }
2085ffd83dbSDimitry Andric   return std::string(strm.GetString());
2090b57cec5SDimitry Andric }
2100b57cec5SDimitry Andric 
operator <<(const char * str)2110b57cec5SDimitry Andric StringList &StringList::operator<<(const char *str) {
2120b57cec5SDimitry Andric   AppendString(str);
2130b57cec5SDimitry Andric   return *this;
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric 
operator <<(const std::string & str)2160b57cec5SDimitry Andric StringList &StringList::operator<<(const std::string &str) {
2170b57cec5SDimitry Andric   AppendString(str);
2180b57cec5SDimitry Andric   return *this;
2190b57cec5SDimitry Andric }
2200b57cec5SDimitry Andric 
operator <<(const StringList & strings)221e8d8bef9SDimitry Andric StringList &StringList::operator<<(const StringList &strings) {
2220b57cec5SDimitry Andric   AppendList(strings);
2230b57cec5SDimitry Andric   return *this;
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric 
operator =(const std::vector<std::string> & rhs)2260b57cec5SDimitry Andric StringList &StringList::operator=(const std::vector<std::string> &rhs) {
2270b57cec5SDimitry Andric   m_strings.assign(rhs.begin(), rhs.end());
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   return *this;
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric 
LogDump(Log * log,const char * name)2320b57cec5SDimitry Andric void StringList::LogDump(Log *log, const char *name) {
2330b57cec5SDimitry Andric   if (!log)
2340b57cec5SDimitry Andric     return;
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   StreamString strm;
2370b57cec5SDimitry Andric   if (name)
2380b57cec5SDimitry Andric     strm.Printf("Begin %s:\n", name);
2390b57cec5SDimitry Andric   for (const auto &s : m_strings) {
2400b57cec5SDimitry Andric     strm.Indent();
2410b57cec5SDimitry Andric     strm.Printf("%s\n", s.c_str());
2420b57cec5SDimitry Andric   }
2430b57cec5SDimitry Andric   if (name)
2440b57cec5SDimitry Andric     strm.Printf("End %s.\n", name);
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   LLDB_LOGV(log, "{0}", strm.GetData());
2470b57cec5SDimitry Andric }
248