simplekey.cpp (3208B)
1 #include "scanner.h" 2 #include "token.h" 3 4 namespace YAML { 5 struct Mark; 6 7 Scanner::SimpleKey::SimpleKey(const Mark& mark_, std::size_t flowLevel_) 8 : mark(mark_), 9 flowLevel(flowLevel_), 10 pIndent(nullptr), 11 pMapStart(nullptr), 12 pKey(nullptr) {} 13 14 void Scanner::SimpleKey::Validate() { 15 // Note: pIndent will *not* be garbage here; 16 // we "garbage collect" them so we can 17 // always refer to them 18 if (pIndent) 19 pIndent->status = IndentMarker::VALID; 20 if (pMapStart) 21 pMapStart->status = Token::VALID; 22 if (pKey) 23 pKey->status = Token::VALID; 24 } 25 26 void Scanner::SimpleKey::Invalidate() { 27 if (pIndent) 28 pIndent->status = IndentMarker::INVALID; 29 if (pMapStart) 30 pMapStart->status = Token::INVALID; 31 if (pKey) 32 pKey->status = Token::INVALID; 33 } 34 35 // CanInsertPotentialSimpleKey 36 bool Scanner::CanInsertPotentialSimpleKey() const { 37 if (!m_simpleKeyAllowed) 38 return false; 39 40 return !ExistsActiveSimpleKey(); 41 } 42 43 // ExistsActiveSimpleKey 44 // . Returns true if there's a potential simple key at our flow level 45 // (there's allowed at most one per flow level, i.e., at the start of the flow 46 // start token) 47 bool Scanner::ExistsActiveSimpleKey() const { 48 if (m_simpleKeys.empty()) 49 return false; 50 51 const SimpleKey& key = m_simpleKeys.top(); 52 return key.flowLevel == GetFlowLevel(); 53 } 54 55 // InsertPotentialSimpleKey 56 // . If we can, add a potential simple key to the queue, 57 // and save it on a stack. 58 void Scanner::InsertPotentialSimpleKey() { 59 if (!CanInsertPotentialSimpleKey()) 60 return; 61 62 SimpleKey key(INPUT.mark(), GetFlowLevel()); 63 64 // first add a map start, if necessary 65 if (InBlockContext()) { 66 key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP); 67 if (key.pIndent) { 68 key.pIndent->status = IndentMarker::UNKNOWN; 69 key.pMapStart = key.pIndent->pStartToken; 70 key.pMapStart->status = Token::UNVERIFIED; 71 } 72 } 73 74 // then add the (now unverified) key 75 m_tokens.push(Token(Token::KEY, INPUT.mark())); 76 key.pKey = &m_tokens.back(); 77 key.pKey->status = Token::UNVERIFIED; 78 79 m_simpleKeys.push(key); 80 } 81 82 // InvalidateSimpleKey 83 // . Automatically invalidate the simple key in our flow level 84 void Scanner::InvalidateSimpleKey() { 85 if (m_simpleKeys.empty()) 86 return; 87 88 // grab top key 89 SimpleKey& key = m_simpleKeys.top(); 90 if (key.flowLevel != GetFlowLevel()) 91 return; 92 93 key.Invalidate(); 94 m_simpleKeys.pop(); 95 } 96 97 // VerifySimpleKey 98 // . Determines whether the latest simple key to be added is valid, 99 // and if so, makes it valid. 100 bool Scanner::VerifySimpleKey() { 101 if (m_simpleKeys.empty()) 102 return false; 103 104 // grab top key 105 SimpleKey key = m_simpleKeys.top(); 106 107 // only validate if we're in the correct flow level 108 if (key.flowLevel != GetFlowLevel()) 109 return false; 110 111 m_simpleKeys.pop(); 112 113 bool isValid = true; 114 115 // needs to be less than 1024 characters and inline 116 if (INPUT.line() != key.mark.line || INPUT.pos() - key.mark.pos > 1024) 117 isValid = false; 118 119 // invalidate key 120 if (isValid) 121 key.Validate(); 122 else 123 key.Invalidate(); 124 125 return isValid; 126 } 127 128 void Scanner::PopAllSimpleKeys() { 129 while (!m_simpleKeys.empty()) 130 m_simpleKeys.pop(); 131 } 132 } // namespace YAML