Author: Michael Buch Date: 2025-12-17T12:58:26Z New Revision: e4c4498798b0e78480bc8196696fa390550dd39a
URL: https://github.com/llvm/llvm-project/commit/e4c4498798b0e78480bc8196696fa390550dd39a DIFF: https://github.com/llvm/llvm-project/commit/e4c4498798b0e78480bc8196696fa390550dd39a.diff LOG: [lldb][ObjC][NFCI] Replace StringLexer with llvm::StringRef (#172466) We had a dedicated `StringLexer` class that pretty much just replicates the `llvm::StringRef` interface. This patch removes the `StringLexer` in favour of just using `llvm::StringRef`. Much of the string parsing can be cleaned up, but I tried to keep the changes a small as possible so just kept the logic and replaced the APIs calls. The only awkward side-effect of this is that we have to pass a `llvm::StringRef &` around. There were some gaps in the API, so added two helper methods to consume/pop off characters from the front of the StringRef (maybe those can be added to `llvm::StringRef` in the future). The `StringLexer` also had a roll-back mechanism used in two places. That can be handled by just saving a copy of the `StringRef`. Added: Modified: lldb/include/lldb/DataFormatters/FormattersContainer.h lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h lldb/source/Utility/CMakeLists.txt lldb/unittests/Utility/CMakeLists.txt Removed: lldb/include/lldb/Utility/StringLexer.h lldb/source/Utility/StringLexer.cpp lldb/unittests/Utility/StringLexerTest.cpp ################################################################################ diff --git a/lldb/include/lldb/DataFormatters/FormattersContainer.h b/lldb/include/lldb/DataFormatters/FormattersContainer.h index f7465fc65538d..0761dcfcb12ea 100644 --- a/lldb/include/lldb/DataFormatters/FormattersContainer.h +++ b/lldb/include/lldb/DataFormatters/FormattersContainer.h @@ -23,7 +23,6 @@ #include "lldb/DataFormatters/TypeSynthetic.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Utility/RegularExpression.h" -#include "lldb/Utility/StringLexer.h" #include "lldb/ValueObject/ValueObject.h" namespace lldb_private { @@ -59,18 +58,15 @@ class TypeMatcher { if (type.IsEmpty()) return type; - std::string type_cstr(type.AsCString()); - StringLexer type_lexer(type_cstr); + llvm::StringRef type_lexer(type.AsCString()); - type_lexer.AdvanceIf("class "); - type_lexer.AdvanceIf("enum "); - type_lexer.AdvanceIf("struct "); - type_lexer.AdvanceIf("union "); + type_lexer.consume_front("class "); + type_lexer.consume_front("enum "); + type_lexer.consume_front("struct "); + type_lexer.consume_front("union "); + type_lexer = type_lexer.ltrim(); - while (type_lexer.NextIf({' ', '\t', '\v', '\f'}).first) - ; - - return ConstString(type_lexer.GetUnlexed()); + return ConstString(type_lexer); } public: diff --git a/lldb/include/lldb/Utility/StringLexer.h b/lldb/include/lldb/Utility/StringLexer.h deleted file mode 100644 index 52f98e860da2b..0000000000000 --- a/lldb/include/lldb/Utility/StringLexer.h +++ /dev/null @@ -1,56 +0,0 @@ -//===-- StringLexer.h -------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_UTILITY_STRINGLEXER_H -#define LLDB_UTILITY_STRINGLEXER_H - -#include <initializer_list> -#include <string> -#include <utility> - -namespace lldb_private { - -class StringLexer { -public: - typedef std::string::size_type Position; - typedef std::string::size_type Size; - - typedef std::string::value_type Character; - - StringLexer(std::string s); - - // These APIs are not bounds-checked. Use HasAtLeast() if you're not sure. - Character Peek(); - - bool NextIf(Character c); - - std::pair<bool, Character> NextIf(std::initializer_list<Character> cs); - - bool AdvanceIf(const std::string &token); - - Character Next(); - - bool HasAtLeast(Size s); - - std::string GetUnlexed(); - - // This will assert if there are less than s characters preceding the cursor. - void PutBack(Size s); - - StringLexer &operator=(const StringLexer &rhs); - -private: - std::string m_data; - Position m_position; - - void Consume(); -}; - -} // namespace lldb_private - -#endif // LLDB_UTILITY_STRINGLEXER_H diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp index f29a876ba2f24..e8908393e7ace 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp @@ -15,13 +15,29 @@ #include "lldb/Target/Target.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" -#include "lldb/Utility/StringLexer.h" #include "clang/Basic/TargetInfo.h" #include <optional> #include <vector> +static char popChar(llvm::StringRef &str) { + const char c = str.front(); + + str = str.drop_front(); + + return c; +} + +static bool consumeChar(llvm::StringRef &str, char c) { + if (!str.starts_with(c)) + return false; + + str = str.drop_front(); + + return true; +} + using namespace lldb_private; AppleObjCTypeEncodingParser::AppleObjCTypeEncodingParser( @@ -35,31 +51,33 @@ AppleObjCTypeEncodingParser::AppleObjCTypeEncodingParser( runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple()); } -std::string AppleObjCTypeEncodingParser::ReadStructName(StringLexer &type) { +std::string AppleObjCTypeEncodingParser::ReadStructName(llvm::StringRef &type) { StreamString buffer; - while (type.HasAtLeast(1) && type.Peek() != '=') - buffer.Printf("%c", type.Next()); + while (!type.empty() && type.front() != '=') + buffer.Printf("%c", popChar(type)); + return std::string(buffer.GetString()); } std::optional<std::string> -AppleObjCTypeEncodingParser::ReadQuotedString(StringLexer &type) { - if (!type.HasAtLeast(1)) +AppleObjCTypeEncodingParser::ReadQuotedString(llvm::StringRef &type) { + if (type.empty()) return std::nullopt; StreamString buffer; - while (type.Peek() != '"') { - buffer.Printf("%c", type.Next()); - if (!type.HasAtLeast(1)) + while (type.front() != '"') { + buffer.Printf("%c", popChar(type)); + + if (type.empty()) return std::nullopt; } return std::string(buffer.GetString()); } -uint32_t AppleObjCTypeEncodingParser::ReadNumber(StringLexer &type) { +uint32_t AppleObjCTypeEncodingParser::ReadNumber(llvm::StringRef &type) { uint32_t total = 0; - while (type.HasAtLeast(1) && isdigit(type.Peek())) - total = 10 * total + (type.Next() - '0'); + while (!type.empty() && isdigit(type.front())) + total = 10 * total + (popChar(type) - '0'); return total; } @@ -72,10 +90,10 @@ AppleObjCTypeEncodingParser::StructElement::StructElement() AppleObjCTypeEncodingParser::StructElement AppleObjCTypeEncodingParser::ReadStructElement(TypeSystemClang &ast_ctx, - StringLexer &type, + llvm::StringRef &type, bool for_expression) { StructElement retval; - if (type.NextIf('"')) { + if (type.consume_front("\"")) { if (auto maybe_name = ReadQuotedString(type)) retval.name = *maybe_name; else @@ -88,22 +106,23 @@ AppleObjCTypeEncodingParser::ReadStructElement(TypeSystemClang &ast_ctx, } clang::QualType AppleObjCTypeEncodingParser::BuildStruct( - TypeSystemClang &ast_ctx, StringLexer &type, bool for_expression) { + TypeSystemClang &ast_ctx, llvm::StringRef &type, bool for_expression) { return BuildAggregate(ast_ctx, type, for_expression, _C_STRUCT_B, _C_STRUCT_E, llvm::to_underlying(clang::TagTypeKind::Struct)); } clang::QualType AppleObjCTypeEncodingParser::BuildUnion( - TypeSystemClang &ast_ctx, StringLexer &type, bool for_expression) { + TypeSystemClang &ast_ctx, llvm::StringRef &type, bool for_expression) { return BuildAggregate(ast_ctx, type, for_expression, _C_UNION_B, _C_UNION_E, llvm::to_underlying(clang::TagTypeKind::Union)); } clang::QualType AppleObjCTypeEncodingParser::BuildAggregate( - TypeSystemClang &ast_ctx, StringLexer &type, bool for_expression, + TypeSystemClang &ast_ctx, llvm::StringRef &type, bool for_expression, char opener, char closer, uint32_t kind) { - if (!type.NextIf(opener)) + if (!consumeChar(type, opener)) return clang::QualType(); + std::string name(ReadStructName(type)); // We do not handle templated classes/structs at the moment. If the name has @@ -112,12 +131,12 @@ clang::QualType AppleObjCTypeEncodingParser::BuildAggregate( const bool is_templated = name.find('<') != std::string::npos; - if (!type.NextIf('=')) + if (!type.consume_front("=")) return clang::QualType(); bool in_union = true; std::vector<StructElement> elements; - while (in_union && type.HasAtLeast(1)) { - if (type.NextIf(closer)) { + while (in_union && !type.empty()) { + if (consumeChar(type, closer)) { in_union = false; break; } else { @@ -158,13 +177,15 @@ clang::QualType AppleObjCTypeEncodingParser::BuildAggregate( } clang::QualType AppleObjCTypeEncodingParser::BuildArray( - TypeSystemClang &ast_ctx, StringLexer &type, bool for_expression) { - if (!type.NextIf(_C_ARY_B)) + TypeSystemClang &ast_ctx, llvm::StringRef &type, bool for_expression) { + if (!consumeChar(type, _C_ARY_B)) return clang::QualType(); + uint32_t size = ReadNumber(type); clang::QualType element_type(BuildType(ast_ctx, type, for_expression)); - if (!type.NextIf(_C_ARY_E)) + if (!consumeChar(type, _C_ARY_E)) return clang::QualType(); + CompilerType array_type(ast_ctx.CreateArrayType( CompilerType(ast_ctx.weak_from_this(), element_type.getAsOpaquePtr()), size, false)); @@ -177,15 +198,16 @@ clang::QualType AppleObjCTypeEncodingParser::BuildArray( // consume but ignore the type info and always return an 'id'; if anything, // dynamic typing will resolve things for us anyway clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType( - TypeSystemClang &clang_ast_ctx, StringLexer &type, bool for_expression) { - if (!type.NextIf(_C_ID)) + TypeSystemClang &clang_ast_ctx, llvm::StringRef &type, + bool for_expression) { + if (!consumeChar(type, _C_ID)) return clang::QualType(); clang::ASTContext &ast_ctx = clang_ast_ctx.getASTContext(); std::string name; - if (type.NextIf('"')) { + if (type.consume_front("\"")) { // We have to be careful here. We're used to seeing // @"NSString" // but in records it is possible that the string following an @ is the name @@ -205,17 +227,18 @@ clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType( // quoted string is a class name. - If we see anything else, the quoted // string is a field name and we push it back onto type. + // Save a copy for possible rollback. + llvm::StringRef backup = type; if (auto maybe_name = ReadQuotedString(type)) name = *maybe_name; else return clang::QualType(); - if (type.HasAtLeast(1)) { - switch (type.Peek()) { + if (!type.empty()) { + switch (type.front()) { default: - // roll back - type.PutBack(name.length() + - 2); // undo our consumption of the string and of the quotes + // roll back: undo our consumption of the string and of the quotes + type = backup; name.clear(); break; case _C_STRUCT_E: @@ -263,16 +286,15 @@ clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType( } } -clang::QualType -AppleObjCTypeEncodingParser::BuildType(TypeSystemClang &clang_ast_ctx, - StringLexer &type, bool for_expression, - uint32_t *bitfield_bit_size) { - if (!type.HasAtLeast(1)) +clang::QualType AppleObjCTypeEncodingParser::BuildType( + TypeSystemClang &clang_ast_ctx, llvm::StringRef &type, bool for_expression, + uint32_t *bitfield_bit_size) { + if (type.empty()) return clang::QualType(); clang::ASTContext &ast_ctx = clang_ast_ctx.getASTContext(); - switch (type.Peek()) { + switch (type.front()) { default: break; case _C_STRUCT_B: @@ -285,9 +307,12 @@ AppleObjCTypeEncodingParser::BuildType(TypeSystemClang &clang_ast_ctx, return BuildObjCObjectPointerType(clang_ast_ctx, type, for_expression); } - switch (type.Next()) { + // Save a copy for potential rollback. + llvm::StringRef backup = type; + + switch (popChar(type)) { default: - type.PutBack(1); + type = backup; return clang::QualType(); case _C_CHR: return ast_ctx.CharTy; @@ -347,7 +372,7 @@ AppleObjCTypeEncodingParser::BuildType(TypeSystemClang &clang_ast_ctx, return ast_ctx.getConstType(target_type); } case _C_PTR: { - if (!for_expression && type.NextIf(_C_UNDEF)) { + if (!for_expression && consumeChar(type, _C_UNDEF)) { // if we are not supporting the concept of unknownAny, but what is being // created here is an unknownAny*, then we can just get away with a void* // this is theoretically wrong (in the same sense as 'theoretically @@ -374,7 +399,7 @@ CompilerType AppleObjCTypeEncodingParser::RealizeType(TypeSystemClang &ast_ctx, const char *name, bool for_expression) { if (name && name[0]) { - StringLexer lexer(name); + llvm::StringRef lexer(name); clang::QualType qual_type = BuildType(ast_ctx, lexer, for_expression); return ast_ctx.GetType(qual_type); } diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h index 3058514f38ba1..6a6461b04c71c 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h @@ -16,7 +16,6 @@ #include "clang/AST/ASTContext.h" namespace lldb_private { -class StringLexer; class AppleObjCTypeEncodingParser : public ObjCLanguageRuntime::EncodingToType { public: AppleObjCTypeEncodingParser(ObjCLanguageRuntime &runtime); @@ -35,35 +34,35 @@ class AppleObjCTypeEncodingParser : public ObjCLanguageRuntime::EncodingToType { ~StructElement() = default; }; - clang::QualType BuildType(TypeSystemClang &clang_ast_ctx, StringLexer &type, - bool for_expression, + clang::QualType BuildType(TypeSystemClang &clang_ast_ctx, + llvm::StringRef &type, bool for_expression, uint32_t *bitfield_bit_size = nullptr); - clang::QualType BuildStruct(TypeSystemClang &ast_ctx, StringLexer &type, + clang::QualType BuildStruct(TypeSystemClang &ast_ctx, llvm::StringRef &type, bool for_expression); clang::QualType BuildAggregate(TypeSystemClang &clang_ast_ctx, - StringLexer &type, bool for_expression, + llvm::StringRef &type, bool for_expression, char opener, char closer, uint32_t kind); - clang::QualType BuildUnion(TypeSystemClang &ast_ctx, StringLexer &type, + clang::QualType BuildUnion(TypeSystemClang &ast_ctx, llvm::StringRef &type, bool for_expression); - clang::QualType BuildArray(TypeSystemClang &ast_ctx, StringLexer &type, + clang::QualType BuildArray(TypeSystemClang &ast_ctx, llvm::StringRef &type, bool for_expression); - std::string ReadStructName(StringLexer &type); + std::string ReadStructName(llvm::StringRef &type); - StructElement ReadStructElement(TypeSystemClang &ast_ctx, StringLexer &type, - bool for_expression); + StructElement ReadStructElement(TypeSystemClang &ast_ctx, + llvm::StringRef &type, bool for_expression); clang::QualType BuildObjCObjectPointerType(TypeSystemClang &clang_ast_ctx, - StringLexer &type, + llvm::StringRef &type, bool for_expression); - uint32_t ReadNumber(StringLexer &type); + uint32_t ReadNumber(llvm::StringRef &type); - std::optional<std::string> ReadQuotedString(StringLexer &type); + std::optional<std::string> ReadQuotedString(llvm::StringRef &type); ObjCLanguageRuntime &m_runtime; }; diff --git a/lldb/source/Utility/CMakeLists.txt b/lldb/source/Utility/CMakeLists.txt index 80b53f8c098d2..04f1692e53b35 100644 --- a/lldb/source/Utility/CMakeLists.txt +++ b/lldb/source/Utility/CMakeLists.txt @@ -63,7 +63,6 @@ add_lldb_library(lldbUtility NO_INTERNAL_DEPENDENCIES StreamString.cpp StringExtractor.cpp StringExtractorGDBRemote.cpp - StringLexer.cpp StringList.cpp StructuredData.cpp TildeExpressionResolver.cpp diff --git a/lldb/source/Utility/StringLexer.cpp b/lldb/source/Utility/StringLexer.cpp deleted file mode 100644 index bda6e25ce7a35..0000000000000 --- a/lldb/source/Utility/StringLexer.cpp +++ /dev/null @@ -1,85 +0,0 @@ -//===-- StringLexer.cpp ---------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Utility/StringLexer.h" - -#include <algorithm> -#include <cassert> -#include <utility> - -using namespace lldb_private; - -StringLexer::StringLexer(std::string s) : m_data(std::move(s)), m_position(0) {} - -StringLexer::Character StringLexer::Peek() { return m_data[m_position]; } - -bool StringLexer::NextIf(Character c) { - auto val = Peek(); - if (val == c) { - Next(); - return true; - } - return false; -} - -std::pair<bool, StringLexer::Character> -StringLexer::NextIf(std::initializer_list<Character> cs) { - auto val = Peek(); - for (auto c : cs) { - if (val == c) { - Next(); - return {true, c}; - } - } - return {false, 0}; -} - -bool StringLexer::AdvanceIf(const std::string &token) { - auto pos = m_position; - bool matches = true; - for (auto c : token) { - if (!NextIf(c)) { - matches = false; - break; - } - } - if (!matches) { - m_position = pos; - return false; - } - return true; -} - -StringLexer::Character StringLexer::Next() { - auto val = Peek(); - Consume(); - return val; -} - -bool StringLexer::HasAtLeast(Size s) { - return (m_data.size() - m_position) >= s; -} - -void StringLexer::PutBack(Size s) { - assert(m_position >= s); - m_position -= s; -} - -std::string StringLexer::GetUnlexed() { - return std::string(m_data, m_position); -} - -void StringLexer::Consume() { m_position++; } - -StringLexer &StringLexer::operator=(const StringLexer &rhs) { - if (this != &rhs) { - m_data = rhs.m_data; - m_position = rhs.m_position; - } - return *this; -} diff --git a/lldb/unittests/Utility/CMakeLists.txt b/lldb/unittests/Utility/CMakeLists.txt index 674eefdffb59c..47c5e815d5b34 100644 --- a/lldb/unittests/Utility/CMakeLists.txt +++ b/lldb/unittests/Utility/CMakeLists.txt @@ -35,7 +35,6 @@ add_lldb_unittest(UtilityTests StreamTest.cpp StringExtractorGDBRemoteTest.cpp StringExtractorTest.cpp - StringLexerTest.cpp StringListTest.cpp StructuredDataTest.cpp SubsystemRAIITest.cpp diff --git a/lldb/unittests/Utility/StringLexerTest.cpp b/lldb/unittests/Utility/StringLexerTest.cpp deleted file mode 100644 index f7a81bddceae1..0000000000000 --- a/lldb/unittests/Utility/StringLexerTest.cpp +++ /dev/null @@ -1,140 +0,0 @@ -//===-- StringLexerTest.cpp -----------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Utility/StringLexer.h" -#include "gtest/gtest.h" - -using namespace lldb_private; - -TEST(StringLexerTest, GetUnlexed) { - StringLexer l("foo"); - EXPECT_EQ("foo", l.GetUnlexed()); - l.Next(); - EXPECT_EQ("oo", l.GetUnlexed()); - l.Next(); - l.Next(); - EXPECT_EQ("", l.GetUnlexed()); -} - -TEST(StringLexerTest, HasAtLeast) { - StringLexer l("foo"); - EXPECT_FALSE(l.HasAtLeast(5)); - EXPECT_FALSE(l.HasAtLeast(4)); - EXPECT_TRUE(l.HasAtLeast(3)); - EXPECT_TRUE(l.HasAtLeast(2)); - EXPECT_TRUE(l.HasAtLeast(1)); - - l.Next(); - EXPECT_FALSE(l.HasAtLeast(5)); - EXPECT_FALSE(l.HasAtLeast(4)); - EXPECT_FALSE(l.HasAtLeast(3)); - EXPECT_TRUE(l.HasAtLeast(2)); - EXPECT_TRUE(l.HasAtLeast(1)); - - l.Next(); - l.Next(); - EXPECT_FALSE(l.HasAtLeast(5)); - EXPECT_FALSE(l.HasAtLeast(4)); - EXPECT_FALSE(l.HasAtLeast(3)); - EXPECT_FALSE(l.HasAtLeast(2)); - EXPECT_FALSE(l.HasAtLeast(1)); -} - -TEST(StringLexerTest, AdvanceIf) { - StringLexer l("foobar"); - - EXPECT_FALSE(l.AdvanceIf("oo")); - // Skip the "fo" part. - EXPECT_TRUE(l.AdvanceIf("fo")); - EXPECT_FALSE(l.AdvanceIf("obarz")); - // Skip the remaining string. - EXPECT_TRUE(l.AdvanceIf("obar")); - - EXPECT_FALSE(l.AdvanceIf("obarz")); - EXPECT_FALSE(l.AdvanceIf("foo")); - EXPECT_FALSE(l.AdvanceIf("o")); - EXPECT_FALSE(l.AdvanceIf(" ")); -} - -TEST(StringLexerTest, PutBack) { - StringLexer l("foo"); - - l.Next(); - l.PutBack(1); - EXPECT_EQ("foo", l.GetUnlexed()); - - l.Next(); - l.Next(); - l.Next(); - l.PutBack(2); - EXPECT_EQ("oo", l.GetUnlexed()); - - l.PutBack(1); - EXPECT_EQ("foo", l.GetUnlexed()); -} - -TEST(StringLexerTest, Peek) { - StringLexer l("foo"); - - EXPECT_EQ('f', l.Peek()); - l.Next(); - EXPECT_EQ('o', l.Peek()); - l.Next(); - EXPECT_EQ('o', l.Peek()); -} - -TEST(StringLexerTest, Next) { - StringLexer l("foo"); - EXPECT_EQ('f', l.Next()); - EXPECT_EQ('o', l.Next()); - EXPECT_EQ('o', l.Next()); -} - -TEST(StringLexerTest, NextIf) { - StringLexer l("foo"); - - EXPECT_FALSE(l.NextIf('\0')); - EXPECT_FALSE(l.NextIf(' ')); - EXPECT_FALSE(l.NextIf('o')); - - EXPECT_TRUE(l.NextIf('f')); - - EXPECT_FALSE(l.NextIf('\0')); - EXPECT_FALSE(l.NextIf(' ')); - EXPECT_FALSE(l.NextIf('f')); - - EXPECT_TRUE(l.NextIf('o')); - - EXPECT_FALSE(l.NextIf('\0')); - EXPECT_FALSE(l.NextIf(' ')); - EXPECT_FALSE(l.NextIf('f')); - - EXPECT_TRUE(l.NextIf('o')); -} - -TEST(StringLexerTest, NextIfList) { - StringLexer l("foo"); - - EXPECT_FALSE(l.NextIf({'\0', ' ', 'o'}).first); - - auto r = l.NextIf({'f'}); - EXPECT_TRUE(r.first); - EXPECT_EQ('f', r.second); - - EXPECT_FALSE(l.NextIf({'\0', ' ', 'f'}).first); - - r = l.NextIf({'f', 'o'}); - EXPECT_TRUE(r.first); - EXPECT_EQ('o', r.second); - - EXPECT_FALSE(l.NextIf({'\0', ' ', 'f'}).first); - - r = l.NextIf({'*', 'f', 'o', 'o'}); - EXPECT_TRUE(r.first); - EXPECT_EQ('o', r.second); -} _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
