* Decodes an encoded string during FormatString. * @param consumer The encoded string. * @param game_script Set if decoding a GameScript-encoded string. This affects how string IDs are handled. * @param builder The string builder to write the string to. */
| 1010 | * @param builder The string builder to write the string to. |
| 1011 | */ |
| 1012 | static void DecodeEncodedString(StringConsumer &consumer, bool game_script, StringBuilder &builder) |
| 1013 | { |
| 1014 | std::vector<StringParameter> sub_args; |
| 1015 | |
| 1016 | StringIndexInTab id(consumer.ReadIntegerBase<uint32_t>(16)); |
| 1017 | if (consumer.AnyBytesLeft() && !consumer.PeekUtf8If(SCC_RECORD_SEPARATOR)) { |
| 1018 | consumer.SkipAll(); |
| 1019 | builder += "(invalid SCC_ENCODED)"; |
| 1020 | return; |
| 1021 | } |
| 1022 | if (game_script && id >= TAB_SIZE_GAMESCRIPT) { |
| 1023 | consumer.SkipAll(); |
| 1024 | builder += "(invalid StringID)"; |
| 1025 | return; |
| 1026 | } |
| 1027 | |
| 1028 | while (consumer.AnyBytesLeft()) { |
| 1029 | consumer.SkipUtf8If(SCC_RECORD_SEPARATOR); |
| 1030 | StringConsumer record(consumer.ReadUntilUtf8(SCC_RECORD_SEPARATOR, StringConsumer::KEEP_SEPARATOR)); |
| 1031 | |
| 1032 | if (!record.AnyBytesLeft()) { |
| 1033 | /* This is an empty parameter. */ |
| 1034 | sub_args.emplace_back(std::monostate{}); |
| 1035 | continue; |
| 1036 | } |
| 1037 | |
| 1038 | /* Get the parameter type. */ |
| 1039 | char32_t parameter_type = record.ReadUtf8(); |
| 1040 | switch (parameter_type) { |
| 1041 | case SCC_ENCODED: { |
| 1042 | uint64_t param = record.ReadIntegerBase<uint64_t>(16); |
| 1043 | if (param >= TAB_SIZE_GAMESCRIPT) { |
| 1044 | builder += "(invalid sub-StringID)"; |
| 1045 | return; |
| 1046 | } |
| 1047 | assert(!record.AnyBytesLeft()); |
| 1048 | param = MakeStringID(TEXT_TAB_GAMESCRIPT_START, StringIndexInTab(param)); |
| 1049 | sub_args.emplace_back(param); |
| 1050 | break; |
| 1051 | } |
| 1052 | |
| 1053 | case SCC_ENCODED_NUMERIC: { |
| 1054 | uint64_t param = record.ReadIntegerBase<uint64_t>(16); |
| 1055 | assert(!record.AnyBytesLeft()); |
| 1056 | sub_args.emplace_back(param); |
| 1057 | break; |
| 1058 | } |
| 1059 | |
| 1060 | case SCC_ENCODED_STRING: { |
| 1061 | sub_args.emplace_back(record.Read(StringConsumer::npos)); |
| 1062 | break; |
| 1063 | } |
| 1064 | |
| 1065 | default: |
| 1066 | /* Unknown parameter, make it blank. */ |
| 1067 | sub_args.emplace_back(std::monostate{}); |
| 1068 | break; |
| 1069 | } |
no test coverage detected