From 9872fd5dc8ddb386e4a7990bfa72433cc157382e Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 2 Feb 2024 19:12:32 +0100 Subject: [PATCH] Codechange: add CopyOutDParam variant for StringParameters && --- src/strings.cpp | 21 ++++ src/strings_func.h | 1 + src/strings_internal.h | 233 ---------------------------------------- src/strings_type.h | 235 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 257 insertions(+), 233 deletions(-) diff --git a/src/strings.cpp b/src/strings.cpp index 428f4a5293..8fbfffe5b7 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -186,6 +186,27 @@ void CopyOutDParam(std::vector &backup, size_t num) } } +/** + * Copy parameters into StringParameterBackup for long-term storage. + * @param backup The backup to write to. + * @param params The parameters to back up. + */ +void CopyOutDParam(std::vector &backup, StringParameters &¶ms) +{ + params.SetOffset(0); + + backup.resize(params.GetDataLeft()); + + for (size_t i = 0; i < params.GetDataLeft(); i++) { + const char *str = params.GetParamStr(i); + if (str != nullptr) { + backup[i] = str; + } else { + backup[i] = params.GetParam(i); + } + } +} + /** * Checks whether the global string parameters have changed compared to the given backup. * @param backup The backup to check against. diff --git a/src/strings_func.h b/src/strings_func.h index 21a77705d8..4cc208b991 100644 --- a/src/strings_func.h +++ b/src/strings_func.h @@ -100,6 +100,7 @@ void SetDParamStr(size_t n, std::string &&str); void CopyInDParam(const std::span backup); void CopyOutDParam(std::vector &backup, size_t num); +void CopyOutDParam(std::vector &backup, class StringParameters &¶ms); bool HaveDParamChanged(const std::vector &backup); uint64_t GetDParam(size_t n); diff --git a/src/strings_internal.h b/src/strings_internal.h index fc28c34716..0ebbe2e59b 100644 --- a/src/strings_internal.h +++ b/src/strings_internal.h @@ -13,239 +13,6 @@ #include "strings_func.h" #include "string_func.h" -/** 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. - std::unique_ptr string; ///< Copied string value, if it has any. - char32_t type; ///< The #StringControlCode to interpret this data with when it's the first parameter, otherwise '\0'. -}; - -class StringParameters { -protected: - StringParameters *parent = nullptr; ///< If not nullptr, this instance references data from this parent instance. - std::span parameters = {}; ///< Array with the actual parameters. - - size_t offset = 0; ///< Current offset in the parameters span. - char32_t next_type = 0; ///< The type of the next data that is retrieved. - - StringParameters(std::span parameters = {}) : - parameters(parameters) - {} - - StringParameter *GetNextParameterPointer(); - -public: - /** - * Create a new StringParameters instance that can reference part of the data of - * the given parent instance. - */ - StringParameters(StringParameters &parent, size_t size) : - parent(&parent), - parameters(parent.parameters.subspan(parent.offset, size)) - {} - - void PrepareForNextRun(); - void SetTypeOfNextParameter(char32_t type) { this->next_type = type; } - - /** - * Get the current offset, so it can be backed up for certain processing - * steps, or be used to offset the argument index within sub strings. - * @return The current offset. - */ - size_t GetOffset() { return this->offset; } - - /** - * Set the offset within the string from where to return the next result of - * \c GetInt64 or \c GetInt32. - * @param offset The offset. - */ - void SetOffset(size_t offset) - { - /* - * The offset must be fewer than the number of parameters when it is - * being set. Unless restoring a backup, then the original value is - * correct as well as long as the offset was not changed. In other - * words, when the offset was already at the end of the parameters and - * the string did not consume any parameters. - */ - assert(offset < this->parameters.size() || this->offset == offset); - this->offset = offset; - } - - /** - * Advance the offset within the string from where to return the next result of - * \c GetInt64 or \c GetInt32. - * @param advance The amount to advance the offset by. - */ - void AdvanceOffset(size_t advance) - { - this->offset += advance; - assert(this->offset <= this->parameters.size()); - } - - /** - * Get the next 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. - */ - template - T GetNextParameter() - { - auto ptr = GetNextParameterPointer(); - return static_cast(ptr->data); - } - - /** - * 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->string != nullptr ? ptr->string->c_str() : 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. - * - * The returned StringParameters must not outlive this StringParameters. - * @return A "range" of the string parameters. - */ - StringParameters GetRemainingParameters() { return GetRemainingParameters(this->offset); } - - /** - * Get a new instance of StringParameters that is a "range" into the - * remaining existing parameters from the given offset. Upon destruction the - * offset in the parent is not updated. However, calls to SetDParam do - * update the parameters. - * - * The returned StringParameters must not outlive this StringParameters. - * @param offset The offset to get the remaining parameters for. - * @return A "range" of the string parameters. - */ - StringParameters GetRemainingParameters(size_t offset) - { - return StringParameters(this->parameters.subspan(offset, this->parameters.size() - offset)); - } - - /** Return the amount of elements which can still be read. */ - size_t GetDataLeft() const - { - return this->parameters.size() - this->offset; - } - - /** Get the type of a specific element. */ - char32_t GetTypeAtOffset(size_t offset) const - { - assert(offset < this->parameters.size()); - return this->parameters[offset].type; - } - - void SetParam(size_t n, uint64_t v) - { - assert(n < this->parameters.size()); - this->parameters[n].data = v; - this->parameters[n].string.reset(); - this->parameters[n].string_view = nullptr; - } - - template ::value, int> = 0> - void SetParam(size_t n, T v) - { - SetParam(n, v.base()); - } - - void SetParam(size_t n, const char *str) - { - assert(n < this->parameters.size()); - this->parameters[n].data = 0; - this->parameters[n].string.reset(); - 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) - { - assert(n < this->parameters.size()); - this->parameters[n].data = 0; - this->parameters[n].string = std::make_unique(std::move(str)); - this->parameters[n].string_view = nullptr; - } - - uint64_t GetParam(size_t n) const - { - assert(n < this->parameters.size()); - assert(this->parameters[n].string_view == nullptr && this->parameters[n].string == 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()); - auto ¶m = this->parameters[n]; - return param.string != nullptr ? param.string->c_str() : param.string_view; - } -}; - -/** - * Extension of StringParameters with its own statically sized buffer for - * the parameters. - */ -template -class ArrayStringParameters : public StringParameters { - std::array params{}; ///< The actual parameters - -public: - ArrayStringParameters() - { - this->parameters = std::span(params.data(), params.size()); - } - - ArrayStringParameters(ArrayStringParameters&& other) noexcept - { - *this = std::move(other); - } - - ArrayStringParameters& operator=(ArrayStringParameters &&other) noexcept - { - this->offset = other.offset; - this->next_type = other.next_type; - this->params = std::move(other.params); - this->parameters = std::span(params.data(), params.size()); - return *this; - } - - ArrayStringParameters(const ArrayStringParameters &other) = delete; - ArrayStringParameters& operator=(const ArrayStringParameters &other) = delete; -}; - -/** - * Helper to create the StringParameters with its own buffer with the given - * parameter values. - * @param args The parameters to set for the to be created StringParameters. - * @return The constructed StringParameters. - */ -template -static auto MakeParameters(const Args&... args) -{ - ArrayStringParameters parameters; - size_t index = 0; - (parameters.SetParam(index++, std::forward(args)), ...); - return parameters; -} - /** * Equivalent to the std::back_insert_iterator in function, with some * convenience helpers for string concatenation. diff --git a/src/strings_type.h b/src/strings_type.h index 5e6d715b63..76cc294aab 100644 --- a/src/strings_type.h +++ b/src/strings_type.h @@ -10,6 +10,8 @@ #ifndef STRINGS_TYPE_H #define STRINGS_TYPE_H +#include "core/strong_typedef_type.hpp" + /** * Numeric value that represents a string, independent of the selected language. */ @@ -118,4 +120,237 @@ struct StringParameterBackup { } }; +/** 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. + std::unique_ptr string; ///< Copied string value, if it has any. + char32_t type; ///< The #StringControlCode to interpret this data with when it's the first parameter, otherwise '\0'. +}; + +class StringParameters { +protected: + StringParameters *parent = nullptr; ///< If not nullptr, this instance references data from this parent instance. + std::span parameters = {}; ///< Array with the actual parameters. + + size_t offset = 0; ///< Current offset in the parameters span. + char32_t next_type = 0; ///< The type of the next data that is retrieved. + + StringParameters(std::span parameters = {}) : + parameters(parameters) + {} + + StringParameter *GetNextParameterPointer(); + +public: + /** + * Create a new StringParameters instance that can reference part of the data of + * the given parent instance. + */ + StringParameters(StringParameters &parent, size_t size) : + parent(&parent), + parameters(parent.parameters.subspan(parent.offset, size)) + {} + + void PrepareForNextRun(); + void SetTypeOfNextParameter(char32_t type) { this->next_type = type; } + + /** + * Get the current offset, so it can be backed up for certain processing + * steps, or be used to offset the argument index within sub strings. + * @return The current offset. + */ + size_t GetOffset() { return this->offset; } + + /** + * Set the offset within the string from where to return the next result of + * \c GetInt64 or \c GetInt32. + * @param offset The offset. + */ + void SetOffset(size_t offset) + { + /* + * The offset must be fewer than the number of parameters when it is + * being set. Unless restoring a backup, then the original value is + * correct as well as long as the offset was not changed. In other + * words, when the offset was already at the end of the parameters and + * the string did not consume any parameters. + */ + assert(offset < this->parameters.size() || this->offset == offset); + this->offset = offset; + } + + /** + * Advance the offset within the string from where to return the next result of + * \c GetInt64 or \c GetInt32. + * @param advance The amount to advance the offset by. + */ + void AdvanceOffset(size_t advance) + { + this->offset += advance; + assert(this->offset <= this->parameters.size()); + } + + /** + * Get the next 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. + */ + template + T GetNextParameter() + { + auto ptr = GetNextParameterPointer(); + return static_cast(ptr->data); + } + + /** + * 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->string != nullptr ? ptr->string->c_str() : 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. + * + * The returned StringParameters must not outlive this StringParameters. + * @return A "range" of the string parameters. + */ + StringParameters GetRemainingParameters() { return GetRemainingParameters(this->offset); } + + /** + * Get a new instance of StringParameters that is a "range" into the + * remaining existing parameters from the given offset. Upon destruction the + * offset in the parent is not updated. However, calls to SetDParam do + * update the parameters. + * + * The returned StringParameters must not outlive this StringParameters. + * @param offset The offset to get the remaining parameters for. + * @return A "range" of the string parameters. + */ + StringParameters GetRemainingParameters(size_t offset) + { + return StringParameters(this->parameters.subspan(offset, this->parameters.size() - offset)); + } + + /** Return the amount of elements which can still be read. */ + size_t GetDataLeft() const + { + return this->parameters.size() - this->offset; + } + + /** Get the type of a specific element. */ + char32_t GetTypeAtOffset(size_t offset) const + { + assert(offset < this->parameters.size()); + return this->parameters[offset].type; + } + + void SetParam(size_t n, uint64_t v) + { + assert(n < this->parameters.size()); + this->parameters[n].data = v; + this->parameters[n].string.reset(); + this->parameters[n].string_view = nullptr; + } + + template ::value, int> = 0> + void SetParam(size_t n, T v) + { + SetParam(n, v.base()); + } + + void SetParam(size_t n, const char *str) + { + assert(n < this->parameters.size()); + this->parameters[n].data = 0; + this->parameters[n].string.reset(); + 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) + { + assert(n < this->parameters.size()); + this->parameters[n].data = 0; + this->parameters[n].string = std::make_unique(std::move(str)); + this->parameters[n].string_view = nullptr; + } + + uint64_t GetParam(size_t n) const + { + assert(n < this->parameters.size()); + assert(this->parameters[n].string_view == nullptr && this->parameters[n].string == 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()); + auto ¶m = this->parameters[n]; + return param.string != nullptr ? param.string->c_str() : param.string_view; + } +}; + +/** + * Extension of StringParameters with its own statically sized buffer for + * the parameters. + */ +template +class ArrayStringParameters : public StringParameters { + std::array params{}; ///< The actual parameters + +public: + ArrayStringParameters() + { + this->parameters = std::span(params.data(), params.size()); + } + + ArrayStringParameters(ArrayStringParameters&& other) noexcept + { + *this = std::move(other); + } + + ArrayStringParameters& operator=(ArrayStringParameters &&other) noexcept + { + this->offset = other.offset; + this->next_type = other.next_type; + this->params = std::move(other.params); + this->parameters = std::span(params.data(), params.size()); + return *this; + } + + ArrayStringParameters(const ArrayStringParameters &other) = delete; + ArrayStringParameters& operator=(const ArrayStringParameters &other) = delete; +}; + +/** + * Helper to create the StringParameters with its own buffer with the given + * parameter values. + * @param args The parameters to set for the to be created StringParameters. + * @return The constructed StringParameters. + */ +template +static auto MakeParameters(const Args&... args) +{ + ArrayStringParameters parameters; + size_t index = 0; + (parameters.SetParam(index++, std::forward(args)), ...); + return parameters; +} + #endif /* STRINGS_TYPE_H */