Files
@ r28506:4fd07c3f848d
Branch filter:
Location: cpp/openttd-patchpack/source/src/script/api/script_text.hpp
r28506:4fd07c3f848d
5.3 KiB
text/x-c++hdr
Fix: [Script] Improve ScriptText validation (#11721)
The validation is now done in two steps:
- First we get the list of parameters in the same order they used to be in encoded string
- Then we validate the parameter types like FormatString would use them while encoding the string
The validation is now done in two steps:
- First we get the list of parameters in the same order they used to be in encoded string
- Then we validate the parameter types like FormatString would use them while encoding the string
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | /*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file script_text.hpp Everything to handle text which can be translated. */
#ifndef SCRIPT_TEXT_HPP
#define SCRIPT_TEXT_HPP
#include "script_object.hpp"
#include "../../core/alloc_type.hpp"
#include <variant>
/**
* Internal parent object of all Text-like objects.
* @api -all
*/
class Text : public ScriptObject {
public:
/**
* Convert a ScriptText to a normal string.
* @return A string.
* @api -all
*/
virtual std::string GetEncodedText() = 0;
/**
* Convert a #ScriptText into a decoded normal string.
* @return A string.
* @api -all
*/
const std::string GetDecodedText();
};
/**
* Internally used class to create a raw text in a Text object.
* @api -all
*/
class RawText : public Text {
public:
RawText(const std::string &text);
std::string GetEncodedText() override { return this->text; }
private:
const std::string text;
};
/**
* Class that handles all text related functions. You can define a language
* file in lang/english.txt, in the same format as OpenTTD does, including
* tags like {BLACK}, {STRING1} etc. The name given to this string is made
* available to you in ScriptText, for example: ScriptText.STR_NEWS, if your
* english.txt contains: STR_NEWS :{BLACK}Welcome {COMPANY}!
*
* In translation files like lang/dutch.txt you can then translate such
* strings, like: STR_NEWS :{BLACK}Hallo {COMPANY}!
* When the user has the dutch language selected, it will automatically use
* the translated string when available. The fallback language is always
* the english language.
*
* If you use parameters in your strings, you will have to define those
* parameters, for example like this:
* \code local text = ScriptText(ScriptText.STR_NEWS);
* text.AddParam(1); \endcode
* This will set the {COMPANY} to the name of Company 1. Alternatively you
* can directly give those arguments to the ScriptText constructor, like this:
* \code local text = ScriptText(ScriptText.STR_NEWS, 1); \endcode
*
* @api game
*/
class ScriptText : public Text , public ZeroedMemoryAllocator {
public:
static const int SCRIPT_TEXT_MAX_PARAMETERS = 20; ///< The maximum amount of parameters you can give to one object.
#ifndef DOXYGEN_API
/**
* The constructor wrapper from Squirrel.
*/
ScriptText(HSQUIRRELVM vm);
#else
/**
* Generate a text from string. You can set parameters to the instance which
* can be required for the string.
* @param string The string of the text.
* @param ... Optional arguments for this string.
*/
ScriptText(StringID string, ...);
#endif /* DOXYGEN_API */
#ifndef DOXYGEN_API
/**
* Used for .param_N and [] set from Squirrel.
*/
SQInteger _set(HSQUIRRELVM vm);
/**
* Set the parameter.
*/
SQInteger SetParam(HSQUIRRELVM vm);
/**
* Add an parameter
*/
SQInteger AddParam(HSQUIRRELVM vm);
#else
/**
* Set the parameter to a value.
* @param parameter Which parameter to set.
* @param value The value of the parameter. Has to be string, integer or an instance of the class ScriptText.
*/
void SetParam(int parameter, Object value);
/**
* Add a value as parameter (appending it).
* @param value The value of the parameter. Has to be string, integer or an instance of the class ScriptText.
* @return The same object as on which this is called, so you can chain.
*/
ScriptText *AddParam(Object value);
#endif /* DOXYGEN_API */
/**
* @api -all
*/
std::string GetEncodedText() override;
private:
using ScriptTextRef = ScriptObjectRef<ScriptText>;
using StringIDList = std::vector<StringID>;
using Param = std::variant<SQInteger, std::string, ScriptTextRef>;
struct ParamCheck {
StringID owner;
int idx;
Param *param;
ParamCheck(StringID owner, int idx, Param *param) : owner(owner), idx(idx), param(param) {}
};
using ParamList = std::vector<ParamCheck>;
using ParamSpan = std::span<ParamCheck>;
StringID string;
Param param[SCRIPT_TEXT_MAX_PARAMETERS];
int paramc;
/**
* Internal function to recursively fill a list of parameters.
* The parameters are added as _GetEncodedText used to encode them
* before the addition of parameter validation.
* @param params The list of parameters to fill.
*/
void _FillParamList(ParamList ¶ms);
/**
* Internal function for recursive calling this function over multiple
* instances, while writing in the same buffer.
* @param output The output to write the encoded text to.
* @param param_count The number of parameters that are in the string.
* @param seen_ids The list of seen StringID.
*/
void _GetEncodedText(std::back_insert_iterator<std::string> &output, int ¶m_count, StringIDList &seen_ids, ParamSpan args);
/**
* Set a parameter, where the value is the first item on the stack.
*/
SQInteger _SetParam(int k, HSQUIRRELVM vm);
};
#endif /* SCRIPT_TEXT_HPP */
|