void test_strview_basics(const string_view& sv, const char *p, size_t n) { ASSERT_EQ(p, sv.data()); ASSERT_EQ(n, sv.size()); ASSERT_EQ(n, sv.length()); ASSERT_EQ((n == 0), sv.empty()); ASSERT_EQ(p, sv.cbegin()); ASSERT_EQ(p, sv.begin()); ASSERT_EQ(p + n, sv.cend()); ASSERT_EQ(p + n, sv.end()); using reviter_t = std::reverse_iterator<string_view::const_iterator>; ASSERT_EQ(reviter_t(sv.end()), sv.rbegin()); ASSERT_EQ(reviter_t(sv.begin()), sv.rend()); ASSERT_EQ(reviter_t(sv.cend()), sv.crbegin()); ASSERT_EQ(reviter_t(sv.cbegin()), sv.crend()); for (size_t i = 0; i < n; ++i) { ASSERT_EQ(p[i], sv[i]); ASSERT_EQ(p[i], sv.at(i)); } ASSERT_THROW(sv.at(n), std::out_of_range); ASSERT_THROW(sv.at(string_view::npos), std::out_of_range); if (n > 0) { ASSERT_EQ(p, &(sv.front())); ASSERT_EQ(p + (n-1), &(sv.back())); ASSERT_EQ(p[0], sv.front()); ASSERT_EQ(p[n-1], sv.back()); } }
size_t find_icase(string_view const Str, wchar_t const What, size_t Pos) { if (Pos >= Str.size()) return Str.npos; const auto It = std::find_if(Str.cbegin() + Pos, Str.cend(), [&](wchar_t const Char) { return equal_icase_t{}(What, Char); }); return It == Str.cend() ? Str.npos : It - Str.cbegin(); }
size_t find_icase(string_view const Str, string_view const What, size_t Pos) { if (Pos >= Str.size()) return Str.npos; const auto It = std::search(Str.cbegin() + Pos, Str.cend(), ALL_CONST_RANGE(What), equal_icase_t{}); return It == Str.cend()? Str.npos : It - Str.cbegin(); }
int main() { typedef std::experimental::string_view string_view; typedef std::experimental::u16string_view u16string_view; typedef std::experimental::u32string_view u32string_view; typedef std::experimental::wstring_view wstring_view; test(string_view ()); test(u16string_view()); test(u32string_view()); test(wstring_view ()); test(string_view ( "123")); test(wstring_view (L"123")); #if __cplusplus >= 201103L test(u16string_view{u"123"}); test(u32string_view{U"123"}); #endif #if _LIBCPP_STD_VER > 11 { constexpr string_view sv { "123", 3 }; constexpr u16string_view u16sv {u"123", 3 }; constexpr u32string_view u32sv {U"123", 3 }; constexpr wstring_view wsv {L"123", 3 }; static_assert ( *sv.begin() == sv[0], "" ); static_assert ( *u16sv.begin() == u16sv[0], "" ); static_assert ( *u32sv.begin() == u32sv[0], "" ); static_assert ( *wsv.begin() == wsv[0], "" ); static_assert ( *sv.cbegin() == sv[0], "" ); static_assert ( *u16sv.cbegin() == u16sv[0], "" ); static_assert ( *u32sv.cbegin() == u32sv[0], "" ); static_assert ( *wsv.cbegin() == wsv[0], "" ); } #endif }
std::list<CommandLine::segment> CommandLine::GetPrompt() { FN_RETURN_TYPE(CommandLine::GetPrompt) Result; int NewPromptSize = DEFAULT_CMDLINE_WIDTH; const auto& PrefixColor = colors::PaletteColorToFarColor(COL_COMMANDLINEPREFIX); if (Global->Opt->CmdLine.UsePromptFormat) { const string_view Format = Global->Opt->CmdLine.strPromptFormat.Get(); auto Tail = Format.cbegin(); auto Color = PrefixColor; FOR_CONST_RANGE(Format, Iterator) { bool Stop; auto NewColor = PrefixColor; const auto NextIterator = colors::ExtractColorInNewFormat(Iterator, Format.cend(), NewColor, Stop); if (NextIterator == Iterator) { if (Stop) break; continue; } if (Iterator != Format.cbegin()) { Result.emplace_back(segment{ string(Tail, Iterator), Color }); } Iterator = NextIterator; Tail = Iterator; Color = NewColor; } Result.emplace_back(segment{ string(Tail, Format.cend()), Color }); for (auto Iterator = Result.begin(); Iterator != Result.end(); ++Iterator) { const auto strExpandedDestStr = os::env::expand(Iterator->Text); Iterator->Text.clear(); static const std::pair<wchar_t, wchar_t> ChrFmt[] = { {L'A', L'&'}, // $A - & (Ampersand) {L'B', L'|'}, // $B - | (pipe) {L'C', L'('}, // $C - ( (Left parenthesis) {L'F', L')'}, // $F - ) (Right parenthesis) {L'G', L'>'}, // $G - > (greater-than sign) {L'L', L'<'}, // $L - < (less-than sign) {L'Q', L'='}, // $Q - = (equal sign) {L'S', L' '}, // $S - (space) {L'$', L'$'}, // $$ - $ (dollar sign) }; FOR_CONST_RANGE(strExpandedDestStr, it) { auto& strDestStr = Iterator->Text; if (*it == L'$' && it + 1 != strExpandedDestStr.cend()) { const auto Chr = upper(*++it); const auto ItemIterator = std::find_if(CONST_RANGE(ChrFmt, Item) { return Item.first == Chr; }); if (ItemIterator != std::cend(ChrFmt)) { strDestStr += ItemIterator->second; } else { const auto& AddCollapsible = [&](string&& Str) { if (strDestStr.empty()) { strDestStr = std::move(Str); Iterator->Collapsible = true; } else { Iterator = Result.insert(std::next(Iterator), segment{ std::move(Str), Iterator->Colour, true }); } // No need to introduce a new segment if we're at the very end if (std::next(Iterator) != Result.end() && std::next(it) != strExpandedDestStr.cend()) { Iterator = Result.insert(std::next(Iterator), segment{ {}, Iterator->Colour, false }); } }; switch (Chr) { /* эти не реaлизованы $E - Escape code (ASCII code 27) $V - Windows version number $_ - Carriage return and linefeed */ case L'M': // $M - Отображение полного имени удаленного диска, связанного с именем текущего диска, или пустой строки, если текущий диск не является сетевым. { string strTemp; if (DriveLocalToRemoteName(DRIVE_UNKNOWN, m_CurDir[0], strTemp)) { AddCollapsible(std::move(strTemp)); } break; } case L'+': // $+ - Отображение нужного числа знаков плюс (+) в зависимости от текущей глубины стека каталогов PUSHD, по одному знаку на каждый сохраненный путь. { strDestStr.append(ppstack.size(), L'+'); break; } case L'H': // $H - Backspace (erases previous character) { if (!strDestStr.empty()) { strDestStr.pop_back(); } else { auto Prev = Iterator; while (Prev != Result.begin()) { --Prev; if (!Prev->Text.empty()) { Prev->Text.pop_back(); break; } } } break; } case L'@': // $@xx - Admin { if (it + 1 != strExpandedDestStr.cend()) { const auto lb = *++it; if (it + 1 != strExpandedDestStr.cend()) { const auto rb = *++it; if (os::security::is_admin()) { append(strDestStr, lb, msg(lng::MConfigCmdlinePromptFormatAdmin), rb); } } } break; } case L'D': // $D - Current date case L'T': // $T - Current time { strDestStr += MkStrFTime(Chr == L'D'? L"%D" : L"%T"); break; } case L'N': // $N - Current drive { const auto Type = ParsePath(m_CurDir); if(Type == root_type::drive_letter) strDestStr += upper(m_CurDir[0]); else if(Type == root_type::unc_drive_letter) strDestStr += upper(m_CurDir[4]); else strDestStr += L'?'; break; } case L'W': // $W - Текущий рабочий каталог (без указания пути) { const auto pos = FindLastSlash(m_CurDir); if (pos != string::npos) { AddCollapsible(m_CurDir.substr(pos + 1)); } break; } case L'P': // $P - Current drive and path { AddCollapsible(string{ m_CurDir }); break; } case L'#': //$#nn - max prompt width in % { if (it + 1 != strExpandedDestStr.end()) { size_t pos; if (from_string(string(it + 1, strExpandedDestStr.cend()), NewPromptSize, &pos)) it += pos; // else // bad format, NewPromptSize unchanged // TODO: diagnostics } } } if (it == strExpandedDestStr.cend()) { break; } } } else {