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