Skip to content

Commit f3bf811

Browse files
committed
Use hashed string values for type creator lookup
1 parent 7b61900 commit f3bf811

File tree

7 files changed

+280
-225
lines changed

7 files changed

+280
-225
lines changed

package/Codegen/Properties/launchSettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"profiles": {
33
"Codegen": {
44
"commandName": "Project",
5-
"commandLineArgs": "-verbose -winmd ..\\..\\..\\..\\..\\example\\windows\\packages\\Microsoft.UI.Xaml.2.6.0\\lib\\uap10.0\\Microsoft.UI.Xaml.winmd"
5+
"commandLineArgs": "-verbose -winmd ..\\..\\..\\..\\..\\examplenuget\\windows\\packages\\Microsoft.UI.Xaml.2.6.0\\lib\\uap10.0\\Microsoft.UI.Xaml.winmd"
66
}
77
}
88
}

package/Codegen/TypeCreator.cs

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// ------------------------------------------------------------------------------
22
// <auto-generated>
33
// This code was generated by a tool.
4-
// Runtime Version: 16.0.0.0
4+
// Runtime Version: 17.0.0.0
55
//
66
// Changes to this file may cause incorrect behavior and will be lost if
77
// the code is regenerated.
@@ -18,8 +18,8 @@ namespace Codegen
1818
/// Class to produce the template output
1919
/// </summary>
2020

