diff --git a/src/strings.cpp b/src/strings.cpp --- a/src/strings.cpp +++ b/src/strings.cpp @@ -178,7 +178,12 @@ void CopyOutDParam(std::vector &backup, size_t num, StringID string) { - /* Just get the string to extract the type information. */ - GetString(string); - - backup.resize(num); - for (size_t i = 0; i < backup.size(); i++) { - if (_global_string_params.GetTypeAtOffset(i) == SCC_RAW_STRING_POINTER) { - backup[i] = (const char *)(size_t)_global_string_params.GetParam(i); - } else { - backup[i] = _global_string_params.GetParam(i); - } - } + CopyOutDParam(backup, num); } /** @@ -1124,7 +1119,7 @@ static void FormatString(StringBuilder & break; case SCC_RAW_STRING_POINTER: { // {RAW_STRING} - const char *raw_string = (const char *)(size_t)args.GetNextParameter(); + const char *raw_string = args.GetNextParameterString(); /* raw_string can be(come) nullptr when the parameter is out of range and 0 is returned instead. */ if (raw_string == nullptr || (game_script && std::find(_game_script_raw_strings.begin(), _game_script_raw_strings.end(), raw_string) == _game_script_raw_strings.end())) { diff --git a/src/strings_internal.h b/src/strings_internal.h --- a/src/strings_internal.h +++ b/src/strings_internal.h @@ -17,6 +17,7 @@ /** The data required to format and validate a single parameter of a string. */ struct StringParameter { uint64_t data; ///< The data of the parameter. + const char *string_view; ///< The string value, if it has any. WChar type; ///< The #StringControlCode to interpret this data with when it's the first parameter, otherwise '\0'. }; @@ -93,6 +94,18 @@ public: } /** + * Get the next string parameter from our parameters. + * This updates the offset, so the next time this is called the next parameter + * will be read. + * @return The next parameter's value. + */ + const char *GetNextParameterString() + { + auto ptr = GetNextParameterPointer(); + return ptr == nullptr ? nullptr : ptr->string_view; + } + + /** * Get a new instance of StringParameters that is a "range" into the * remaining existing parameters. Upon destruction the offset in the parent * is not updated. However, calls to SetDParam do update the parameters. @@ -134,17 +147,36 @@ public: { assert(n < this->parameters.size()); this->parameters[n].data = v; + this->parameters[n].string_view = nullptr; } - void SetParam(size_t n, const char *str) { this->SetParam(n, (uint64_t)(size_t)str); } + void SetParam(size_t n, const char *str) + { + assert(n < this->parameters.size()); + this->parameters[n].data = 0; + this->parameters[n].string_view = str; + } + void SetParam(size_t n, const std::string &str) { this->SetParam(n, str.c_str()); } void SetParam(size_t n, std::string &&str) = delete; // block passing temporaries to SetDParam uint64 GetParam(size_t n) const { assert(n < this->parameters.size()); + assert(this->parameters[n].string_view == nullptr); return this->parameters[n].data; } + + /** + * Get the stored string of the parameter, or \c nullptr when there is none. + * @param n The index into the parameters. + * @return The stored string. + */ + const char *GetParamStr(size_t n) const + { + assert(n < this->parameters.size()); + return this->parameters[n].string_view; + } }; /**