Files
OpenVulkano/openVulkanoCpp/Host/iOS/IosDeviceNameDecoder.hpp
2025-08-16 10:10:10 +02:00

156 lines
6.6 KiB
C++

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "Base/Logger.hpp"
#include "Data/Containers/String.hpp"
#include <fmt/format.h>
#include <c4/format.hpp>
#include <map>
namespace OpenVulkano
{
namespace
{
std::tuple<std::string_view, int, int> SplitAppleModelComponents(std::string_view input)
{
size_t commaPos = input.rfind(',');
// Find the boundary between text and number
size_t numberStart = commaPos - 1;
while (numberStart > 0 && std::isdigit(input[numberStart - 1])) { --numberStart; }
if (numberStart < 1 || commaPos == std::string_view::npos) return { input, -1, -1 };
std::string_view beforeNumber = input.substr(0, numberStart);
std::string_view number = input.substr(numberStart, commaPos - numberStart);
std::string_view afterComma = input.substr(commaPos + 1);
int major = -1, minor = -1;
c4::from_chars(c4::csubstr(number.begin(), number.length()), &major);
c4::from_chars(c4::csubstr(afterComma.begin(), afterComma.length()), &minor);
return { beforeNumber, major, minor };
}
std::string DecodeIPhoneName(int major, int minor)
{
uint32_t number = std::max(major - 1, 1);
std::string suffix;
switch(major)
{
case 1: if (minor == 1) number = 1; else if (minor == 2) { number = 3; suffix = "G"; } break;
case 2: number = 3; suffix = "GS";
case 4: suffix = "s"; //fallthrough
case 3: number = 4; break;
case 6: suffix = "s"; //fallthrough
case 5: number = 5; if(minor > 2) suffix = "c"; break;
case 7: if (minor == 1) suffix = " Plus"; break;
case 8: if (minor == 4) return "iPhone SE";
number = 6; suffix = "s";
if (minor == 2) suffix += " Plus"; break;
case 9: number = 7; if ((minor & 1) == 0) suffix = " Plus"; break;
case 10: if (minor < 3) { number = 8; if (minor == 2) suffix = " Plus"; } else return "iPhone X"; break;
case 11: { switch (minor) {
case 2: return "iPhone XS";
case 8: return "iPhone XR";
case 4: case 6: return "iPhone XS Max";
} break; }
case 12:
if (minor == 8) return "iPhone SE (2nd generation)";
if (minor > 2) suffix = " Pro"; if (minor > 4) suffix += " Max"; break;
case 13:
if (minor == 1) { suffix = " Mini"; break; }
if (minor > 2) suffix = " Pro"; if (minor == 4) suffix += " Max"; break;
case 14: if (minor == 6) return "iPhone SE (3nd generation)";
if (minor == 2) suffix = " Pro"; if (minor == 3) suffix = " Pro Max";
if (minor == 4) suffix = " Mini"; if (minor > 6) number = 14; if (minor == 8) suffix = " Plus";
break;
case 15:
if (minor == 2) suffix = " Pro"; else if (minor == 3) suffix = " Pro Max";
else if (minor > 3) number = 15; if (minor == 5) suffix = " Plus"; break;
case 16: suffix = " Pro"; if (minor == 2) suffix += " Max"; break;
case 17: if (minor == 1) suffix = " Pro"; else if (minor == 2) suffix = " Pro Max"; else if (minor == 4) suffix = " Plus"; break;
case 18: if (minor == 1) suffix = " Pro"; else if (minor == 2) suffix = " Pro Max"; else if (minor == 4) return "iPhone Air";
}
return fmt::format("iPhone {}{}", number, suffix);
}
std::string DecodeIPadName(int major, int minor)
{
std::string type = "unknown";
uint32_t gen = major * 1000 + minor;
std::map<std::pair<int, int>, std::pair<std::string, uint32_t>> options = {
{{1, 1}, {"", 1}}, {{1, 2}, {"", 1}}, {{1, 3}, {"", 1}},
{{2, 1}, {"", 2}}, {{2, 2}, {"", 2}}, {{2, 3}, {"", 2}}, {{2, 4}, {"", 2}},
{{3, 1}, {"", 3}}, {{3, 2}, {"", 3}}, {{3, 3}, {"", 3}},
{{3, 4}, {"", 4}}, {{3, 5}, {"", 4}}, {{3, 6}, {"", 4}},
{{6, 11}, {"", 5}}, {{6, 12}, {"", 5}},
{{7, 5}, {"", 6}}, {{7, 6}, {"", 6}},
{{7, 11}, {"", 7}}, {{7, 12}, {"", 7}},
{{11, 6}, {"", 8}}, {{11, 7}, {"", 8}},
{{12, 1}, {"", 9}}, {{12, 2}, {"", 9}},
{{13, 18}, {"", 10}}, {{13, 19}, {"", 10}},
{{2, 5}, {"Mini", 1}}, {{2, 6}, {"Mini", 1}}, {{2, 7}, {"Mini", 1}},
{{4, 4}, {"Mini", 2}}, {{4, 5}, {"Mini", 2}}, {{4, 6}, {"Mini", 2}},
{{4, 7}, {"Mini", 3}}, {{4, 8}, {"Mini", 3}}, {{4, 9}, {"Mini", 3}},
{{5, 1}, {"Mini", 4}}, {{5, 2}, {"Mini", 4}},
{{11, 1}, {"Mini", 5}}, {{11, 2}, {"Mini", 5}},
{{14, 1}, {"Mini", 6}}, {{14, 2}, {"Mini", 6}},
{{4, 1}, {"Air", 1}}, {{4, 2}, {"Air", 1}}, {{4, 3}, {"Air", 1}},
{{5, 3}, {"Air", 2}}, {{5, 4}, {"Air", 2}},
{{11, 3}, {"Air", 3}}, {{11, 4}, {"Air", 3}},
{{13, 1}, {"Air", 4}}, {{13, 2}, {"Air", 4}},
{{13, 16}, {"Air", 5}}, {{13, 17}, {"Air", 5}},
{{6, 7}, {"Pro 12.9\"", 1}}, {{6, 8}, {"Pro 12.9\"", 1}},
{{7, 1}, {"Pro 12.9\"", 2}}, {{7, 2}, {"Pro 12.9\"", 2}},
{{8, 5}, {"Pro 12.9\"", 3}}, {{8, 6}, {"Pro 12.9\"", 3}}, {{8, 7}, {"Pro 12.9\"", 3}}, {{8, 8}, {"Pro 12.9\"", 3}},
{{8, 11}, {"Pro 12.9\"", 4}}, {{8, 12}, {"Pro 12.9\"", 4}},
{{13, 8}, {"Pro 12.9\"", 5}}, {{13, 9}, {"Pro 12.9\"", 5}}, {{13, 10}, {"Pro 12.9\"", 5}}, {{13, 11}, {"Pro 12.9\"", 5}},
{{14, 5}, {"Pro 12.9\"", 6}}, {{14, 6}, {"Pro 12.9\"", 6}},
{{16, 5}, {"Pro 12.9\"", 7}}, {{16, 6}, {"Pro 12.9\"", 7}},
{{6, 3}, {"Pro 9.7\"", 1}}, {{6, 4}, {"Pro 9.7\"", 1}},
{{7, 3}, {"Pro 10.5\"", 1}}, {{7, 4}, {"Pro 10.5\"", 1}},
{{8, 1}, {"Pro 11\"", 1}}, {{8, 2}, {"Pro 11\"", 1}}, {{8, 3}, {"Pro 11\"", 1}}, {{8, 4}, {"Pro 11\"", 1}},
{{8, 9}, {"Pro 11\"", 2}}, {{8, 10}, {"Pro 11\"", 2}},
{{13, 4}, {"Pro 11\"", 3}}, {{13, 5}, {"Pro 11\"", 3}}, {{13, 6}, {"Pro 11\"", 3}}, {{13, 7}, {"Pro 11\"", 3}},
{{14, 3}, {"Pro 11\"", 4}}, {{14, 4}, {"Pro 11\"", 4}},
{{16, 3}, {"Pro 11\"", 5}}, {{16, 4}, {"Pro 11\"", 5}},
};
auto iter = options.find({major, minor});
if (iter != options.end())
{
type = iter->second.first;
gen = iter->second.second;
}
else
{
spdlog::warn("Could not decode iPad identifier iPad{},{}", major, minor);
}
return fmt::format("iPad {} ({}{} generation)", type, gen, String::GetOrdinal(gen));
}
std::string DecodeModelString(const std::string& model)
{
if (model == "i386" || model == "x86_64") return "Simulator";
auto [type, major, minor] = SplitAppleModelComponents(model);
if (type == "iPhone") return DecodeIPhoneName(major, minor);
else if (type == "iPad") return DecodeIPadName(major, minor);
else if (type == "iPod")
{
if (major == 7) major = 6; else if (major == 9) major = 7;
return fmt::format("iPod touch ({}{} generation)", major, String::GetOrdinal(major));
}
else
{
spdlog::warn("Could not decode identifier {}", model);
}
return "";
}
}
}