Skip to content

Commit 2825868

Browse files
committed
scripts: Support InheritUnitsFrom: [] property
Appends units from one or more unit classes defined in array. Note that the `Units: []` property must still exist, even if empty. The usecase is to mirror/copy the units of another unit class, such as TemperatureDelta inheriting units of Temperature.
1 parent 134e935 commit 2825868

File tree

1 file changed

+152
-111
lines changed

1 file changed

+152
-111
lines changed

UnitsNet/Scripts/GenerateUnits.ps1

Lines changed: 152 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -8,96 +8,6 @@ function ToCamelCase($str)
88
return $str.Substring(0,1).ToLowerInvariant() + $str.Substring(1)
99
}
1010

11-
function GetUnits($unitClass)
12-
{
13-
$units = @();
14-
15-
foreach ($unit in $unitClass.Units)
16-
{
17-
$units += $unit;
18-
$prefixIndex = 0;
19-
foreach ($prefix in $unit.Prefixes)
20-
{
21-
$prefixInfo = switch ($prefix)
22-
{
23-
"Kilo" { "k", "1e3d"; break; }
24-
"Hecto" { "h", "1e2d"; break; }
25-
"Deca" { "da", "1e1d"; break; }
26-
"Deci" { "d", "1e-1d"; break; }
27-
"Centi" { "c", "1e-2d"; break; }
28-
"Milli" { "m", "1e-3d"; break; }
29-
"Micro" { "μ", "1e-6d"; break; }
30-
"Nano" { "n", "1e-9d"; break; }
31-
32-
# Optimization, move less frequently used prefixes to the end
33-
"Pico" { "p", "1e-12d"; break; }
34-
"Femto" { "f", "1e-15d"; break; }
35-
"Atto" { "a", "1e-18d"; break; }
36-
"Zepto" { "z", "1e-21d"; break; }
37-
"Yocto" { "y", "1e-24d"; break; }
38-
39-
"Yotta" { "Y", "1e24d"; break; }
40-
"Zetta" { "Z", "1e21d"; break; }
41-
"Exa" { "E", "1e18d"; break; }
42-
"Peta" { "P", "1e15d"; break; }
43-
"Tera" { "T", "1e12d"; break; }
44-
"Giga" { "G", "1e9d"; break; }
45-
"Mega" { "M", "1e6d"; break; }
46-
47-
# Binary prefixes
48-
"Kibi" { "Ki", "1024d"; break; }
49-
"Mebi" { "Mi", "(1024d * 1024)"; break; }
50-
"Gibi" { "Gi", "(1024d * 1024 * 1024)"; break; }
51-
"Tebi" { "Ti", "(1024d * 1024 * 1024 * 1024)"; break; }
52-
"Pebi" { "Pi", "(1024d * 1024 * 1024 * 1024 * 1024)"; break; }
53-
"Exbi" { "Ei", "(1024d * 1024 * 1024 * 1024 * 1024 * 1024)"; break; }
54-
}
55-
56-
$prefixAbbreviation = $prefixInfo[0];
57-
$prefixFactor = $prefixInfo[1];
58-
59-
$u = New-Object PsObject -Property @{
60-
SingularName=$prefix + $(ToCamelCase $unit.SingularName);
61-
PluralName=$prefix + $(ToCamelCase $unit.PluralName);
62-
FromUnitToBaseFunc="("+$unit.FromUnitToBaseFunc+") * $prefixFactor";
63-
FromBaseToUnitFunc="("+$unit.FromBaseToUnitFunc+") / $prefixFactor";
64-
Localization=$unit.Localization | % {
65-
$abbrev = $prefixAbbreviation + $_.Abbreviations[0];
66-
if ($_.AbbreviationsWithPrefixes) {
67-
$abbrev = $_.AbbreviationsWithPrefixes[$prefixIndex++];
68-
}
69-
70-
New-Object PsObject -Property @{
71-
Culture=$_.Culture;
72-
Abbreviations= $abbrev;
73-
}};
74-
}
75-
76-
$units += $u;
77-
}
78-
}
79-
80-
foreach ($u in $units) {
81-
# Use decimal for internal calculations if base type is not double, such as for long or int.
82-
if ($unitClass.BaseType -ne "double") {
83-
$u.FromUnitToBaseFunc = $u.FromUnitToBaseFunc -replace "m", "d";
84-
$u.FromBaseToUnitFunc = $u.FromBaseToUnitFunc -replace "d", "m";
85-
}
86-
87-
# Convert to/from double for other base types
88-
if ($unitClass.BaseType -eq "decimal") {
89-
$u.FromUnitToBaseFunc = "Convert.ToDecimal($($u.FromUnitToBaseFunc))";
90-
$u.FromBaseToUnitFunc = "Convert.ToDouble($($u.FromBaseToUnitFunc))";
91-
} else {
92-
if ($unitClass.BaseType -eq "long") {
93-
$u.FromUnitToBaseFunc = "Convert.ToInt64($($u.FromUnitToBaseFunc))";
94-
$u.FromBaseToUnitFunc = "Convert.ToDouble($($u.FromBaseToUnitFunc))";
95-
}
96-
}
97-
}
98-
99-
return $units | sort SingularName;
100-
}
10111

