@@ -74,16 +74,16 @@ private static IEnumerable<Marker> ScanForPlaceholders(
7474
7575 for ( int i = 0 ; ; )
7676 {
77- int open = value . IndexOf ( parameterPlaceholderOpening , i ) ;
77+ int open = value . IndexOf ( parameterPlaceholderOpening , i , StringComparison . Ordinal ) ;
7878 if ( open == - 1 ) yield break ; // Parameter placeholder opening not found
7979
80- int close = value . IndexOf ( parameterPlaceholderClosing , open + 1 ) ;
80+ int close = value . IndexOf ( parameterPlaceholderClosing , open + parameterPlaceholderOpening . Length , StringComparison . Ordinal ) ;
8181 if ( close == - 1 ) yield break ; // Parameter placeholder closing not found
8282
83- var key = value . Substring ( open + 1 , close - open - 1 ) ;
84- yield return new Marker ( open , close + 1 , key ) ;
83+ var key = value . Substring ( open + parameterPlaceholderOpening . Length , close - open - parameterPlaceholderOpening . Length ) ;
84+ yield return new Marker ( open , close + parameterPlaceholderClosing . Length , key ) ;
8585
86- i = close + 1 ;
86+ i = close + parameterPlaceholderClosing . Length ;
8787 }
8888 }
8989
@@ -121,8 +121,7 @@ private static IEnumerable<Marker> ScanForPlaceholders(
121121 private static List < string > TopologicalSort ( IDictionary < string , List < string > > graph )
122122 {
123123 var ordered = new List < string > ( graph . Count ) ;
124- var visited = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) ;
125- var visiting = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) ;
124+ var states = new Dictionary < string , NodeState > ( graph . Count , StringComparer . OrdinalIgnoreCase ) ;
126125
127126 foreach ( var node in graph . Keys )
128127 Dfs ( node ) ;
@@ -132,21 +131,36 @@ private static List<string> TopologicalSort(IDictionary<string, List<string>> gr
132131
133132 void Dfs ( string node )
134133 {
135- if ( ! visiting . Add ( node ) )
136- throw new CyclicDependencyException (
137- $ "Cyclic dependency detected on parameter '{ node } '.") ;
134+ ref var stateRef = ref CollectionsMarshal . GetValueRefOrAddDefault ( states , node , out bool exists ) ;
138135
139- if ( ! visited . Add ( node ) )
140- return ;
136+ if ( exists )
137+ {
138+ if ( stateRef == NodeState . Visiting )
139+ throw new CyclicDependencyException ( $ "Cyclic dependency detected on parameter '{ node } '.") ;
140+
141+ if ( stateRef == NodeState . Visited )
142+ return ;
143+ }
144+
145+ stateRef = NodeState . Visiting ;
141146
142147 if ( ! graph . TryGetValue ( node , out var children ) )
143148 throw new InvalidOperationException ( $ "Undefined parameter '{ node } '.") ;
144149
145150 foreach ( var child in children )
151+ {
146152 Dfs ( child ) ;
153+ }
147154
148- visiting . Remove ( node ) ;
155+ stateRef = NodeState . Visited ;
149156 ordered . Add ( node ) ;
150157 }
151158 }
159+
160+ private enum NodeState : Byte
161+ {
162+ Visiting ,
163+ Visited
164+ }
152165}
166+
0 commit comments