55using System ;
66using System . Collections . Generic ;
77using System . Numerics ;
8+ using System . Runtime . CompilerServices ;
89using Windows . UI ;
910using Windows . UI . Composition ;
1011
@@ -283,9 +284,10 @@ internal void EnsureReferenceInfo()
283284
284285 // Create a map to store the generated paramNames for each CompObj
285286 _compObjToParamNameMap = new Dictionary < CompositionObject , string > ( ) ;
287+ var paramCount = 0u ;
286288 foreach ( var compObj in compObjects )
287289 {
288- string paramName = Guid . NewGuid ( ) . ToUppercaseAsciiLetters ( ) ;
290+ string paramName = CreateUniqueParamNameFromIndex ( paramCount ++ ) ;
289291
290292 _compObjToParamNameMap . Add ( compObj , paramName ) ;
291293 }
@@ -312,6 +314,37 @@ internal void EnsureReferenceInfo()
312314 refNode . ParamName = paramName ;
313315 }
314316 }
317+
318+ // Generates Excel-column-like identifiers, e.g. A, B, ..., Z, AA, BA...
319+ // This implementation aggregates characters in reverse order to avoid having to
320+ // precompute the exact number of characters in the resulting string. This is not
321+ // important in this context as the only critical property to maintain is to have
322+ // a unique mapping to each input value to the resulting sequence of letters.
323+ [ SkipLocalsInit ]
324+ static unsafe string CreateUniqueParamNameFromIndex ( uint i )
325+ {
326+ const int alphabetLength = 'Z' - 'A' + 1 ;
327+
328+ // The total length of the resulting sequence is guaranteed to always
329+ // be less than 8, given that log26(4294967295) ≈ 6.8. In this case we
330+ // are just allocating the immediate next power of two following that.
331+ // Note: this is using a char* buffer instead of Span<char> as the latter
332+ // is not referenced here, and we don't want to pull in an extra package.
333+ char * characters = stackalloc char [ 8 ] ;
334+
335+ characters [ 0 ] = ( char ) ( 'A' + ( i % alphabetLength ) ) ;
336+
337+ int totalCharacters = 1 ;
338+
339+ while ( ( i /= alphabetLength ) > 0 )
340+ {
341+ i -- ;
342+
343+ characters [ totalCharacters ++ ] = ( char ) ( 'A' + ( i % alphabetLength ) ) ;
344+ }
345+
346+ return new string ( characters , 0 , totalCharacters ) ;
347+ }
315348 }
316349
317350 /// <summary>
@@ -670,4 +703,4 @@ public ReferenceInfo(string paramName, CompositionObject compObj)
670703 /// <value>The subchannels.</value>
671704 protected internal string [ ] Subchannels { get ; set ; }
672705 }
673- }
706+ }
0 commit comments