10212
function GenerateUnitClass($unitClass, $outDir)
10313
{
@@ -198,6 +108,146 @@ function EnsureDirExists([String] $dirPath) {
198108
}
199109
}
200110

111+
function Set-DefaultValues {
112+
param ([Parameter(Mandatory = $true, ValueFromPipeline=$true)] $unitClass)
113+
PROCESS {
114+
if (!$unitClass.BaseType) {
115+
$unitClass | Add-Member BaseType "double"
116+
}
117+
if ($unitClass.GenerateArithmetic -eq $null) {
118+
$unitClass | Add-Member GenerateArithmetic $true
119+
}
120+
# 'Logarithmic' is optional in the .json file and assumed to be false if not specified
121+
if (!$unitClass.Logarithmic) {
122+
$unitClass | Add-Member Logarithmic $false
123+
}
124+
elseif (!$unitClass.LogarithmicScalingFactor) {
125+
$unitClass | Add-Member LogarithmicScalingFactor 1
126+
}
127+
return $unitClass
128+
}
129+
}
130+
131+
function Set-ConversionFunctions
132+
{
133+
param ([Parameter(Mandatory = $true, ValueFromPipeline=$true)] $unitClass)
134+
PROCESS {
135+
foreach ($u in $unitClass.Units) {
136+
137+
# Use decimal for internal calculations if base type is not double, such as for long or int.
138+
if ($unitClass.BaseType -ne "double") {
139+
$u.FromUnitToBaseFunc = $u.FromUnitToBaseFunc -replace "m", "d"
140+
$u.FromBaseToUnitFunc = $u.FromBaseToUnitFunc -replace "d", "m"
141+
}
142+
143+
# Convert to/from double for other base types
144+
if ($unitClass.BaseType -eq "decimal") {
145+
$u.FromUnitToBaseFunc = "Convert.ToDecimal($($u.FromUnitToBaseFunc))"
146+
$u.FromBaseToUnitFunc = "Convert.ToDouble($($u.FromBaseToUnitFunc))"
147+
} else {
148+
if ($unitClass.BaseType -eq "long") {
149+
$u.FromUnitToBaseFunc = "Convert.ToInt64($($u.FromUnitToBaseFunc))"
150+
$u.FromBaseToUnitFunc = "Convert.ToDouble($($u.FromBaseToUnitFunc))"
151+
}
152+
}
153+
}
154+
return $unitClass
155+
}
156+
}
157+
158+
function Add-PrefixUnits {
159+
param ([Parameter(Mandatory = $true, ValueFromPipeline=$true)] $unitClass)
160+
PROCESS {
161+
$prefixUnits = @()
162+
163+
foreach ($unit in $unitClass.Units)
164+
{
165+
$prefixIndex = 0
166+
foreach ($prefix in $unit.Prefixes)
167+
{
168+
$prefixInfo = switch ($prefix)
169+
{
170+
"Kilo" { "k", "1e3d"; break; }
171+
"Hecto" { "h", "1e2d"; break; }
172+
"Deca" { "da", "1e1d"; break; }
173+
"Deci" { "d", "1e-1d"; break; }
174+
"Centi" { "c", "1e-2d"; break; }
175+
"Milli" { "m", "1e-3d"; break; }
176+
"Micro" { "μ", "1e-6d"; break; }
177+
"Nano" { "n", "1e-9d"; break; }
178+
179+
# Optimization, move less frequently used prefixes to the end
180+
"Pico" { "p", "1e-12d"; break; }
181+
"Femto" { "f", "1e-15d"; break; }
182+
"Atto" { "a", "1e-18d"; break; }
183+
"Zepto" { "z", "1e-21d"; break; }
184+
"Yocto" { "y", "1e-24d"; break; }
185+
186+
"Yotta" { "Y", "1e24d"; break; }
187+
"Zetta" { "Z", "1e21d"; break; }
188+
"Exa" { "E", "1e18d"; break; }
189+
"Peta" { "P", "1e15d"; break; }
190+
"Tera" { "T", "1e12d"; break; }
191+
"Giga" { "G", "1e9d"; break; }
192+
"Mega" { "M", "1e6d"; break; }
193+
194+
# Binary prefixes
195+
"Kibi" { "Ki", "1024d"; break; }
196+
"Mebi" { "Mi", "(1024d * 1024)"; break; }
197+
"Gibi" { "Gi", "(1024d * 1024 * 1024)"; break; }
198+
"Tebi" { "Ti", "(1024d * 1024 * 1024 * 1024)"; break; }
199+
"Pebi" { "Pi", "(1024d * 1024 * 1024 * 1024 * 1024)"; break; }
200+
"Exbi" { "Ei", "(1024d * 1024 * 1024 * 1024 * 1024 * 1024)"; break; }
201+
}
202+
203+
$prefixAbbreviation = $prefixInfo[0]
204+
$prefixFactor = $prefixInfo[1]
205+
206+
$prefixUnit = New-Object PsObject -Property @{
207+
SingularName=$prefix + $(ToCamelCase $unit.SingularName)
208+
PluralName=$prefix + $(ToCamelCase $unit.PluralName)
209+
FromUnitToBaseFunc="("+$unit.FromUnitToBaseFunc+") * $prefixFactor"
210+
FromBaseToUnitFunc="("+$unit.FromBaseToUnitFunc+") / $prefixFactor"
211+
Localization=$unit.Localization | % {
212+
$abbrev = $prefixAbbreviation + $_.Abbreviations[0]
213+
if ($_.AbbreviationsWithPrefixes) {
214+
$abbrev = $_.AbbreviationsWithPrefixes[$prefixIndex++]
215+
}
216+
217+
New-Object PsObject -Property @{
218+
Culture=$_.Culture
219+
Abbreviations= $abbrev
220+
}}
221+
}
222+
223+
# Append prefix unit
224+
$prefixUnits += $prefixUnit
225+
} # foreach prefixes
226+
} # foreach units
227+
228+
$unitClass.Units += $prefixUnits
229+
return $unitClass
230+
}
231+
}
232+
233+
function Set-UnitsOrderedByName {
234+
param ([Parameter(Mandatory = $true, ValueFromPipeline=$true)] $unitClass)
235+
PROCESS {
236+
$unitClass.Units = ($unitClass.Units | sort SingularName)
237+
return $unitClass
238+
}
239+
}
240+
241+
function Add-InheritedUnits($unitClass, $unitClasses) {
242+
243+
foreach ($inheritFromUnitClassName in $unitClass.InheritUnitsFrom) {
244+
$inheritFromUnitClass = $unitClasses | Where { $_.Name -eq $inheritFromUnitClassName } | Select -First 1
245+
$unitClass.Units += $inheritFromUnitClass.Units
246+
247+
Write-Host -NoNewline "(inherit $inheritFromUnitClassName) "
248+
}
249+
}
250+
201251
# Load external generator functions with same name as file
202252
. "$PSScriptRoot/Include-GenerateTemplates.ps1"
203253
. "$PSScriptRoot/Include-GenerateLogarithmicCode.ps1"
@@ -217,37 +267,28 @@ EnsureDirExists ($numberExtensionsDir = "$PSScriptRoot/../GeneratedCode/Extensio
217267
EnsureDirExists ($testsCustomCodeDir = "$PSScriptRoot/../../UnitsNet.Tests/CustomCode")
218268

219269
$templatesDir = "$PSScriptRoot/../UnitDefinitions"
220-
$unitClasses = @();
221-
222270
$pad = 25
223-
get-childitem -path $templatesDir -filter "*.json" | % {
224-
$templateFile = $_.FullName
225-
$json = (Get-Content $templateFile | Out-String)
226-
$unitClass = $json | ConvertFrom-Json
227-
228-
# Set default values
229-
if (!$unitClass.BaseType) {
230-
$unitClass | Add-Member BaseType "double";
231-
}
232-
# 'Logarithmic' is optional in the .json file and assumed to be false if not specified
233-
if (!$unitClass.Logarithmic) {
234-
$unitClass | Add-Member Logarithmic "False"
235-
}
236-
elseif (!$unitClass.LogarithmicScalingFactor) {
237-
$unitClass | Add-Member LogarithmicScalingFactor "1"
238-
}
239271

240-
# Expand unit prefixes into units
241-
$unitClass.Units = GetUnits $unitClass;
272+
# Parse unit definitions from .json files and populate properties
273+
$unitClasses = Get-ChildItem -Path $templatesDir -filter "*.json" `
274+
| %{(Get-Content $_.FullName | Out-String)} `
275+
| ConvertFrom-Json `
276+
| Add-PrefixUnits `
277+
| Set-DefaultValues `
278+
| Set-ConversionFunctions `
279+
| Set-UnitsOrderedByName
242280

281+
foreach ($unitClass in $unitClasses) {
243282
Write-Host -NoNewline "$($unitClass.Name):".PadRight($pad)
283+
284+
Add-InheritedUnits $unitClass $unitClasses
285+
244286
GenerateUnitClass $unitClass $unitClassDir
245287
GenerateUnitEnum $unitClass $unitEnumDir
246288
GenerateNumberExtensions $unitClass $numberExtensionsDir
247289
GenerateUnitTestBaseClass $unitClass $testsDir
248290
GenerateUnitTestClassIfNotExists $unitClass $testsCustomCodeDir
249291

250-
$unitClasses += $unitClass;
251292
Write-Host ""
252293
}
253294

0 commit comments

Comments
 (0)