1//===-- StringList.cpp ------------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "lldb/Core/StringList.h" 11 12#include "lldb/Core/StreamString.h" 13#include "lldb/Host/FileSpec.h" 14 15#include <string> 16 17using namespace lldb_private; 18 19StringList::StringList () : 20 m_strings () 21{ 22} 23 24StringList::StringList (const char *str) : 25 m_strings () 26{ 27 if (str) 28 m_strings.push_back (str); 29} 30 31StringList::StringList (const char **strv, int strc) : 32 m_strings () 33{ 34 for (int i = 0; i < strc; ++i) 35 { 36 if (strv[i]) 37 m_strings.push_back (strv[i]); 38 } 39} 40 41StringList::~StringList () 42{ 43} 44 45void 46StringList::AppendString (const char *str) 47{ 48 if (str) 49 m_strings.push_back (str); 50} 51 52void 53StringList::AppendString (const std::string &s) 54{ 55 m_strings.push_back (s); 56} 57 58void 59StringList::AppendString (std::string &&s) 60{ 61 m_strings.push_back (s); 62} 63 64void 65StringList::AppendString (const char *str, size_t str_len) 66{ 67 if (str) 68 m_strings.push_back (std::string (str, str_len)); 69} 70 71void 72StringList::AppendList (const char **strv, int strc) 73{ 74 for (int i = 0; i < strc; ++i) 75 { 76 if (strv[i]) 77 m_strings.push_back (strv[i]); 78 } 79} 80 81void 82StringList::AppendList (StringList strings) 83{ 84 size_t len = strings.GetSize(); 85 86 for (size_t i = 0; i < len; ++i) 87 m_strings.push_back (strings.GetStringAtIndex(i)); 88} 89 90bool 91StringList::ReadFileLines (FileSpec &input_file) 92{ 93 return input_file.ReadFileLines (m_strings); 94} 95 96size_t 97StringList::GetSize () const 98{ 99 return m_strings.size(); 100} 101 102size_t 103StringList::GetMaxStringLength () const 104{ 105 size_t max_length = 0; 106 for (const auto &s : m_strings) 107 { 108 const size_t len = s.size(); 109 if (max_length < len) 110 max_length = len; 111 } 112 return max_length; 113} 114 115 116const char * 117StringList::GetStringAtIndex (size_t idx) const 118{ 119 if (idx < m_strings.size()) 120 return m_strings[idx].c_str(); 121 return NULL; 122} 123 124void 125StringList::Join (const char *separator, Stream &strm) 126{ 127 size_t size = GetSize(); 128 129 if (size == 0) 130 return; 131 132 for (uint32_t i = 0; i < size; ++i) 133 { 134 if (i > 0) 135 strm.PutCString(separator); 136 strm.PutCString(GetStringAtIndex(i)); 137 } 138} 139 140void 141StringList::Clear () 142{ 143 m_strings.clear(); 144} 145 146void 147StringList::LongestCommonPrefix (std::string &common_prefix) 148{ 149 const size_t num_strings = m_strings.size(); 150 151 if (num_strings == 0) 152 { 153 common_prefix.clear(); 154 } 155 else 156 { 157 common_prefix = m_strings.front(); 158 159 for (size_t idx = 1; idx < num_strings; ++idx) 160 { 161 std::string &curr_string = m_strings[idx]; 162 size_t new_size = curr_string.size(); 163 164 // First trim common_prefix if it is longer than the current element: 165 if (common_prefix.size() > new_size) 166 common_prefix.erase (new_size); 167 168 // Then trim it at the first disparity: 169 for (size_t i = 0; i < common_prefix.size(); i++) 170 { 171 if (curr_string[i] != common_prefix[i]) 172 { 173 common_prefix.erase(i); 174 break; 175 } 176 } 177 178 // If we've emptied the common prefix, we're done. 179 if (common_prefix.empty()) 180 break; 181 } 182 } 183} 184 185void 186StringList::InsertStringAtIndex (size_t idx, const char *str) 187{ 188 if (str) 189 { 190 if (idx < m_strings.size()) 191 m_strings.insert (m_strings.begin() + idx, str); 192 else 193 m_strings.push_back (str); 194 } 195} 196 197void 198StringList::InsertStringAtIndex (size_t idx, const std::string &str) 199{ 200 if (idx < m_strings.size()) 201 m_strings.insert (m_strings.begin() + idx, str); 202 else 203 m_strings.push_back (str); 204} 205 206void 207StringList::InsertStringAtIndex (size_t idx, std::string &&str) 208{ 209 if (idx < m_strings.size()) 210 m_strings.insert (m_strings.begin() + idx, str); 211 else 212 m_strings.push_back (str); 213} 214 215void 216StringList::DeleteStringAtIndex (size_t idx) 217{ 218 if (idx < m_strings.size()) 219 m_strings.erase (m_strings.begin() + idx); 220} 221 222size_t 223StringList::SplitIntoLines (const std::string &lines) 224{ 225 return SplitIntoLines (lines.c_str(), lines.size()); 226} 227 228size_t 229StringList::SplitIntoLines (const char *lines, size_t len) 230{ 231 const size_t orig_size = m_strings.size(); 232 233 if (len == 0) 234 return 0; 235 236 const char *k_newline_chars = "\r\n"; 237 const char *p = lines; 238 const char *end = lines + len; 239 while (p < end) 240 { 241 size_t count = strcspn (p, k_newline_chars); 242 if (count == 0) 243 { 244 if (p[count] == '\r' || p[count] == '\n') 245 m_strings.push_back(std::string()); 246 else 247 break; 248 } 249 else 250 { 251 if (p + count > end) 252 count = end - p; 253 m_strings.push_back(std::string(p, count)); 254 } 255 if (p[count] == '\r' && p[count+1] == '\n') 256 count++; // Skip an extra newline char for the DOS newline 257 count++; // Skip the newline character 258 p += count; 259 } 260 return m_strings.size() - orig_size; 261} 262 263void 264StringList::RemoveBlankLines () 265{ 266 if (GetSize() == 0) 267 return; 268 269 size_t idx = 0; 270 while (idx < m_strings.size()) 271 { 272 if (m_strings[idx].empty()) 273 DeleteStringAtIndex(idx); 274 else 275 idx++; 276 } 277} 278 279std::string 280StringList::CopyList(const char* item_preamble, const char* items_sep) const 281{ 282 StreamString strm; 283 for (size_t i = 0; i < GetSize(); i++) 284 { 285 if (i && items_sep && items_sep[0]) 286 strm << items_sep; 287 if (item_preamble) 288 strm << item_preamble; 289 strm << GetStringAtIndex(i); 290 } 291 return std::string(strm.GetData()); 292} 293 294StringList& 295StringList::operator << (const char* str) 296{ 297 AppendString(str); 298 return *this; 299} 300 301StringList& 302StringList::operator << (StringList strings) 303{ 304 AppendList(strings); 305 return *this; 306} 307 308size_t 309StringList::AutoComplete (const char *s, StringList &matches, size_t &exact_idx) const 310{ 311 matches.Clear(); 312 exact_idx = SIZE_MAX; 313 if (s && s[0]) 314 { 315 const size_t s_len = strlen (s); 316 const size_t num_strings = m_strings.size(); 317 318 for (size_t i=0; i<num_strings; ++i) 319 { 320 if (m_strings[i].find(s) == 0) 321 { 322 if (exact_idx == SIZE_MAX && m_strings[i].size() == s_len) 323 exact_idx = matches.GetSize(); 324 matches.AppendString (m_strings[i]); 325 } 326 } 327 } 328 else 329 { 330 // No string, so it matches everything 331 matches = *this; 332 } 333 return matches.GetSize(); 334} 335 336