Files
llvm/lldb/source/Core/StringList.cpp
Greg Clayton 44d937820b Merging the iohandler branch back into main.
The many many benefits include:
1 - Input/Output/Error streams are now handled as real streams not a push style input
2 - auto completion in python embedded interpreter
3 - multi-line input for "script" and "expression" commands now allow you to edit previous/next lines using up and down arrow keys and this makes multi-line input actually a viable thing to use
4 - it is now possible to use curses to drive LLDB (please try the "gui" command)

We will need to deal with and fix any buildbot failures and tests and arise now that input/output and error are correctly hooked up in all cases.

llvm-svn: 200263
2014-01-27 23:43:24 +00:00

336 lines
6.9 KiB
C++

//===-- StringList.cpp ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Core/StringList.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/FileSpec.h"
#include <string>
using namespace lldb_private;
StringList::StringList () :
m_strings ()
{
}
StringList::StringList (const char *str) :
m_strings ()
{
if (str)
m_strings.push_back (str);
}
StringList::StringList (const char **strv, int strc) :
m_strings ()
{
for (int i = 0; i < strc; ++i)
{
if (strv[i])
m_strings.push_back (strv[i]);
}
}
StringList::~StringList ()
{
}
void
StringList::AppendString (const char *str)
{
if (str)
m_strings.push_back (str);
}
void
StringList::AppendString (const std::string &s)
{
m_strings.push_back (s);
}
void
StringList::AppendString (std::string &&s)
{
m_strings.push_back (s);
}
void
StringList::AppendString (const char *str, size_t str_len)
{
if (str)
m_strings.push_back (std::string (str, str_len));
}
void
StringList::AppendList (const char **strv, int strc)
{
for (int i = 0; i < strc; ++i)
{
if (strv[i])
m_strings.push_back (strv[i]);
}
}
void
StringList::AppendList (StringList strings)
{
size_t len = strings.GetSize();
for (size_t i = 0; i < len; ++i)
m_strings.push_back (strings.GetStringAtIndex(i));
}
bool
StringList::ReadFileLines (FileSpec &input_file)
{
return input_file.ReadFileLines (m_strings);
}
size_t
StringList::GetSize () const
{
return m_strings.size();
}
size_t
StringList::GetMaxStringLength () const
{
size_t max_length = 0;
for (const auto &s : m_strings)
{
const size_t len = s.size();
if (max_length < len)
max_length = len;
}
return max_length;
}
const char *
StringList::GetStringAtIndex (size_t idx) const
{
if (idx < m_strings.size())
return m_strings[idx].c_str();
return NULL;
}
void
StringList::Join (const char *separator, Stream &strm)
{
size_t size = GetSize();
if (size == 0)
return;
for (uint32_t i = 0; i < size; ++i)
{
if (i > 0)
strm.PutCString(separator);
strm.PutCString(GetStringAtIndex(i));
}
}
void
StringList::Clear ()
{
m_strings.clear();
}
void
StringList::LongestCommonPrefix (std::string &common_prefix)
{
const size_t num_strings = m_strings.size();
if (num_strings == 0)
{
common_prefix.clear();
}
else
{
common_prefix = m_strings.front();
for (size_t idx = 1; idx < num_strings; ++idx)
{
std::string &curr_string = m_strings[idx];
size_t new_size = curr_string.size();
// First trim common_prefix if it is longer than the current element:
if (common_prefix.size() > new_size)
common_prefix.erase (new_size);
// Then trim it at the first disparity:
for (size_t i = 0; i < common_prefix.size(); i++)
{
if (curr_string[i] != common_prefix[i])
{
common_prefix.erase(i);
break;
}
}
// If we've emptied the common prefix, we're done.
if (common_prefix.empty())
break;
}
}
}
void
StringList::InsertStringAtIndex (size_t idx, const char *str)
{
if (str)
{
if (idx < m_strings.size())
m_strings.insert (m_strings.begin() + idx, str);
else
m_strings.push_back (str);
}
}
void
StringList::InsertStringAtIndex (size_t idx, const std::string &str)
{
if (idx < m_strings.size())
m_strings.insert (m_strings.begin() + idx, str);
else
m_strings.push_back (str);
}
void
StringList::InsertStringAtIndex (size_t idx, std::string &&str)
{
if (idx < m_strings.size())
m_strings.insert (m_strings.begin() + idx, str);
else
m_strings.push_back (str);
}
void
StringList::DeleteStringAtIndex (size_t idx)
{
if (idx < m_strings.size())
m_strings.erase (m_strings.begin() + idx);
}
size_t
StringList::SplitIntoLines (const std::string &lines)
{
return SplitIntoLines (lines.c_str(), lines.size());
}
size_t
StringList::SplitIntoLines (const char *lines, size_t len)
{
const size_t orig_size = m_strings.size();
if (len == 0)
return 0;
const char *k_newline_chars = "\r\n";
const char *p = lines;
const char *end = lines + len;
while (p < end)
{
size_t count = strcspn (p, k_newline_chars);
if (count == 0)
{
if (p[count] == '\r' || p[count] == '\n')
m_strings.push_back(std::string());
else
break;
}
else
{
if (p + count > end)
count = end - p;
m_strings.push_back(std::string(p, count));
}
if (p[count] == '\r' && p[count+1] == '\n')
count++; // Skip an extra newline char for the DOS newline
count++; // Skip the newline character
p += count;
}
return m_strings.size() - orig_size;
}
void
StringList::RemoveBlankLines ()
{
if (GetSize() == 0)
return;
size_t idx = 0;
while (idx < m_strings.size())
{
if (m_strings[idx].empty())
DeleteStringAtIndex(idx);
else
idx++;
}
}
std::string
StringList::CopyList(const char* item_preamble, const char* items_sep) const
{
StreamString strm;
for (size_t i = 0; i < GetSize(); i++)
{
if (i && items_sep && items_sep[0])
strm << items_sep;
if (item_preamble)
strm << item_preamble;
strm << GetStringAtIndex(i);
}
return std::string(strm.GetData());
}
StringList&
StringList::operator << (const char* str)
{
AppendString(str);
return *this;
}
StringList&
StringList::operator << (StringList strings)
{
AppendList(strings);
return *this;
}
size_t
StringList::AutoComplete (const char *s, StringList &matches, size_t &exact_idx) const
{
matches.Clear();
exact_idx = SIZE_MAX;
if (s && s[0])
{
const size_t s_len = strlen (s);
const size_t num_strings = m_strings.size();
for (size_t i=0; i<num_strings; ++i)
{
if (m_strings[i].find(s) == 0)
{
if (exact_idx == SIZE_MAX && m_strings[i].size() == s_len)
exact_idx = matches.GetSize();
matches.AppendString (m_strings[i]);
}
}
}
else
{
// No string, so it matches everything
matches = *this;
}
return matches.GetSize();
}