* Parse a face code into a company manager face. * @param str Face code to parse. * @return Company manager face, or std::nullopt if it could not be parsed. */
| 1488 | * @return Company manager face, or std::nullopt if it could not be parsed. |
| 1489 | */ |
| 1490 | std::optional<CompanyManagerFace> ParseCompanyManagerFaceCode(std::string_view str) |
| 1491 | { |
| 1492 | if (str.empty()) return std::nullopt; |
| 1493 | |
| 1494 | CompanyManagerFace cmf; |
| 1495 | StringConsumer consumer{str}; |
| 1496 | if (consumer.FindChar(':') != StringConsumer::npos) { |
| 1497 | auto label = consumer.ReadUntilChar(':', StringConsumer::SKIP_ONE_SEPARATOR); |
| 1498 | |
| 1499 | /* Read numeric part and ensure it's valid. */ |
| 1500 | auto bits = consumer.TryReadIntegerBase<uint32_t>(10, true); |
| 1501 | if (!bits.has_value() || consumer.AnyBytesLeft()) return std::nullopt; |
| 1502 | |
| 1503 | /* Ensure style label is valid. */ |
| 1504 | auto style = FindCompanyManagerFaceLabel(label); |
| 1505 | if (!style.has_value()) return std::nullopt; |
| 1506 | |
| 1507 | SetCompanyManagerFaceStyle(cmf, *style); |
| 1508 | cmf.bits = *bits; |
| 1509 | } else { |
| 1510 | /* No ':' included, treat as numeric-only. This allows old-style codes to be entered. */ |
| 1511 | auto bits = ParseInteger(str, 10, true); |
| 1512 | if (!bits.has_value()) return std::nullopt; |
| 1513 | |
| 1514 | /* Old codes use bits 0..1 to represent face style. These map directly to the default face styles. */ |
| 1515 | SetCompanyManagerFaceStyle(cmf, GB(*bits, 0, 2)); |
| 1516 | cmf.bits = *bits; |
| 1517 | } |
| 1518 | |
| 1519 | /* Force the face bits to be valid. */ |
| 1520 | FaceVars vars = GetCompanyManagerFaceVars(cmf.style); |
| 1521 | ScaleAllCompanyManagerFaceBits(cmf, vars); |
| 1522 | cmf.bits = MaskCompanyManagerFaceBits(cmf, vars); |
| 1523 | |
| 1524 | return cmf; |
| 1525 | } |
no test coverage detected