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>
17*5f7ddb14SDimitry Andric #include <cstdint>
18*5f7ddb14SDimitry 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
36*5f7ddb14SDimitry 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)450b57cec5SDimitry Andric void StringList::AppendString(std::string &&s) { m_strings.push_back(s); }
460b57cec5SDimitry Andric
AppendString(const char * str,size_t str_len)470b57cec5SDimitry Andric void StringList::AppendString(const char *str, size_t str_len) {
480b57cec5SDimitry Andric if (str)
490b57cec5SDimitry Andric m_strings.push_back(std::string(str, str_len));
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric
AppendString(llvm::StringRef str)520b57cec5SDimitry Andric void StringList::AppendString(llvm::StringRef str) {
530b57cec5SDimitry Andric m_strings.push_back(str.str());
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric
AppendList(const char ** strv,int strc)560b57cec5SDimitry Andric void StringList::AppendList(const char **strv, int strc) {
570b57cec5SDimitry Andric for (int i = 0; i < strc; ++i) {
580b57cec5SDimitry Andric if (strv[i])
590b57cec5SDimitry Andric m_strings.push_back(strv[i]);
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric
AppendList(StringList strings)630b57cec5SDimitry Andric void StringList::AppendList(StringList strings) {
649dba64beSDimitry Andric m_strings.reserve(m_strings.size() + strings.GetSize());
659dba64beSDimitry Andric m_strings.insert(m_strings.end(), strings.begin(), strings.end());
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric
GetSize() const680b57cec5SDimitry Andric size_t StringList::GetSize() const { return m_strings.size(); }
690b57cec5SDimitry Andric
GetMaxStringLength() const700b57cec5SDimitry Andric size_t StringList::GetMaxStringLength() const {
710b57cec5SDimitry Andric size_t max_length = 0;
720b57cec5SDimitry Andric for (const auto &s : m_strings) {
730b57cec5SDimitry Andric const size_t len = s.size();
740b57cec5SDimitry Andric if (max_length < len)
750b57cec5SDimitry Andric max_length = len;
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric return max_length;
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric
GetStringAtIndex(size_t idx) const800b57cec5SDimitry Andric const char *StringList::GetStringAtIndex(size_t idx) const {
810b57cec5SDimitry Andric if (idx < m_strings.size())
820b57cec5SDimitry Andric return m_strings[idx].c_str();
830b57cec5SDimitry Andric return nullptr;
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric
Join(const char * separator,Stream & strm)860b57cec5SDimitry Andric void StringList::Join(const char *separator, Stream &strm) {
870b57cec5SDimitry Andric size_t size = GetSize();
880b57cec5SDimitry Andric
890b57cec5SDimitry Andric if (size == 0)
900b57cec5SDimitry Andric return;
910b57cec5SDimitry Andric
920b57cec5SDimitry Andric for (uint32_t i = 0; i < size; ++i) {
930b57cec5SDimitry Andric if (i > 0)
940b57cec5SDimitry Andric strm.PutCString(separator);
950b57cec5SDimitry Andric strm.PutCString(GetStringAtIndex(i));
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric }
980b57cec5SDimitry Andric
Clear()990b57cec5SDimitry Andric void StringList::Clear() { m_strings.clear(); }
1000b57cec5SDimitry Andric
LongestCommonPrefix()1019dba64beSDimitry Andric std::string StringList::LongestCommonPrefix() {
1020b57cec5SDimitry Andric if (m_strings.empty())
1039dba64beSDimitry Andric return {};
1040b57cec5SDimitry Andric
1050b57cec5SDimitry Andric auto args = llvm::makeArrayRef(m_strings);
1060b57cec5SDimitry Andric llvm::StringRef prefix = args.front();
1070b57cec5SDimitry Andric for (auto arg : args.drop_front()) {
1080b57cec5SDimitry Andric size_t count = 0;
1090b57cec5SDimitry Andric for (count = 0; count < std::min(prefix.size(), arg.size()); ++count) {
1100b57cec5SDimitry Andric if (prefix[count] != arg[count])
1110b57cec5SDimitry Andric break;
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric prefix = prefix.take_front(count);
1140b57cec5SDimitry Andric }
1159dba64beSDimitry Andric return prefix.str();
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric
InsertStringAtIndex(size_t idx,const char * str)1180b57cec5SDimitry Andric void StringList::InsertStringAtIndex(size_t idx, const char *str) {
1190b57cec5SDimitry Andric if (str) {
1200b57cec5SDimitry Andric if (idx < m_strings.size())
1210b57cec5SDimitry Andric m_strings.insert(m_strings.begin() + idx, str);
1220b57cec5SDimitry Andric else
1230b57cec5SDimitry Andric m_strings.push_back(str);
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric
InsertStringAtIndex(size_t idx,const std::string & str)1270b57cec5SDimitry Andric void StringList::InsertStringAtIndex(size_t idx, const std::string &str) {
1280b57cec5SDimitry Andric if (idx < m_strings.size())
1290b57cec5SDimitry Andric m_strings.insert(m_strings.begin() + idx, str);
1300b57cec5SDimitry Andric else
1310b57cec5SDimitry Andric m_strings.push_back(str);
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric
InsertStringAtIndex(size_t idx,std::string && str)1340b57cec5SDimitry Andric void StringList::InsertStringAtIndex(size_t idx, std::string &&str) {
1350b57cec5SDimitry Andric if (idx < m_strings.size())
1360b57cec5SDimitry Andric m_strings.insert(m_strings.begin() + idx, str);
1370b57cec5SDimitry Andric else
1380b57cec5SDimitry Andric m_strings.push_back(str);
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric
DeleteStringAtIndex(size_t idx)1410b57cec5SDimitry Andric void StringList::DeleteStringAtIndex(size_t idx) {
1420b57cec5SDimitry Andric if (idx < m_strings.size())
1430b57cec5SDimitry Andric m_strings.erase(m_strings.begin() + idx);
1440b57cec5SDimitry Andric }
1450b57cec5SDimitry Andric
SplitIntoLines(const std::string & lines)1460b57cec5SDimitry Andric size_t StringList::SplitIntoLines(const std::string &lines) {
1470b57cec5SDimitry Andric return SplitIntoLines(lines.c_str(), lines.size());
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric
SplitIntoLines(const char * lines,size_t len)1500b57cec5SDimitry Andric size_t StringList::SplitIntoLines(const char *lines, size_t len) {
1510b57cec5SDimitry Andric const size_t orig_size = m_strings.size();
1520b57cec5SDimitry Andric
1530b57cec5SDimitry Andric if (len == 0)
1540b57cec5SDimitry Andric return 0;
1550b57cec5SDimitry Andric
1560b57cec5SDimitry Andric const char *k_newline_chars = "\r\n";
1570b57cec5SDimitry Andric const char *p = lines;
1580b57cec5SDimitry Andric const char *end = lines + len;
1590b57cec5SDimitry Andric while (p < end) {
1600b57cec5SDimitry Andric size_t count = strcspn(p, k_newline_chars);
1610b57cec5SDimitry Andric if (count == 0) {
1620b57cec5SDimitry Andric if (p[count] == '\r' || p[count] == '\n')
1630b57cec5SDimitry Andric m_strings.push_back(std::string());
1640b57cec5SDimitry Andric else
1650b57cec5SDimitry Andric break;
1660b57cec5SDimitry Andric } else {
1670b57cec5SDimitry Andric if (p + count > end)
1680b57cec5SDimitry Andric count = end - p;
1690b57cec5SDimitry Andric m_strings.push_back(std::string(p, count));
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric if (p[count] == '\r' && p[count + 1] == '\n')
1720b57cec5SDimitry Andric count++; // Skip an extra newline char for the DOS newline
1730b57cec5SDimitry Andric count++; // Skip the newline character
1740b57cec5SDimitry Andric p += count;
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric return m_strings.size() - orig_size;
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric
RemoveBlankLines()1790b57cec5SDimitry Andric void StringList::RemoveBlankLines() {
1800b57cec5SDimitry Andric if (GetSize() == 0)
1810b57cec5SDimitry Andric return;
1820b57cec5SDimitry Andric
1830b57cec5SDimitry Andric size_t idx = 0;
1840b57cec5SDimitry Andric while (idx < m_strings.size()) {
1850b57cec5SDimitry Andric if (m_strings[idx].empty())
1860b57cec5SDimitry Andric DeleteStringAtIndex(idx);
1870b57cec5SDimitry Andric else
1880b57cec5SDimitry Andric idx++;
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric }
1910b57cec5SDimitry Andric
CopyList(const char * item_preamble,const char * items_sep) const1920b57cec5SDimitry Andric std::string StringList::CopyList(const char *item_preamble,
1930b57cec5SDimitry Andric const char *items_sep) const {
1940b57cec5SDimitry Andric StreamString strm;
1950b57cec5SDimitry Andric for (size_t i = 0; i < GetSize(); i++) {
1960b57cec5SDimitry Andric if (i && items_sep && items_sep[0])
1970b57cec5SDimitry Andric strm << items_sep;
1980b57cec5SDimitry Andric if (item_preamble)
1990b57cec5SDimitry Andric strm << item_preamble;
2000b57cec5SDimitry Andric strm << GetStringAtIndex(i);
2010b57cec5SDimitry Andric }
2025ffd83dbSDimitry Andric return std::string(strm.GetString());
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric
operator <<(const char * str)2050b57cec5SDimitry Andric StringList &StringList::operator<<(const char *str) {
2060b57cec5SDimitry Andric AppendString(str);
2070b57cec5SDimitry Andric return *this;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric
operator <<(const std::string & str)2100b57cec5SDimitry Andric StringList &StringList::operator<<(const std::string &str) {
2110b57cec5SDimitry Andric AppendString(str);
2120b57cec5SDimitry Andric return *this;
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric
operator <<(const StringList & strings)215af732203SDimitry Andric StringList &StringList::operator<<(const StringList &strings) {
2160b57cec5SDimitry Andric AppendList(strings);
2170b57cec5SDimitry Andric return *this;
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric
operator =(const std::vector<std::string> & rhs)2200b57cec5SDimitry Andric StringList &StringList::operator=(const std::vector<std::string> &rhs) {
2210b57cec5SDimitry Andric m_strings.assign(rhs.begin(), rhs.end());
2220b57cec5SDimitry Andric
2230b57cec5SDimitry Andric return *this;
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric
LogDump(Log * log,const char * name)2260b57cec5SDimitry Andric void StringList::LogDump(Log *log, const char *name) {
2270b57cec5SDimitry Andric if (!log)
2280b57cec5SDimitry Andric return;
2290b57cec5SDimitry Andric
2300b57cec5SDimitry Andric StreamString strm;
2310b57cec5SDimitry Andric if (name)
2320b57cec5SDimitry Andric strm.Printf("Begin %s:\n", name);
2330b57cec5SDimitry Andric for (const auto &s : m_strings) {
2340b57cec5SDimitry Andric strm.Indent();
2350b57cec5SDimitry Andric strm.Printf("%s\n", s.c_str());
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric if (name)
2380b57cec5SDimitry Andric strm.Printf("End %s.\n", name);
2390b57cec5SDimitry Andric
2400b57cec5SDimitry Andric LLDB_LOGV(log, "{0}", strm.GetData());
2410b57cec5SDimitry Andric }
242