Global Metrics
path: .metrics.nom.closures
old: 0.0
new: 12.0
path: .metrics.nom.total
old: 24.0
new: 36.0
path: .metrics.halstead.vocabulary
old: 312.0
new: 753.0
path: .metrics.halstead.length
old: 1428.0
new: 6466.0
path: .metrics.halstead.volume
old: 11831.554368535291
new: 61792.368149508686
path: .metrics.halstead.bugs
old: 1.4793798826961218
new: 10.020023904688337
path: .metrics.halstead.purity_ratio
old: 1.7273077361568678
new: 1.0748837177224864
path: .metrics.halstead.N1
old: 800.0
new: 3812.0
path: .metrics.halstead.n2
old: 289.0
new: 708.0
path: .metrics.halstead.level
old: 0.04001661589587372
new: 0.011856317508163778
path: .metrics.halstead.effort
old: 295666.0403099027
new: 5211767.322101569
path: .metrics.halstead.N2
old: 628.0
new: 2654.0
path: .metrics.halstead.estimated_program_length
old: 2466.5954472320072
new: 6950.198118793597
path: .metrics.halstead.time
old: 16425.891128327927
new: 289542.6290056427
path: .metrics.halstead.difficulty
old: 24.98961937716263
new: 84.34322033898304
path: .metrics.halstead.n1
old: 23.0
new: 45.0
path: .metrics.cyclomatic.sum
old: 36.0
new: 232.0
path: .metrics.cyclomatic.average
old: 1.2413793103448276
new: 8.285714285714286
path: .metrics.nexits.sum
old: 18.0
new: 89.0
path: .metrics.nexits.average
old: 0.75
new: 2.4722222222222223
path: .metrics.loc.blank
old: 92.0
new: 203.0
path: .metrics.loc.cloc
old: 86.0
new: 116.0
path: .metrics.loc.ploc
old: 312.0
new: 1229.0
path: .metrics.loc.sloc
old: 490.0
new: 1548.0
path: .metrics.loc.lloc
old: 50.0
new: 502.0
path: .metrics.cognitive.sum
old: 6.0
new: 260.0
path: .metrics.cognitive.average
old: 0.25
new: 7.222222222222222
path: .metrics.mi.mi_original
old: 13.602300893813222
new: -58.70843142131106
path: .metrics.mi.mi_sei
old: -22.191143170127805
new: -116.20282499414296
path: .metrics.mi.mi_visual_studio
old: 7.954561926206562
new: 0.0
path: .metrics.nargs.sum
old: 48.0
new: 39.0
path: .metrics.nargs.average
old: 2.0
new: 1.0833333333333333
Spaces Data
Minimal test - lines (108, 153)
path: .spaces[1].metrics.nargs.sum
old: 15.0
new: 3.0
path: .spaces[1].metrics.cognitive.average
old: 0.0
new: 14.0
path: .spaces[1].metrics.cognitive.sum
old: 0.0
new: 14.0
path: .spaces[1].metrics.mi.mi_original
old: 44.13672315598086
new: 69.07027766109776
path: .spaces[1].metrics.mi.mi_sei
old: 22.714564746670128
new: 49.610087688997254
path: .spaces[1].metrics.mi.mi_visual_studio
old: 25.810949214023896
new: 40.39197524040805
path: .spaces[1].metrics.cyclomatic.average
old: 1.3333333333333333
new: 12.0
path: .spaces[1].metrics.cyclomatic.sum
old: 8.0
new: 12.0
path: .spaces[1].metrics.loc.ploc
old: 101.0
new: 40.0
path: .spaces[1].metrics.loc.sloc
old: 164.0
new: 46.0
path: .spaces[1].metrics.loc.blank
old: 25.0
new: 1.0
path: .spaces[1].metrics.loc.cloc
old: 38.0
new: 5.0
path: .spaces[1].metrics.loc.lloc
old: 17.0
new: 24.0
path: .spaces[1].metrics.nom.total
old: 5.0
new: 1.0
path: .spaces[1].metrics.nom.functions
old: 5.0
new: 1.0
path: .spaces[1].metrics.nexits.average
old: 0.2
new: 2.0
path: .spaces[1].metrics.nexits.sum
old: 1.0
new: 2.0
path: .spaces[1].metrics.halstead.vocabulary
old: 127.0
new: 57.0
path: .spaces[1].metrics.halstead.estimated_program_length
old: 812.7907414266465
new: 276.0964047443681
path: .spaces[1].metrics.halstead.difficulty
old: 18.908256880733944
new: 47.36
path: .spaces[1].metrics.halstead.n1
old: 18.0
new: 32.0
path: .spaces[1].metrics.halstead.volume
old: 3480.3649740125384
new: 1265.737133073749
path: .spaces[1].metrics.halstead.n2
old: 109.0
new: 25.0
path: .spaces[1].metrics.halstead.level
old: 0.052886948083454635
new: 0.021114864864864864
path: .spaces[1].metrics.halstead.N2
old: 229.0
new: 74.0
path: .spaces[1].metrics.halstead.time
old: 3655.979720407666
new: 3330.295034576264
path: .spaces[1].metrics.halstead.length
old: 498.0
new: 217.0
path: .spaces[1].metrics.halstead.bugs
old: 0.5433290601490782
new: 0.5105624708171167
path: .spaces[1].metrics.halstead.purity_ratio
old: 1.6321099225434668
new: 1.272333662416443
path: .spaces[1].metrics.halstead.effort
old: 65807.63496733799
new: 59945.31062237275
path: .spaces[1].metrics.halstead.N1
old: 269.0
new: 143.0
Code
static void GetProcessorInformation(int* physical_cpus, int* cache_size_L2,
int* cache_size_L3) {
MOZ_ASSERT(physical_cpus && cache_size_L2 && cache_size_L3);
*physical_cpus = 0;
*cache_size_L2 = 0; // This will be in kbytes
*cache_size_L3 = 0; // This will be in kbytes
// Determine buffer size, allocate and get processor information.
// Size can change between calls (unlikely), so a loop is done.
SYSTEM_LOGICAL_PROCESSOR_INFORMATION info_buffer[32];
SYSTEM_LOGICAL_PROCESSOR_INFORMATION* infos = &info_buffer[0];
DWORD return_length = sizeof(info_buffer);
while (!::GetLogicalProcessorInformation(infos, &return_length)) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
infos == &info_buffer[0]) {
infos = new SYSTEM_LOGICAL_PROCESSOR_INFORMATION
[return_length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)];
} else {
return;
}
}
for (size_t i = 0;
i < return_length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); ++i) {
if (infos[i].Relationship == RelationProcessorCore) {
++*physical_cpus;
} else if (infos[i].Relationship == RelationCache) {
// Only care about L2 and L3 cache
switch (infos[i].Cache.Level) {
case 2:
*cache_size_L2 = static_cast(infos[i].Cache.Size / 1024);
break;
case 3:
*cache_size_L3 = static_cast(infos[i].Cache.Size / 1024);
break;
default:
break;
}
}
}
if (infos != &info_buffer[0]) {
delete[] infos;
}
return;
}
Minimal test - lines (256, 267)
path: .spaces[2].spaces[1].metrics.halstead.volume
old: 8.0
new: 307.19248754831744
path: .spaces[2].spaces[1].metrics.halstead.effort
old: 12.0
new: 3401.0596835706574
path: .spaces[2].spaces[1].metrics.halstead.vocabulary
old: 4.0
new: 24.0
path: .spaces[2].spaces[1].metrics.halstead.purity_ratio
old: 1.188721875540867
new: 1.2913768635474638
path: .spaces[2].spaces[1].metrics.halstead.estimated_program_length
old: 4.754887502163468
new: 86.52224985768008
path: .spaces[2].spaces[1].metrics.halstead.N1
old: 3.0
new: 36.0
path: .spaces[2].spaces[1].metrics.halstead.n2
old: 1.0
new: 14.0
path: .spaces[2].spaces[1].metrics.halstead.N2
old: 1.0
new: 31.0
path: .spaces[2].spaces[1].metrics.halstead.level
old: 0.6666666666666666
new: 0.0903225806451613
path: .spaces[2].spaces[1].metrics.halstead.length
old: 4.0
new: 67.0
path: .spaces[2].spaces[1].metrics.halstead.time
old: 0.6666666666666666
new: 188.94776019836985
path: .spaces[2].spaces[1].metrics.halstead.bugs
old: 0.0017471609294725976
new: 0.07538557425168033
path: .spaces[2].spaces[1].metrics.halstead.difficulty
old: 1.5
new: 11.071428571428571
path: .spaces[2].spaces[1].metrics.halstead.n1
old: 3.0
new: 10.0
path: .spaces[2].spaces[1].metrics.cyclomatic.sum
old: 1.0
new: 3.0
path: .spaces[2].spaces[1].metrics.cyclomatic.average
old: 1.0
new: 3.0
path: .spaces[2].spaces[1].metrics.nexits.sum
old: 0.0
new: 3.0
path: .spaces[2].spaces[1].metrics.nexits.average
old: 0.0
new: 3.0
path: .spaces[2].spaces[1].metrics.loc.ploc
old: 1.0
new: 12.0
path: .spaces[2].spaces[1].metrics.loc.lloc
old: 0.0
new: 6.0
path: .spaces[2].spaces[1].metrics.loc.sloc
old: 1.0
new: 12.0
path: .spaces[2].spaces[1].metrics.cognitive.average
old: 0.0
new: 2.0
path: .spaces[2].spaces[1].metrics.cognitive.sum
old: 0.0
new: 2.0
path: .spaces[2].spaces[1].metrics.nargs.sum
old: 0.0
new: 4.0
path: .spaces[2].spaces[1].metrics.nargs.average
old: 0.0
new: 4.0
path: .spaces[2].spaces[1].metrics.mi.mi_original
old: 159.95690398326485
new: 100.27164463226268
path: .spaces[2].spaces[1].metrics.mi.mi_sei
old: 155.17000000000002
new: 69.26601203894644
path: .spaces[2].spaces[1].metrics.mi.mi_visual_studio
old: 93.54204911302038
new: 58.63838867383783
Code
static nsresult CollectDiskInfo(nsIFile* greDir, nsIFile* winDir,
nsIFile* profDir, DiskInfo& info) {
nsresult rv = GetFolderDiskInfo(greDir, info.binary);
if (NS_FAILED(rv)) {
return rv;
}
rv = GetFolderDiskInfo(winDir, info.system);
if (NS_FAILED(rv)) {
return rv;
}
return GetFolderDiskInfo(profDir, info.profile);
}
Minimal test - lines (383, 405)
path: .spaces[2].spaces[3].metrics.cognitive.average
old: 0.0
new: 3.0
path: .spaces[2].spaces[3].metrics.cognitive.sum
old: 0.0
new: 3.0
path: .spaces[2].spaces[3].metrics.cyclomatic.average
old: 1.0
new: 4.0
path: .spaces[2].spaces[3].metrics.cyclomatic.sum
old: 1.0
new: 4.0
path: .spaces[2].spaces[3].metrics.mi.mi_visual_studio
old: 70.54838854584763
new: 50.97813672020155
path: .spaces[2].spaces[3].metrics.mi.mi_original
old: 120.63774441339945
new: 87.17261379154465
path: .spaces[2].spaces[3].metrics.mi.mi_sei
old: 98.44444347663332
new: 77.00817251560392
path: .spaces[2].spaces[3].metrics.loc.ploc
old: 5.0
new: 19.0
path: .spaces[2].spaces[3].metrics.loc.sloc
old: 5.0
new: 23.0
path: .spaces[2].spaces[3].metrics.loc.blank
old: 0.0
new: 1.0
path: .spaces[2].spaces[3].metrics.loc.cloc
old: 0.0
new: 3.0
path: .spaces[2].spaces[3].metrics.loc.lloc
old: 1.0
new: 10.0
path: .spaces[2].spaces[3].metrics.halstead.n2
old: 10.0
new: 23.0
path: .spaces[2].spaces[3].metrics.halstead.difficulty
old: 3.5
new: 11.304347826086955
path: .spaces[2].spaces[3].metrics.halstead.effort
old: 357.6529986094047
new: 5435.164631951092
path: .spaces[2].spaces[3].metrics.halstead.n1
old: 7.0
new: 13.0
path: .spaces[2].spaces[3].metrics.halstead.N1
old: 15.0
new: 53.0
path: .spaces[2].spaces[3].metrics.halstead.estimated_program_length
old: 52.87076540327685
new: 152.14764132514549
path: .spaces[2].spaces[3].metrics.halstead.purity_ratio
old: 2.114830616131074
new: 1.6359961432811343
path: .spaces[2].spaces[3].metrics.halstead.length
old: 25.0
new: 93.0
path: .spaces[2].spaces[3].metrics.halstead.volume
old: 102.18657103125848
new: 480.80302513413505
path: .spaces[2].spaces[3].metrics.halstead.N2
old: 10.0
new: 40.0
path: .spaces[2].spaces[3].metrics.halstead.vocabulary
old: 17.0
new: 36.0
path: .spaces[2].spaces[3].metrics.halstead.time
old: 19.869611033855815
new: 301.95359066394957
path: .spaces[2].spaces[3].metrics.halstead.bugs
old: 0.016795257201959398
new: 0.10304348718180392
path: .spaces[2].spaces[3].metrics.halstead.level
old: 0.2857142857142857
new: 0.08846153846153845
path: .spaces[2].spaces[3].metrics.nexits.average
old: 1.0
new: 4.0
path: .spaces[2].spaces[3].metrics.nexits.sum
old: 1.0
new: 4.0
path: .spaces[2].spaces[3].metrics.nargs.average
old: 5.0
new: 1.0
path: .spaces[2].spaces[3].metrics.nargs.sum
old: 5.0
new: 1.0
Code
nsresult CollectCountryCode(nsAString& aCountryCode) {
GEOID geoid = GetUserGeoID(GEOCLASS_NATION);
if (geoid == GEOID_NOT_AVAILABLE) {
return NS_ERROR_NOT_AVAILABLE;
}
// Get required length
int numChars = GetGeoInfoW(geoid, GEO_ISO2, nullptr, 0, 0);
if (!numChars) {
return NS_ERROR_FAILURE;
}
// Now get the string for real
aCountryCode.SetLength(numChars);
numChars =
GetGeoInfoW(geoid, GEO_ISO2, char16ptr_t(aCountryCode.BeginWriting()),
aCountryCode.Length(), 0);
if (!numChars) {
return NS_ERROR_FAILURE;
}
// numChars includes null terminator
aCountryCode.Truncate(numChars - 1);
return NS_OK;
}
Minimal test - lines (158, 254)
path: .spaces[2].spaces[0].metrics.nexits.sum
old: 0.0
new: 5.0
path: .spaces[2].spaces[0].metrics.nexits.average
old: 0.0
new: 5.0
path: .spaces[2].spaces[0].metrics.loc.blank
old: 1.0
new: 4.0
path: .spaces[2].spaces[0].metrics.loc.ploc
old: 5.0
new: 84.0
path: .spaces[2].spaces[0].metrics.loc.sloc
old: 6.0
new: 97.0
path: .spaces[2].spaces[0].metrics.loc.cloc
old: 0.0
new: 9.0
path: .spaces[2].spaces[0].metrics.loc.lloc
old: 2.0
new: 37.0
path: .spaces[2].spaces[0].metrics.cyclomatic.sum
old: 1.0
new: 14.0
path: .spaces[2].spaces[0].metrics.cyclomatic.average
old: 1.0
new: 14.0
path: .spaces[2].spaces[0].metrics.cognitive.average
old: 0.0
new: 17.0
path: .spaces[2].spaces[0].metrics.cognitive.sum
old: 0.0
new: 17.0
path: .spaces[2].spaces[0].metrics.halstead.N1
old: 17.0
new: 278.0
path: .spaces[2].spaces[0].metrics.halstead.volume
old: 147.1612434150308
new: 2973.2687181189913
path: .spaces[2].spaces[0].metrics.halstead.length
old: 33.0
new: 458.0
path: .spaces[2].spaces[0].metrics.halstead.estimated_program_length
old: 76.63504134881501
new: 510.469900749982
path: .spaces[2].spaces[0].metrics.halstead.N2
old: 16.0
new: 180.0
path: .spaces[2].spaces[0].metrics.halstead.n1
old: 9.0
new: 23.0
path: .spaces[2].spaces[0].metrics.halstead.level
old: 0.18055555555555555
new: 0.0323671497584541
path: .spaces[2].spaces[0].metrics.halstead.vocabulary
old: 22.0
new: 90.0
path: .spaces[2].spaces[0].metrics.halstead.purity_ratio
old: 2.3222739802671213
new: 1.1145631020741966
path: .spaces[2].spaces[0].metrics.halstead.time
old: 45.28038258924025
new: 5103.371680353493
path: .spaces[2].spaces[0].metrics.halstead.bugs
old: 0.029084870903957623
new: 0.6786281672060677
path: .spaces[2].spaces[0].metrics.halstead.difficulty
old: 5.538461538461538
new: 30.895522388059703
path: .spaces[2].spaces[0].metrics.halstead.effort
old: 815.0468866063245
new: 91860.69024636286
path: .spaces[2].spaces[0].metrics.halstead.n2
old: 13.0
new: 67.0
path: .spaces[2].spaces[0].metrics.mi.mi_sei
old: 91.44708689076764
new: 23.59321273585606
path: .spaces[2].spaces[0].metrics.mi.mi_original
old: 115.78754642453409
new: 52.08311268174872
path: .spaces[2].spaces[0].metrics.mi.mi_visual_studio
old: 67.7120154529439
new: 30.457960632601587
path: .spaces[2].spaces[0].metrics.nargs.average
old: 1.0
new: 2.0
path: .spaces[2].spaces[0].metrics.nargs.sum
old: 1.0
new: 2.0
Code
static nsresult GetFolderDiskInfo(nsIFile* file, FolderDiskInfo& info) {
info.model.Truncate();
info.revision.Truncate();
info.isSSD = false;
nsAutoString filePath;
nsresult rv = file->GetPath(filePath);
NS_ENSURE_SUCCESS(rv, rv);
wchar_t volumeMountPoint[MAX_PATH] = {L'\\', L'\\', L'.', L'\\'};
const size_t PREFIX_LEN = 4;
if (!::GetVolumePathNameW(
filePath.get(), volumeMountPoint + PREFIX_LEN,
mozilla::ArrayLength(volumeMountPoint) - PREFIX_LEN)) {
return NS_ERROR_UNEXPECTED;
}
size_t volumeMountPointLen = wcslen(volumeMountPoint);
// Since we would like to open a drive and not a directory, we need to
// remove any trailing backslash. A drive handle is valid for
// DeviceIoControl calls, a directory handle is not.
if (volumeMountPoint[volumeMountPointLen - 1] == L'\\') {
volumeMountPoint[volumeMountPointLen - 1] = L'\0';
}
ScopedHandle handle(::CreateFileW(volumeMountPoint, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
OPEN_EXISTING, 0, nullptr));
if (!handle.IsValid()) {
return NS_ERROR_UNEXPECTED;
}
STORAGE_PROPERTY_QUERY queryParameters = {StorageDeviceProperty,
PropertyStandardQuery};
STORAGE_DEVICE_DESCRIPTOR outputHeader = {sizeof(STORAGE_DEVICE_DESCRIPTOR)};
DWORD bytesRead = 0;
if (!::DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY, &queryParameters,
sizeof(queryParameters), &outputHeader,
sizeof(outputHeader), &bytesRead, nullptr)) {
return NS_ERROR_FAILURE;
}
PSTORAGE_DEVICE_DESCRIPTOR deviceOutput =
(PSTORAGE_DEVICE_DESCRIPTOR)malloc(outputHeader.Size);
if (!::DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY, &queryParameters,
sizeof(queryParameters), deviceOutput,
outputHeader.Size, &bytesRead, nullptr)) {
free(deviceOutput);
return NS_ERROR_FAILURE;
}
queryParameters.PropertyId = StorageDeviceTrimProperty;
bytesRead = 0;
bool isSSD = false;
DEVICE_TRIM_DESCRIPTOR trimDescriptor = {sizeof(DEVICE_TRIM_DESCRIPTOR)};
if (::DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY, &queryParameters,
sizeof(queryParameters), &trimDescriptor,
sizeof(trimDescriptor), &bytesRead, nullptr)) {
if (trimDescriptor.TrimEnabled) {
isSSD = true;
}
}
if (isSSD) {
// Get Seek Penalty
queryParameters.PropertyId = StorageDeviceSeekPenaltyProperty;
bytesRead = 0;
DEVICE_SEEK_PENALTY_DESCRIPTOR seekPenaltyDescriptor = {
sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR)};
if (::DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY,
&queryParameters, sizeof(queryParameters),
&seekPenaltyDescriptor, sizeof(seekPenaltyDescriptor),
&bytesRead, nullptr)) {
// It is possible that the disk has TrimEnabled, but also
// IncursSeekPenalty; In this case, this is an HDD
if (seekPenaltyDescriptor.IncursSeekPenalty) {
isSSD = false;
}
}
}
// Some HDDs are including product ID info in the vendor field. Since PNP
// IDs include vendor info and product ID concatenated together, we'll do
// that here and interpret the result as a unique ID for the HDD model.
if (deviceOutput->VendorIdOffset) {
info.model =
reinterpret_cast(deviceOutput) + deviceOutput->VendorIdOffset;
}
if (deviceOutput->ProductIdOffset) {
info.model +=
reinterpret_cast(deviceOutput) + deviceOutput->ProductIdOffset;
}
info.model.CompressWhitespace();
if (deviceOutput->ProductRevisionOffset) {
info.revision = reinterpret_cast(deviceOutput) +
deviceOutput->ProductRevisionOffset;
info.revision.CompressWhitespace();
}
info.isSSD = isSSD;
free(deviceOutput);
return NS_OK;
}
Minimal test - lines (411, 454)
path: .spaces[3].metrics.halstead.difficulty
old: 10.459090909090907
new: 20.60606060606061
path: .spaces[3].metrics.halstead.time
old: 1597.472587678559
new: 1121.2838223175231
path: .spaces[3].metrics.halstead.vocabulary
old: 123.0
new: 53.0
path: .spaces[3].metrics.halstead.level
old: 0.09561060408518036
new: 0.04852941176470588
path: .spaces[3].metrics.halstead.N1
old: 219.0
new: 103.0
path: .spaces[3].metrics.halstead.n2
old: 110.0
new: 33.0
path: .spaces[3].metrics.halstead.n1
old: 13.0
new: 20.0
path: .spaces[3].metrics.halstead.volume
old: 2749.235744114339
new: 979.474397730307
path: .spaces[3].metrics.halstead.N2
old: 177.0
new: 68.0
path: .spaces[3].metrics.halstead.purity_ratio
old: 2.005190113190775
new: 1.4789682329624338
path: .spaces[3].metrics.halstead.bugs
old: 0.3128595082439908
new: 0.2470988852770693
path: .spaces[3].metrics.halstead.length
old: 396.0
new: 171.0
path: .spaces[3].metrics.halstead.estimated_program_length
old: 794.0552848235468
new: 252.9035678365762
path: .spaces[3].metrics.halstead.effort
old: 28754.506578214063
new: 20183.108801715414
path: .spaces[3].metrics.loc.sloc
old: 126.0
new: 44.0
path: .spaces[3].metrics.loc.lloc
old: 4.0
new: 19.0
path: .spaces[3].metrics.loc.cloc
old: 12.0
new: 1.0
path: .spaces[3].metrics.loc.blank
old: 30.0
new: 8.0
path: .spaces[3].metrics.loc.ploc
old: 84.0
new: 35.0
path: .spaces[3].metrics.mi.mi_original
old: 50.32302625520013
new: 71.81364421602458
path: .spaces[3].metrics.mi.mi_visual_studio
old: 29.42867032467844
new: 41.99628316726584
path: .spaces[3].metrics.mi.mi_sei
old: 20.4133005167154
new: 40.392329485421904
path: .spaces[3].metrics.cyclomatic.average
old: 1.0
new: 9.0
path: .spaces[3].metrics.cyclomatic.sum
old: 5.0
new: 9.0
path: .spaces[3].metrics.nom.functions
old: 4.0
new: 1.0
path: .spaces[3].metrics.nom.total
old: 4.0
new: 1.0
path: .spaces[3].metrics.nargs.sum
old: 0.0
new: 2.0
path: .spaces[3].metrics.nargs.average
old: 0.0
new: 2.0
path: .spaces[3].metrics.cognitive.average
old: 0.0
new: 13.0
path: .spaces[3].metrics.cognitive.sum
old: 0.0
new: 13.0
path: .spaces[3].metrics.nexits.average
old: 1.0
new: 5.0
path: .spaces[3].metrics.nexits.sum
old: 4.0
new: 5.0
Code
static HRESULT EnumWSCProductList(nsAString& aOutput,
NotNull aProdList) {
MOZ_ASSERT(aOutput.IsEmpty());
LONG count;
HRESULT hr = aProdList->get_Count(&count);
if (FAILED(hr)) {
return hr;
}
for (LONG index = 0; index < count; ++index) {
RefPtr product;
hr = aProdList->get_Item(index, getter_AddRefs(product));
if (FAILED(hr)) {
return hr;
}
WSC_SECURITY_PRODUCT_STATE state;
hr = product->get_ProductState(&state);
if (FAILED(hr)) {
return hr;
}
// We only care about products that are active
if (state == WSC_SECURITY_PRODUCT_STATE_OFF ||
state == WSC_SECURITY_PRODUCT_STATE_SNOOZED) {
continue;
}
_bstr_t bName;
hr = product->get_ProductName(bName.GetAddress());
if (FAILED(hr)) {
return hr;
}
if (!aOutput.IsEmpty()) {
aOutput.AppendLiteral(u";");
}
aOutput.Append((wchar_t*)bName, bName.length());
}
return S_OK;
}
Minimal test - lines (269, 381)
path: .spaces[2].spaces[2].metrics.cyclomatic.sum
old: 1.0
new: 14.0
path: .spaces[2].spaces[2].metrics.cyclomatic.average
old: 1.0
new: 14.0
path: .spaces[2].spaces[2].metrics.mi.mi_visual_studio
old: 70.54838854584763
new: 29.686938184331822
path: .spaces[2].spaces[2].metrics.mi.mi_original
old: 120.63774441339945
new: 50.764664295207425
path: .spaces[2].spaces[2].metrics.mi.mi_sei
old: 98.44444347663332
new: 22.200006259191916
path: .spaces[2].spaces[2].metrics.halstead.n1
old: 7.0
new: 21.0
path: .spaces[2].spaces[2].metrics.halstead.difficulty
old: 3.5
new: 22.183098591549296
path: .spaces[2].spaces[2].metrics.halstead.effort
old: 357.6529986094047
new: 52820.178584341906
path: .spaces[2].spaces[2].metrics.halstead.volume
old: 102.18657103125848
new: 2381.1001139608097
path: .spaces[2].spaces[2].metrics.halstead.n2
old: 10.0
new: 71.0
path: .spaces[2].spaces[2].metrics.halstead.estimated_program_length
old: 52.87076540327685
new: 528.8707113631864
path: .spaces[2].spaces[2].metrics.halstead.N1
old: 15.0
new: 215.0
path: .spaces[2].spaces[2].metrics.halstead.N2
old: 10.0
new: 150.0
path: .spaces[2].spaces[2].metrics.halstead.bugs
old: 0.016795257201959398
new: 0.469258327898019
path: .spaces[2].spaces[2].metrics.halstead.level
old: 0.2857142857142857
new: 0.04507936507936508
path: .spaces[2].spaces[2].metrics.halstead.vocabulary
old: 17.0
new: 92.0
path: .spaces[2].spaces[2].metrics.halstead.time
old: 19.869611033855815
new: 2934.4543657967724
path: .spaces[2].spaces[2].metrics.halstead.purity_ratio
old: 2.114830616131074
new: 1.4489608530498257
path: .spaces[2].spaces[2].metrics.halstead.length
old: 25.0
new: 365.0
path: .spaces[2].spaces[2].metrics.nexits.sum
old: 1.0
new: 7.0
path: .spaces[2].spaces[2].metrics.nexits.average
old: 1.0
new: 7.0
path: .spaces[2].spaces[2].metrics.nargs.sum
old: 5.0
new: 1.0
path: .spaces[2].spaces[2].metrics.nargs.average
old: 5.0
new: 1.0
path: .spaces[2].spaces[2].metrics.loc.blank
old: 0.0
new: 26.0
path: .spaces[2].spaces[2].metrics.loc.sloc
old: 5.0
new: 113.0
path: .spaces[2].spaces[2].metrics.loc.ploc
old: 5.0
new: 76.0
path: .spaces[2].spaces[2].metrics.loc.lloc
old: 1.0
new: 24.0
path: .spaces[2].spaces[2].metrics.loc.cloc
old: 0.0
new: 11.0
path: .spaces[2].spaces[2].metrics.cognitive.average
old: 0.0
new: 16.0
path: .spaces[2].spaces[2].metrics.cognitive.sum
old: 0.0
new: 16.0
Code
static nsresult CollectOSInfo(OSInfo& info) {
HKEY installYearHKey;
LONG status = RegOpenKeyExW(
HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0,
KEY_READ | KEY_WOW64_64KEY, &installYearHKey);
if (status != ERROR_SUCCESS) {
return NS_ERROR_UNEXPECTED;
}
nsAutoRegKey installYearKey(installYearHKey);
DWORD type = 0;
time_t raw_time = 0;
DWORD time_size = sizeof(time_t);
status = RegQueryValueExW(installYearHKey, L"InstallDate", nullptr, &type,
(LPBYTE)&raw_time, &time_size);
if (status != ERROR_SUCCESS) {
return NS_ERROR_UNEXPECTED;
}
if (type != REG_DWORD) {
return NS_ERROR_UNEXPECTED;
}
tm time;
if (localtime_s(&time, &raw_time) != 0) {
return NS_ERROR_UNEXPECTED;
}
info.installYear = 1900UL + time.tm_year;
nsAutoServiceHandle scm(
OpenSCManager(nullptr, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT));
if (!scm) {
return NS_ERROR_UNEXPECTED;
}
bool superfetchServiceRunning = false;
// Superfetch was introduced in Windows Vista as a service with the name
// SysMain. The service display name was also renamed to SysMain after Windows
// 10 build 1809.
nsAutoServiceHandle hService(OpenService(scm, L"SysMain", GENERIC_READ));
if (hService) {
SERVICE_STATUS superfetchStatus;
LPSERVICE_STATUS pSuperfetchStatus = &superfetchStatus;
if (!QueryServiceStatus(hService, pSuperfetchStatus)) {
return NS_ERROR_UNEXPECTED;
}
superfetchServiceRunning =
superfetchStatus.dwCurrentState == SERVICE_RUNNING;
}
// If the SysMain (Superfetch) service is available, but not configured using
// the defaults, then it's disabled for our purposes, since it's not going to
// be operating as expected.
bool superfetchUsingDefaultParams = true;
bool prefetchUsingDefaultParams = true;
static const WCHAR prefetchParamsKeyName[] =
L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory "
L"Management\\PrefetchParameters";
static const DWORD SUPERFETCH_DEFAULT_PARAM = 3;
static const DWORD PREFETCH_DEFAULT_PARAM = 3;
HKEY prefetchParamsHKey;
LONG prefetchParamsStatus =
RegOpenKeyExW(HKEY_LOCAL_MACHINE, prefetchParamsKeyName, 0,
KEY_READ | KEY_WOW64_64KEY, &prefetchParamsHKey);
if (prefetchParamsStatus == ERROR_SUCCESS) {
DWORD valueSize = sizeof(DWORD);
DWORD superfetchValue = 0;
nsAutoRegKey prefetchParamsKey(prefetchParamsHKey);
LONG superfetchParamStatus = RegQueryValueExW(
prefetchParamsHKey, L"EnableSuperfetch", nullptr, &type,
reinterpret_cast(&superfetchValue), &valueSize);
// If the EnableSuperfetch registry key doesn't exist, then it's using the
// default configuration.
if (superfetchParamStatus == ERROR_SUCCESS &&
superfetchValue != SUPERFETCH_DEFAULT_PARAM) {
superfetchUsingDefaultParams = false;
}
DWORD prefetchValue = 0;
LONG prefetchParamStatus = RegQueryValueExW(
prefetchParamsHKey, L"EnablePrefetcher", nullptr, &type,
reinterpret_cast(&prefetchValue), &valueSize);
// If the EnablePrefetcher registry key doesn't exist, then we interpret
// that as the Prefetcher being disabled (since Prefetch behaviour when
// the key is not available appears to be undefined).
if (prefetchParamStatus != ERROR_SUCCESS ||
prefetchValue != PREFETCH_DEFAULT_PARAM) {
prefetchUsingDefaultParams = false;
}
}
info.hasSuperfetch = superfetchServiceRunning && superfetchUsingDefaultParams;
info.hasPrefetch = prefetchUsingDefaultParams;
return NS_OK;
}
Minimal test - lines (83, 102)
path: .spaces[0].metrics.mi.mi_sei
old: 57.52690427340841
new: 82.31601521355236
path: .spaces[0].metrics.mi.mi_original
old: 71.06814893953512
new: 89.67762446765975
path: .spaces[0].metrics.mi.mi_visual_studio
old: 41.560321017272
new: 52.44305524424547
path: .spaces[0].metrics.nargs.sum
old: 7.0
new: 2.0
path: .spaces[0].metrics.nargs.average
old: 2.3333333333333335
new: 2.0
path: .spaces[0].metrics.nexits.sum
old: 1.0
new: 0.0
path: .spaces[0].metrics.nexits.average
old: 0.3333333333333333
new: 0.0
path: .spaces[0].metrics.nom.total
old: 3.0
new: 1.0
path: .spaces[0].metrics.nom.functions
old: 3.0
new: 1.0
path: .spaces[0].metrics.cognitive.average
old: 0.0
new: 6.0
path: .spaces[0].metrics.cognitive.sum
old: 0.0
new: 6.0
path: .spaces[0].metrics.halstead.effort
old: 11184.763035777643
new: 6257.4381578504945
path: .spaces[0].metrics.halstead.N2
old: 67.0
new: 37.0
path: .spaces[0].metrics.halstead.bugs
old: 0.16671062136977333
new: 0.1131904507539615
path: .spaces[0].metrics.halstead.estimated_program_length
old: 271.4804827296223
new: 134.01359166423458
path: .spaces[0].metrics.halstead.difficulty
old: 12.5625
new: 13.63157894736842
path: .spaces[0].metrics.halstead.level
old: 0.07960199004975124
new: 0.07335907335907335
path: .spaces[0].metrics.halstead.length
old: 154.0
new: 91.0
path: .spaces[0].metrics.halstead.n1
old: 15.0
new: 14.0
path: .spaces[0].metrics.halstead.n2
old: 40.0
new: 19.0
path: .spaces[0].metrics.halstead.volume
old: 890.3293958827976
new: 459.03986486161926
path: .spaces[0].metrics.halstead.vocabulary
old: 55.0
new: 33.0
path: .spaces[0].metrics.halstead.purity_ratio
old: 1.7628602774650797
new: 1.4726768314751053
path: .spaces[0].metrics.halstead.time
old: 621.3757242098692
new: 347.6354532139164
path: .spaces[0].metrics.halstead.N1
old: 87.0
new: 54.0
path: .spaces[0].metrics.cyclomatic.average
old: 1.0
new: 4.0
path: .spaces[0].metrics.loc.lloc
old: 2.0
new: 6.0
path: .spaces[0].metrics.loc.sloc
old: 51.0
new: 20.0
path: .spaces[0].metrics.loc.blank
old: 9.0
new: 1.0
path: .spaces[0].metrics.loc.cloc
old: 9.0
new: 3.0
path: .spaces[0].metrics.loc.ploc
old: 33.0
new: 16.0
Code
static void SimpleParseKeyValuePairs(
const std::string& aFilename,
std::map& aKeyValuePairs) {
std::ifstream input(aFilename.c_str());
for (std::string line; std::getline(input, line);) {
nsAutoCString key, value;
nsCCharSeparatedTokenizer tokens(nsDependentCString(line.c_str()), ':');
if (tokens.hasMoreTokens()) {
key = tokens.nextToken();
if (tokens.hasMoreTokens()) {
value = tokens.nextToken();
}
// We want the value even if there was just one token, to cover the
// case where we had the key, and the value was blank (seems to be
// a valid scenario some files.)
aKeyValuePairs[key] = value;
}
}
}
Minimal test - lines (157, 407)
path: .spaces[2].metrics.mi.mi_visual_studio
old: 30.82913446425164
new: 15.730621990958085
path: .spaces[2].metrics.mi.mi_sei
old: 15.54022234389272
new: -10.629968506169888
path: .spaces[2].metrics.mi.mi_original
old: 52.7178199338703
new: 26.899363604538323
path: .spaces[2].metrics.nom.total
old: 12.0
new: 4.0
path: .spaces[2].metrics.nom.functions
old: 12.0
new: 4.0
path: .spaces[2].metrics.cognitive.sum
old: 5.0
new: 38.0
path: .spaces[2].metrics.cognitive.average
old: 0.4166666666666667
new: 9.5
path: .spaces[2].metrics.nexits.sum
old: 12.0
new: 19.0
path: .spaces[2].metrics.nexits.average
old: 1.0
new: 4.75
path: .spaces[2].metrics.loc.sloc
old: 97.0
new: 251.0
path: .spaces[2].metrics.loc.blank
old: 18.0
new: 35.0
path: .spaces[2].metrics.loc.ploc
old: 76.0
new: 193.0
path: .spaces[2].metrics.loc.lloc
old: 27.0
new: 77.0
path: .spaces[2].metrics.loc.cloc
old: 3.0
new: 23.0
path: .spaces[2].metrics.halstead.level
old: 0.057971014492753624
new: 0.029541530788413584
path: .spaces[2].metrics.halstead.time
old: 2208.5825221471587
new: 13863.690370890305
path: .spaces[2].metrics.halstead.N1
old: 217.0
new: 583.0
path: .spaces[2].metrics.halstead.difficulty
old: 17.25
new: 33.85064935064935
path: .spaces[2].metrics.halstead.n1
old: 18.0
new: 26.0
path: .spaces[2].metrics.halstead.vocabulary
old: 90.0
new: 180.0
path: .spaces[2].metrics.halstead.n2
old: 72.0
new: 154.0
path: .spaces[2].metrics.halstead.bugs
old: 0.3882720863300512
new: 1.3212337196103938
path: .spaces[2].metrics.halstead.purity_ratio
old: 1.4627978876896002
new: 1.2614802438401251
path: .spaces[2].metrics.halstead.N2
old: 138.0
new: 401.0
path: .spaces[2].metrics.halstead.effort
old: 39754.48539864885
new: 249546.4266760255
path: .spaces[2].metrics.halstead.estimated_program_length
old: 519.293250129808
new: 1241.2965599386832
path: .spaces[2].metrics.halstead.volume
old: 2304.6078491970347
new: 7371.9834467884
path: .spaces[2].metrics.halstead.length
old: 355.0
new: 984.0
path: .spaces[2].metrics.cyclomatic.sum
old: 17.0
new: 36.0
path: .spaces[2].metrics.cyclomatic.average
old: 1.3076923076923077
new: 7.2
path: .spaces[2].metrics.nargs.average
old: 2.1666666666666665
new: 2.0
path: .spaces[2].metrics.nargs.sum
old: 26.0
new: 8.0
Code
namespace {
static nsresult GetFolderDiskInfo(nsIFile* file, FolderDiskInfo& info) {
info.model.Truncate();
info.revision.Truncate();
info.isSSD = false;
nsAutoString filePath;
nsresult rv = file->GetPath(filePath);
NS_ENSURE_SUCCESS(rv, rv);
wchar_t volumeMountPoint[MAX_PATH] = {L'\\', L'\\', L'.', L'\\'};
const size_t PREFIX_LEN = 4;
if (!::GetVolumePathNameW(
filePath.get(), volumeMountPoint + PREFIX_LEN,
mozilla::ArrayLength(volumeMountPoint) - PREFIX_LEN)) {
return NS_ERROR_UNEXPECTED;
}
size_t volumeMountPointLen = wcslen(volumeMountPoint);
// Since we would like to open a drive and not a directory, we need to
// remove any trailing backslash. A drive handle is valid for
// DeviceIoControl calls, a directory handle is not.
if (volumeMountPoint[volumeMountPointLen - 1] == L'\\') {
volumeMountPoint[volumeMountPointLen - 1] = L'\0';
}
ScopedHandle handle(::CreateFileW(volumeMountPoint, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
OPEN_EXISTING, 0, nullptr));
if (!handle.IsValid()) {
return NS_ERROR_UNEXPECTED;
}
STORAGE_PROPERTY_QUERY queryParameters = {StorageDeviceProperty,
PropertyStandardQuery};
STORAGE_DEVICE_DESCRIPTOR outputHeader = {sizeof(STORAGE_DEVICE_DESCRIPTOR)};
DWORD bytesRead = 0;
if (!::DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY, &queryParameters,
sizeof(queryParameters), &outputHeader,
sizeof(outputHeader), &bytesRead, nullptr)) {
return NS_ERROR_FAILURE;
}
PSTORAGE_DEVICE_DESCRIPTOR deviceOutput =
(PSTORAGE_DEVICE_DESCRIPTOR)malloc(outputHeader.Size);
if (!::DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY, &queryParameters,
sizeof(queryParameters), deviceOutput,
outputHeader.Size, &bytesRead, nullptr)) {
free(deviceOutput);
return NS_ERROR_FAILURE;
}
queryParameters.PropertyId = StorageDeviceTrimProperty;
bytesRead = 0;
bool isSSD = false;
DEVICE_TRIM_DESCRIPTOR trimDescriptor = {sizeof(DEVICE_TRIM_DESCRIPTOR)};
if (::DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY, &queryParameters,
sizeof(queryParameters), &trimDescriptor,
sizeof(trimDescriptor), &bytesRead, nullptr)) {
if (trimDescriptor.TrimEnabled) {
isSSD = true;
}
}
if (isSSD) {
// Get Seek Penalty
queryParameters.PropertyId = StorageDeviceSeekPenaltyProperty;
bytesRead = 0;
DEVICE_SEEK_PENALTY_DESCRIPTOR seekPenaltyDescriptor = {
sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR)};
if (::DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY,
&queryParameters, sizeof(queryParameters),
&seekPenaltyDescriptor, sizeof(seekPenaltyDescriptor),
&bytesRead, nullptr)) {
// It is possible that the disk has TrimEnabled, but also
// IncursSeekPenalty; In this case, this is an HDD
if (seekPenaltyDescriptor.IncursSeekPenalty) {
isSSD = false;
}
}
}
// Some HDDs are including product ID info in the vendor field. Since PNP
// IDs include vendor info and product ID concatenated together, we'll do
// that here and interpret the result as a unique ID for the HDD model.
if (deviceOutput->VendorIdOffset) {
info.model =
reinterpret_cast(deviceOutput) + deviceOutput->VendorIdOffset;
}
if (deviceOutput->ProductIdOffset) {
info.model +=
reinterpret_cast(deviceOutput) + deviceOutput->ProductIdOffset;
}
info.model.CompressWhitespace();
if (deviceOutput->ProductRevisionOffset) {
info.revision = reinterpret_cast(deviceOutput) +
deviceOutput->ProductRevisionOffset;
info.revision.CompressWhitespace();
}
info.isSSD = isSSD;
free(deviceOutput);
return NS_OK;
}
static nsresult CollectDiskInfo(nsIFile* greDir, nsIFile* winDir,
nsIFile* profDir, DiskInfo& info) {
nsresult rv = GetFolderDiskInfo(greDir, info.binary);
if (NS_FAILED(rv)) {
return rv;
}
rv = GetFolderDiskInfo(winDir, info.system);
if (NS_FAILED(rv)) {
return rv;
}
return GetFolderDiskInfo(profDir, info.profile);
}
static nsresult CollectOSInfo(OSInfo& info) {
HKEY installYearHKey;
LONG status = RegOpenKeyExW(
HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0,
KEY_READ | KEY_WOW64_64KEY, &installYearHKey);
if (status != ERROR_SUCCESS) {
return NS_ERROR_UNEXPECTED;
}
nsAutoRegKey installYearKey(installYearHKey);
DWORD type = 0;
time_t raw_time = 0;
DWORD time_size = sizeof(time_t);
status = RegQueryValueExW(installYearHKey, L"InstallDate", nullptr, &type,
(LPBYTE)&raw_time, &time_size);
if (status != ERROR_SUCCESS) {
return NS_ERROR_UNEXPECTED;
}
if (type != REG_DWORD) {
return NS_ERROR_UNEXPECTED;
}
tm time;
if (localtime_s(&time, &raw_time) != 0) {
return NS_ERROR_UNEXPECTED;
}
info.installYear = 1900UL + time.tm_year;
nsAutoServiceHandle scm(
OpenSCManager(nullptr, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT));
if (!scm) {
return NS_ERROR_UNEXPECTED;
}
bool superfetchServiceRunning = false;
// Superfetch was introduced in Windows Vista as a service with the name
// SysMain. The service display name was also renamed to SysMain after Windows
// 10 build 1809.
nsAutoServiceHandle hService(OpenService(scm, L"SysMain", GENERIC_READ));
if (hService) {
SERVICE_STATUS superfetchStatus;
LPSERVICE_STATUS pSuperfetchStatus = &superfetchStatus;
if (!QueryServiceStatus(hService, pSuperfetchStatus)) {
return NS_ERROR_UNEXPECTED;
}
superfetchServiceRunning =
superfetchStatus.dwCurrentState == SERVICE_RUNNING;
}
// If the SysMain (Superfetch) service is available, but not configured using
// the defaults, then it's disabled for our purposes, since it's not going to
// be operating as expected.
bool superfetchUsingDefaultParams = true;
bool prefetchUsingDefaultParams = true;
static const WCHAR prefetchParamsKeyName[] =
L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory "
L"Management\\PrefetchParameters";
static const DWORD SUPERFETCH_DEFAULT_PARAM = 3;
static const DWORD PREFETCH_DEFAULT_PARAM = 3;
HKEY prefetchParamsHKey;
LONG prefetchParamsStatus =
RegOpenKeyExW(HKEY_LOCAL_MACHINE, prefetchParamsKeyName, 0,
KEY_READ | KEY_WOW64_64KEY, &prefetchParamsHKey);
if (prefetchParamsStatus == ERROR_SUCCESS) {
DWORD valueSize = sizeof(DWORD);
DWORD superfetchValue = 0;
nsAutoRegKey prefetchParamsKey(prefetchParamsHKey);
LONG superfetchParamStatus = RegQueryValueExW(
prefetchParamsHKey, L"EnableSuperfetch", nullptr, &type,
reinterpret_cast(&superfetchValue), &valueSize);
// If the EnableSuperfetch registry key doesn't exist, then it's using the
// default configuration.
if (superfetchParamStatus == ERROR_SUCCESS &&
superfetchValue != SUPERFETCH_DEFAULT_PARAM) {
superfetchUsingDefaultParams = false;
}
DWORD prefetchValue = 0;
LONG prefetchParamStatus = RegQueryValueExW(
prefetchParamsHKey, L"EnablePrefetcher", nullptr, &type,
reinterpret_cast(&prefetchValue), &valueSize);
// If the EnablePrefetcher registry key doesn't exist, then we interpret
// that as the Prefetcher being disabled (since Prefetch behaviour when
// the key is not available appears to be undefined).
if (prefetchParamStatus != ERROR_SUCCESS ||
prefetchValue != PREFETCH_DEFAULT_PARAM) {
prefetchUsingDefaultParams = false;
}
}
info.hasSuperfetch = superfetchServiceRunning && superfetchUsingDefaultParams;
info.hasPrefetch = prefetchUsingDefaultParams;
return NS_OK;
}
nsresult CollectCountryCode(nsAString& aCountryCode) {
GEOID geoid = GetUserGeoID(GEOCLASS_NATION);
if (geoid == GEOID_NOT_AVAILABLE) {
return NS_ERROR_NOT_AVAILABLE;
}
// Get required length
int numChars = GetGeoInfoW(geoid, GEO_ISO2, nullptr, 0, 0);
if (!numChars) {
return NS_ERROR_FAILURE;
}
// Now get the string for real
aCountryCode.SetLength(numChars);
numChars =
GetGeoInfoW(geoid, GEO_ISO2, char16ptr_t(aCountryCode.BeginWriting()),
aCountryCode.Length(), 0);
if (!numChars) {
return NS_ERROR_FAILURE;
}
// numChars includes null terminator
aCountryCode.Truncate(numChars - 1);
return NS_OK;
}
} // namespace