21-
#line 1 "F:\react-native-xaml\package\Codegen\TypeCreator.tt"
22-
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")]
21+
#line 1 "C:\Users\asklar\source\repos\react-native-xaml\package\Codegen\TypeCreator.tt"
22+
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
2323
public partial class TypeCreator : TypeCreatorBase
2424
{
2525
#line hidden
@@ -31,80 +31,85 @@ public virtual string TransformText()
3131
this.Write("#include \"pch.h\"\r\n#include \"XamlMetadata.h\"\r\n#include \"Crc32Str.h\"\r\n#include <win" +
3232
"string.h>\r\n\r\n");
3333

34-
#line 11 "F:\react-native-xaml\package\Codegen\TypeCreator.tt"
34+
#line 11 "C:\Users\asklar\source\repos\react-native-xaml\package\Codegen\TypeCreator.tt"
3535
foreach (var ns in Types.Select(x => x.GetNamespace()).Distinct()) {
3636

3737
#line default
3838
#line hidden
3939
this.Write("#include \"winrt/");
4040

41-
#line 12 "F:\react-native-xaml\package\Codegen\TypeCreator.tt"
41+
#line 12 "C:\Users\asklar\source\repos\react-native-xaml\package\Codegen\TypeCreator.tt"
4242
this.Write(this.ToStringHelper.ToStringWithCulture(ns));
4343

4444
#line default
4545
#line hidden
4646
this.Write(".h\"\r\n");
4747

48-
#line 13 "F:\react-native-xaml\package\Codegen\TypeCreator.tt"
48+
#line 13 "C:\Users\asklar\source\repos\react-native-xaml\package\Codegen\TypeCreator.tt"
4949
}
5050

5151
#line default
5252
#line hidden
53-
this.Write(@"
54-
/*************************************************************
55-
THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT MODIFY MANUALLY
56-
**************************************************************/
57-
58-
winrt::Windows::Foundation::IInspectable XamlMetadata::Create(const std::string_view& typeName) const {
59-
wchar_t buf[128]{};
60-
for (auto i = 0u; i < typeName.size() && i < ARRAYSIZE(buf) - 1; i++) {
61-
buf[i] = static_cast<wchar_t>(typeName[i]);
62-
}
63-
64-
HSTRING clsid = nullptr;
65-
if (SUCCEEDED(WindowsCreateString(buf, static_cast<UINT32>(wcslen(buf)), &clsid))) {
66-
winrt::com_ptr<::IInspectable> insp{ nullptr };
67-
if (SUCCEEDED(RoActivateInstance(clsid, insp.put()))) {
68-
winrt::IUnknown unk{ nullptr };
69-
winrt::copy_from_abi(unk, insp.get());
70-
WindowsDeleteString(clsid);
71-
return unk.as<winrt::IInspectable>();
72-
} else {
73-
// type probably has a custom activation factory, use C++/WinRT to create it
74-
WindowsDeleteString(clsid);
75-
clsid = nullptr;
76-
const auto key = COMPILE_TIME_CRC32_STR(typeName.data());
77-
switch (key) {
78-
");
53+
this.Write("\r\n/*************************************************************\r\nTHIS FILE WAS A" +
54+
"UTOMATICALLY GENERATED, DO NOT MODIFY MANUALLY\r\n********************************" +
55+
"******************************/\r\n\r\ntemplate<typename T, typename K, size_t N>\r\nc" +
56+
"onst T* binary_search_map(const std::pair<K, T> (& map)[N], size_t low, size_t h" +
57+
"igh, const K& key) {\r\n while (low != high) {\r\n size_t midpoint = (low " +
58+
"+ high) / 2;\r\n if (map[midpoint].first == key) return &(map[midpoint].sec" +
59+
"ond);\r\n else if (((high - low) % 2 == 1) && map[midpoint + 1].first == ke" +
60+
"y) return &(map[midpoint + 1].second);\r\n else if (key < map[midpoint].fir" +
61+
"st) high = midpoint;\r\n else /*if (key > map[midpoint].first)*/ low = midp" +
62+
"oint + 1;\r\n }\r\n if (map[low].first == key) return &(map[low].second);\r\n " +
63+
" return nullptr;\r\n}\r\n\r\nwinrt::Windows::Foundation::IInspectable XamlMetadata::Cr" +
64+
"eate(const std::string_view& typeName) const {\r\n wchar_t buf[128]{};\r\n for (au" +
65+
"to i = 0u; i < typeName.size() && i < ARRAYSIZE(buf) - 1; i++) {\r\n buf[i] = s" +
66+
"tatic_cast<wchar_t>(typeName[i]);\r\n }\r\n\r\n HSTRING clsid = nullptr;\r\n if (SUCC" +
67+
"EEDED(WindowsCreateString(buf, static_cast<UINT32>(wcslen(buf)), &clsid))) {\r\n " +
68+
" winrt::com_ptr<::IInspectable> insp{ nullptr };\r\n if (SUCCEEDED(RoActivateI" +
69+
"nstance(clsid, insp.put()))) {\r\n winrt::IUnknown unk{ nullptr };\r\n win" +
70+
"rt::copy_from_abi(unk, insp.get());\r\n WindowsDeleteString(clsid);\r\n re" +
71+
"turn unk.as<winrt::IInspectable>();\r\n } else {\r\n // type probably has a " +
72+
"custom activation factory, use C++/WinRT to create it\r\n WindowsDeleteString" +
73+
"(clsid);\r\n clsid = nullptr;\r\n const auto key = COMPILE_TIME_CRC32_STR(" +
74+
"typeName.data());\r\n const std::pair<uint32_t, winrt::Windows::Foundation::I" +
75+
"Inspectable(*)()> map[] = {\r\n");
7976

80-
#line 39 "F:\react-native-xaml\package\Codegen\TypeCreator.tt"
81-
foreach (var t in Types.Where(t => Util.GetComposableFactoryType(t) != null)) {
77+
#line 52 "C:\Users\asklar\source\repos\react-native-xaml\package\Codegen\TypeCreator.tt"
78+
foreach (var t in Types.Where(t => Util.GetComposableFactoryType(t) != null).OrderBy(t => Util.GetCRC32(t.GetFullName()))) {
8279

8380
#line default
8481
#line hidden
85-
this.Write(" case COMPILE_TIME_CRC32_STR(\"");
82+
this.Write(" { COMPILE_TIME_CRC32_STR(\"");
8683

87-
#line 40 "F:\react-native-xaml\package\Codegen\TypeCreator.tt"
84+
#line 53 "C:\Users\asklar\source\repos\react-native-xaml\package\Codegen\TypeCreator.tt"
8885
this.Write(this.ToStringHelper.ToStringWithCulture(t.GetFullName()));
8986

9087
#line default
9188
#line hidden
92-
this.Write("\"): { return ");
89+
this.Write("\"), []() -> winrt::Windows::Foundation::IInspectable { return ");
9390

94-
#line 40 "F:\react-native-xaml\package\Codegen\TypeCreator.tt"
91+
#line 53 "C:\Users\asklar\source\repos\react-native-xaml\package\Codegen\TypeCreator.tt"
9592
this.Write(this.ToStringHelper.ToStringWithCulture(Util.GetCppWinRTType(t)));
9693

9794
#line default
9895
#line hidden
99-
this.Write("(); }\r\n");
96+
this.Write("(); } }, // 0x");
10097

101-
#line 41 "F:\react-native-xaml\package\Codegen\TypeCreator.tt"
98+
#line 53 "C:\Users\asklar\source\repos\react-native-xaml\package\Codegen\TypeCreator.tt"
99+
this.Write(this.ToStringHelper.ToStringWithCulture(Util.GetCRC32(t.GetFullName()).ToString("X8")));
100+
101+
#line default
102+
#line hidden
103+
this.Write("\r\n");
104+
105+
#line 54 "C:\Users\asklar\source\repos\react-native-xaml\package\Codegen\TypeCreator.tt"
102106
}
103107

104108
#line default
105109
#line hidden
106-
this.Write(" }\r\n }\r\n }\r\n assert(false && \"xaml type not found\");\r\n return nullptr;\r\n" +
107-
"}\r\n\r\n\r\n");
110+
this.Write(" };\r\n\r\n if (const auto it = binary_search_map(map, 0, std::size(map), k" +
111+
"ey)) {\r\n return (* it)();\r\n }\r\n }\r\n }\r\n assert(false && \"xaml t" +
112+
"ype not found\");\r\n return nullptr;\r\n}\r\n\r\n\r\n");
108113
return this.GenerationEnvironment.ToString();
109114
}
110115
}
@@ -115,7 +120,7 @@ public virtual string TransformText()
115120
/// <summary>
116121
/// Base class for this transformation
117122
/// </summary>
118-
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")]
123+
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
119124
public class TypeCreatorBase
120125
{
121126
#region Fields

package/Codegen/TypeCreator.tt

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,19 @@
1616
THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT MODIFY MANUALLY
1717
**************************************************************/
1818

19+
template<typename T, typename K, size_t N>
20+
const T* binary_search_map(const std::pair<K, T> (& map)[N], size_t low, size_t high, const K& key) {
21+
while (low != high) {
22+
size_t midpoint = (low + high) / 2;
23+
if (map[midpoint].first == key) return &(map[midpoint].second);
24+
else if (((high - low) % 2 == 1) && map[midpoint + 1].first == key) return &(map[midpoint + 1].second);
25+
else if (key < map[midpoint].first) high = midpoint;
26+
else /*if (key > map[midpoint].first)*/ low = midpoint + 1;
27+
}
28+
if (map[low].first == key) return &(map[low].second);
29+
return nullptr;
30+
}
31+
1932
winrt::Windows::Foundation::IInspectable XamlMetadata::Create(const std::string_view& typeName) const {
2033
wchar_t buf[128]{};
2134
for (auto i = 0u; i < typeName.size() && i < ARRAYSIZE(buf) - 1; i++) {
@@ -31,15 +44,19 @@ winrt::Windows::Foundation::IInspectable XamlMetadata::Create(const std::string_
3144
WindowsDeleteString(clsid);
3245
return unk.as<winrt::IInspectable>();
3346
} else {
34-
// type probably has a custom activation factory, use C++/WinRT to create it
35-
WindowsDeleteString(clsid);
36-
clsid = nullptr;
37-
const auto key = COMPILE_TIME_CRC32_STR(typeName.data());
38-
switch (key) {
39-
<# foreach (var t in Types.Where(t => Util.GetComposableFactoryType(t) != null)) { #>
40-
case COMPILE_TIME_CRC32_STR("<#= t.GetFullName() #>"): { return <#= Util.GetCppWinRTType(t) #>(); }
47+
// type probably has a custom activation factory, use C++/WinRT to create it
48+
WindowsDeleteString(clsid);
49+
clsid = nullptr;
50+
const auto key = COMPILE_TIME_CRC32_STR(typeName.data());
51+
const std::pair<uint32_t, winrt::Windows::Foundation::IInspectable(*)()> map[] = {
52+
<# foreach (var t in Types.Where(t => Util.GetComposableFactoryType(t) != null).OrderBy(t => Util.GetCRC32(t.GetFullName()))) { #>
53+
{ COMPILE_TIME_CRC32_STR("<#= t.GetFullName() #>"), []() -> winrt::Windows::Foundation::IInspectable { return <#= Util.GetCppWinRTType(t) #>(); } }, // 0x<#= Util.GetCRC32(t.GetFullName()).ToString("X8") #>
4154
<# } #>
42-
}
55+
};
56+
57+
if (const auto it = binary_search_map(map, 0, std::size(map), key)) {
58+
return (* it)();
59+
}
4360
}
4461
}
4562
assert(false && "xaml type not found");

package/Codegen/Util.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,16 @@ public static string GetEventArgsMethodArgs(MrType argType, string methodName)
643643
return paramTypes;
644644
}
645645

646+
public static UInt32 GetCRC32(string input)
647+
{
648+
var crc32 = 5381u;
649+
for (int i = input.Length - 1; i >=0; i--)
650+
{
651+
crc32 = 33 * crc32 + input[i];
652+
}
653+
return crc32;
654+
}
655+
646656
public static string GetEventArgsMethodReturnType(MrType argType, string methodName)
647657
{
648658
argType.GetMethodsAndConstructors(out var methods, out var ctors);

0 commit comments

Comments
 (0)