Fix trigger for tier 1 call counting delay (#17477)
[platform/upstream/coreclr.git] / src / binder / stringlexer.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 // ============================================================
5 //
6 // StringLexer.cpp
7 //
8
9
10 //
11 // Implements the StringLexer class
12 //
13 // ============================================================
14
15 #define DISABLE_BINDER_DEBUG_LOGGING
16
17 #include "stringlexer.hpp"
18 #include "utils.hpp"
19
20 #include "ex.h"
21
22 namespace BINDER_SPACE
23 {
24     StringLexer::LEXEME_TYPE
25     StringLexer::GetNextLexeme(SString &currentString, BOOL fPermitUnescapedQuotes)
26     {
27         BOOL fIsEscaped = FALSE;
28         WCHAR wcCurrentChar = INVALID_CHARACTER;
29         BINDER_LOG_ENTER(L"StringLexer::GetNextLexeme");
30
31         // Remove any white spaces
32         do
33         {
34             wcCurrentChar = PopCharacter(&fIsEscaped);
35         }
36         while (IsWhitespace(wcCurrentChar));
37
38         // Determine lexeme type
39         LEXEME_TYPE kLexemeType = LEXEME_TYPE_INVALID;
40         if (!fIsEscaped)
41         {
42             kLexemeType = GetLexemeType(wcCurrentChar);
43
44             if (kLexemeType != LEXEME_TYPE_STRING)
45             {
46                 return kLexemeType;
47             }
48         }
49
50         // First character of string lexeme; push it back
51         PushCharacter(wcCurrentChar, fIsEscaped);
52         kLexemeType = ParseString(currentString, fPermitUnescapedQuotes);
53         if (kLexemeType == LEXEME_TYPE_STRING)
54         {
55             BINDER_LOG_LEAVE_HR(L"StringLexer::GetNextLexeme(LEXEME_TYPE_STRING)", S_OK);
56         }
57         else
58         {
59             BINDER_LOG_LEAVE_HR(L"StringLexer::GetNextLexeme(LEXEME_TYPE_INVALID)",
60                                 S_FALSE);
61         }
62
63         return kLexemeType;
64     }
65
66     StringLexer::LEXEME_TYPE
67     StringLexer::ParseString(SString &currentString, BOOL fPermitUnescapedQuotes)
68     {
69         BOOL fIsFirstCharacter = TRUE;
70         WCHAR wcCurrentChar = INVALID_CHARACTER;
71         WCHAR wcOpeningQuote = INVALID_CHARACTER;
72
73         currentString.Clear();
74
75         // Read until we find another lexeme that's not a string character
76         for (;;)
77         {
78             BOOL fIsEscaped = FALSE;
79             wcCurrentChar = PopCharacter(&fIsEscaped);
80
81             if (wcCurrentChar == INVALID_CHARACTER)
82             {
83                 // Found invalid character encoding
84                 BINDER_LOG(L"StringLexer::ParseString: Invalid character encoding");
85                 return LEXEME_TYPE_INVALID;
86             }
87
88             if (IsEOS(wcCurrentChar))
89             {
90                 if (IsQuoteCharacter(wcOpeningQuote))
91                 {
92                     // EOS and unclosed quotes is an error
93                     BINDER_LOG(L"StringLexer::ParseString: EOS and unclosed quotes");
94                     return LEXEME_TYPE_INVALID;
95                 }
96                 else
97                 {
98                     // Reached end of input and therefore of string
99                     break;
100                 }
101             }
102
103             if (fIsFirstCharacter)
104             {
105                 fIsFirstCharacter = FALSE;
106
107                 // If first character is quote, then record its quoteness
108                 if (IsQuoteCharacter(wcCurrentChar))
109                 {
110                     wcOpeningQuote = wcCurrentChar;
111                     continue;
112                 }
113             }
114             
115             if (wcCurrentChar == wcOpeningQuote)
116             {
117                 // We've found the closing quote for a quoted string
118                 break;
119             }
120            
121             if (!fPermitUnescapedQuotes && !fIsEscaped && IsQuoteCharacter(wcCurrentChar) && !IsQuoteCharacter(wcOpeningQuote))
122             {
123                 // Unescaped quotes in the middle of the string are an error
124                 BINDER_LOG(L"StringLexer::ParseString: Quote in the middle of a string");
125                 return LEXEME_TYPE_INVALID;
126             }
127
128             if (IsSeparatorChar(wcCurrentChar) && !IsQuoteCharacter(wcOpeningQuote) && !fIsEscaped)
129             {
130                 // Unescaped separator char terminates the string
131                 PushCharacter(wcCurrentChar, fIsEscaped);
132                 break;
133             }
134
135             // Add character to current string
136             currentString.Append(wcCurrentChar);
137         }
138
139         if (!IsQuoteCharacter(wcOpeningQuote))
140         {
141             // Remove trailing white spaces from unquoted string
142             BINDER_LOG(L"StringLexer::ParseString: Trimming string");
143             TrimTrailingWhiteSpaces(currentString);
144         }
145
146         BINDER_LOG_STRING(L"string", currentString);
147
148         return LEXEME_TYPE_STRING;
149     }
150
151     void StringLexer::TrimTrailingWhiteSpaces(SString &currentString)
152     {
153         SString::Iterator begin = currentString.Begin();
154         SString::Iterator cursor = currentString.End() - 1;
155         BOOL fFoundWhiteSpace = FALSE;
156
157         for (;;)
158         {
159             if ((cursor >= begin) && IsWhitespace(cursor[0]))
160             {
161                 fFoundWhiteSpace = TRUE;
162                 cursor--;
163                 continue;
164             }
165             break;
166         }
167             
168         if (fFoundWhiteSpace)
169         {
170             currentString.Truncate(cursor + 1);
171         }
172     }
173 };