1254721Semaste//===-- StringList.cpp ------------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/Core/StringList.h"
11254721Semaste
12254721Semaste#include "lldb/Core/StreamString.h"
13254721Semaste#include "lldb/Host/FileSpec.h"
14254721Semaste
15254721Semaste#include <string>
16254721Semaste
17254721Semasteusing namespace lldb_private;
18254721Semaste
19254721SemasteStringList::StringList () :
20254721Semaste    m_strings ()
21254721Semaste{
22254721Semaste}
23254721Semaste
24254721SemasteStringList::StringList (const char *str) :
25254721Semaste    m_strings ()
26254721Semaste{
27254721Semaste    if (str)
28254721Semaste        m_strings.push_back (str);
29254721Semaste}
30254721Semaste
31254721SemasteStringList::StringList (const char **strv, int strc) :
32254721Semaste    m_strings ()
33254721Semaste{
34254721Semaste    for (int i = 0; i < strc; ++i)
35254721Semaste    {
36254721Semaste        if (strv[i])
37254721Semaste            m_strings.push_back (strv[i]);
38254721Semaste    }
39254721Semaste}
40254721Semaste
41254721SemasteStringList::~StringList ()
42254721Semaste{
43254721Semaste}
44254721Semaste
45254721Semastevoid
46254721SemasteStringList::AppendString (const char *str)
47254721Semaste{
48254721Semaste    if (str)
49254721Semaste        m_strings.push_back (str);
50254721Semaste}
51254721Semaste
52254721Semastevoid
53254721SemasteStringList::AppendString (const std::string &s)
54254721Semaste{
55254721Semaste    m_strings.push_back (s);
56254721Semaste}
57254721Semaste
58254721Semastevoid
59269024SemasteStringList::AppendString (std::string &&s)
60269024Semaste{
61269024Semaste    m_strings.push_back (s);
62269024Semaste}
63269024Semaste
64269024Semastevoid
65254721SemasteStringList::AppendString (const char *str, size_t str_len)
66254721Semaste{
67254721Semaste    if (str)
68254721Semaste        m_strings.push_back (std::string (str, str_len));
69254721Semaste}
70254721Semaste
71254721Semastevoid
72254721SemasteStringList::AppendList (const char **strv, int strc)
73254721Semaste{
74254721Semaste    for (int i = 0; i < strc; ++i)
75254721Semaste    {
76254721Semaste        if (strv[i])
77254721Semaste            m_strings.push_back (strv[i]);
78254721Semaste    }
79254721Semaste}
80254721Semaste
81254721Semastevoid
82254721SemasteStringList::AppendList (StringList strings)
83254721Semaste{
84254721Semaste    size_t len = strings.GetSize();
85254721Semaste
86254721Semaste    for (size_t i = 0; i < len; ++i)
87254721Semaste        m_strings.push_back (strings.GetStringAtIndex(i));
88254721Semaste}
89254721Semaste
90254721Semastebool
91254721SemasteStringList::ReadFileLines (FileSpec &input_file)
92254721Semaste{
93254721Semaste    return input_file.ReadFileLines (m_strings);
94254721Semaste}
95254721Semaste
96254721Semastesize_t
97254721SemasteStringList::GetSize () const
98254721Semaste{
99254721Semaste    return m_strings.size();
100254721Semaste}
101254721Semaste
102269024Semastesize_t
103269024SemasteStringList::GetMaxStringLength () const
104269024Semaste{
105269024Semaste    size_t max_length = 0;
106269024Semaste    for (const auto &s : m_strings)
107269024Semaste    {
108269024Semaste        const size_t len = s.size();
109269024Semaste        if (max_length < len)
110269024Semaste            max_length = len;
111269024Semaste    }
112269024Semaste    return max_length;
113269024Semaste}
114269024Semaste
115269024Semaste
116254721Semasteconst char *
117254721SemasteStringList::GetStringAtIndex (size_t idx) const
118254721Semaste{
119254721Semaste    if (idx < m_strings.size())
120254721Semaste        return m_strings[idx].c_str();
121254721Semaste    return NULL;
122254721Semaste}
123254721Semaste
124254721Semastevoid
125254721SemasteStringList::Join (const char *separator, Stream &strm)
126254721Semaste{
127254721Semaste    size_t size = GetSize();
128254721Semaste
129254721Semaste    if (size == 0)
130254721Semaste        return;
131254721Semaste
132254721Semaste    for (uint32_t i = 0; i < size; ++i)
133254721Semaste    {
134254721Semaste        if (i > 0)
135254721Semaste            strm.PutCString(separator);
136254721Semaste        strm.PutCString(GetStringAtIndex(i));
137254721Semaste    }
138254721Semaste}
139254721Semaste
140254721Semastevoid
141254721SemasteStringList::Clear ()
142254721Semaste{
143254721Semaste    m_strings.clear();
144254721Semaste}
145254721Semaste
146254721Semastevoid
147254721SemasteStringList::LongestCommonPrefix (std::string &common_prefix)
148254721Semaste{
149269024Semaste    const size_t num_strings = m_strings.size();
150254721Semaste
151269024Semaste    if (num_strings == 0)
152269024Semaste    {
153254721Semaste        common_prefix.clear();
154269024Semaste    }
155254721Semaste    else
156254721Semaste    {
157269024Semaste        common_prefix = m_strings.front();
158254721Semaste
159269024Semaste        for (size_t idx = 1; idx < num_strings; ++idx)
160269024Semaste        {
161269024Semaste            std::string &curr_string = m_strings[idx];
162269024Semaste            size_t new_size = curr_string.size();
163254721Semaste
164269024Semaste            // First trim common_prefix if it is longer than the current element:
165269024Semaste            if (common_prefix.size() > new_size)
166269024Semaste                common_prefix.erase (new_size);
167254721Semaste
168269024Semaste            // Then trim it at the first disparity:
169269024Semaste            for (size_t i = 0; i < common_prefix.size(); i++)
170254721Semaste            {
171269024Semaste                if (curr_string[i] != common_prefix[i])
172269024Semaste                {
173269024Semaste                    common_prefix.erase(i);
174269024Semaste                    break;
175269024Semaste                }
176269024Semaste            }
177269024Semaste
178269024Semaste            // If we've emptied the common prefix, we're done.
179269024Semaste            if (common_prefix.empty())
180254721Semaste                break;
181254721Semaste        }
182254721Semaste    }
183254721Semaste}
184254721Semaste
185254721Semastevoid
186254721SemasteStringList::InsertStringAtIndex (size_t idx, const char *str)
187254721Semaste{
188254721Semaste    if (str)
189254721Semaste    {
190254721Semaste        if (idx < m_strings.size())
191254721Semaste            m_strings.insert (m_strings.begin() + idx, str);
192254721Semaste        else
193254721Semaste            m_strings.push_back (str);
194254721Semaste    }
195254721Semaste}
196254721Semaste
197254721Semastevoid
198269024SemasteStringList::InsertStringAtIndex (size_t idx, const std::string &str)
199269024Semaste{
200269024Semaste    if (idx < m_strings.size())
201269024Semaste        m_strings.insert (m_strings.begin() + idx, str);
202269024Semaste    else
203269024Semaste        m_strings.push_back (str);
204269024Semaste}
205269024Semaste
206269024Semastevoid
207269024SemasteStringList::InsertStringAtIndex (size_t idx, std::string &&str)
208269024Semaste{
209269024Semaste    if (idx < m_strings.size())
210269024Semaste        m_strings.insert (m_strings.begin() + idx, str);
211269024Semaste    else
212269024Semaste        m_strings.push_back (str);
213269024Semaste}
214269024Semaste
215269024Semastevoid
216254721SemasteStringList::DeleteStringAtIndex (size_t idx)
217254721Semaste{
218254721Semaste    if (idx < m_strings.size())
219254721Semaste        m_strings.erase (m_strings.begin() + idx);
220254721Semaste}
221254721Semaste
222254721Semastesize_t
223269024SemasteStringList::SplitIntoLines (const std::string &lines)
224269024Semaste{
225269024Semaste    return SplitIntoLines (lines.c_str(), lines.size());
226269024Semaste}
227269024Semaste
228269024Semastesize_t
229254721SemasteStringList::SplitIntoLines (const char *lines, size_t len)
230254721Semaste{
231254721Semaste    const size_t orig_size = m_strings.size();
232254721Semaste
233254721Semaste    if (len == 0)
234254721Semaste        return 0;
235254721Semaste
236254721Semaste    const char *k_newline_chars = "\r\n";
237254721Semaste    const char *p = lines;
238254721Semaste    const char *end = lines + len;
239254721Semaste    while (p < end)
240254721Semaste    {
241254721Semaste        size_t count = strcspn (p, k_newline_chars);
242254721Semaste        if (count == 0)
243254721Semaste        {
244254721Semaste            if (p[count] == '\r' || p[count] == '\n')
245254721Semaste                m_strings.push_back(std::string());
246254721Semaste            else
247254721Semaste                break;
248254721Semaste        }
249254721Semaste        else
250254721Semaste        {
251254721Semaste            if (p + count > end)
252254721Semaste                count = end - p;
253254721Semaste            m_strings.push_back(std::string(p, count));
254254721Semaste        }
255254721Semaste        if (p[count] == '\r' && p[count+1] == '\n')
256254721Semaste            count++;    // Skip an extra newline char for the DOS newline
257254721Semaste        count++;    // Skip the newline character
258254721Semaste        p += count;
259254721Semaste    }
260254721Semaste    return m_strings.size() - orig_size;
261254721Semaste}
262254721Semaste
263254721Semastevoid
264254721SemasteStringList::RemoveBlankLines ()
265254721Semaste{
266254721Semaste    if (GetSize() == 0)
267254721Semaste        return;
268254721Semaste
269254721Semaste    size_t idx = 0;
270254721Semaste    while (idx < m_strings.size())
271254721Semaste    {
272254721Semaste        if (m_strings[idx].empty())
273254721Semaste            DeleteStringAtIndex(idx);
274254721Semaste        else
275254721Semaste            idx++;
276254721Semaste    }
277254721Semaste}
278254721Semaste
279254721Semastestd::string
280269024SemasteStringList::CopyList(const char* item_preamble, const char* items_sep) const
281254721Semaste{
282254721Semaste    StreamString strm;
283254721Semaste    for (size_t i = 0; i < GetSize(); i++)
284254721Semaste    {
285254721Semaste        if (i && items_sep && items_sep[0])
286254721Semaste            strm << items_sep;
287254721Semaste        if (item_preamble)
288254721Semaste            strm << item_preamble;
289254721Semaste        strm << GetStringAtIndex(i);
290254721Semaste    }
291254721Semaste    return std::string(strm.GetData());
292254721Semaste}
293254721Semaste
294254721SemasteStringList&
295254721SemasteStringList::operator << (const char* str)
296254721Semaste{
297254721Semaste    AppendString(str);
298254721Semaste    return *this;
299254721Semaste}
300254721Semaste
301254721SemasteStringList&
302254721SemasteStringList::operator << (StringList strings)
303254721Semaste{
304254721Semaste    AppendList(strings);
305254721Semaste    return *this;
306254721Semaste}
307254721Semaste
308254721Semastesize_t
309254721SemasteStringList::AutoComplete (const char *s, StringList &matches, size_t &exact_idx) const
310254721Semaste{
311254721Semaste    matches.Clear();
312254721Semaste    exact_idx = SIZE_MAX;
313254721Semaste    if (s && s[0])
314254721Semaste    {
315254721Semaste        const size_t s_len = strlen (s);
316254721Semaste        const size_t num_strings = m_strings.size();
317254721Semaste
318254721Semaste        for (size_t i=0; i<num_strings; ++i)
319254721Semaste        {
320254721Semaste            if (m_strings[i].find(s) == 0)
321254721Semaste            {
322254721Semaste                if (exact_idx == SIZE_MAX && m_strings[i].size() == s_len)
323254721Semaste                    exact_idx = matches.GetSize();
324254721Semaste                matches.AppendString (m_strings[i]);
325254721Semaste            }
326254721Semaste        }
327254721Semaste    }
328254721Semaste    else
329254721Semaste    {
330254721Semaste        // No string, so it matches everything
331254721Semaste        matches = *this;
332254721Semaste    }
333254721Semaste    return matches.GetSize();
334254721Semaste}
335254721Semaste
336