Revert IPF string handling optimisations
When reverting this revert (after 1.18 has branched), the new .hpp file should be added to XCode and CodeBlocks. This reverts PR #8396, PR #8407 and the "Small fixup" commit; they bumped the minimum compiler version from GCC 7 to 8 or 11. This reverts commit870eeff8e6
. This reverts commit029136b19a
. This reverts commitd74ff6f31b
. This reverts commit8a6de95d48
. This reverts commitd14d233d79
. This reverts commit698f5c115c
.
This commit is contained in:
parent
e0df67656a
commit
e14d7ddee9
6 changed files with 141 additions and 167 deletions
|
@ -38,7 +38,7 @@ std::vector<std::string> images_general;
|
|||
|
||||
void gather_images(const config& from, std::vector<std::string>& to)
|
||||
{
|
||||
const auto& im = utils::parenthetical_split(from["images"].str(), ',');
|
||||
const auto& im = utils::parenthetical_split(from["images"], ',');
|
||||
to.insert(to.end(), im.begin(), im.end());
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "log.hpp"
|
||||
#include "serialization/string_utils.hpp"
|
||||
#include "team.hpp"
|
||||
#include "utils/from_chars.hpp"
|
||||
|
||||
#include "formula/formula.hpp"
|
||||
#include "formula/callable.hpp"
|
||||
|
@ -38,7 +37,10 @@ namespace image {
|
|||
/** Adds @a mod to the queue (unless mod is nullptr). */
|
||||
void modification_queue::push(std::unique_ptr<modification> mod)
|
||||
{
|
||||
priorities_[mod->priority()].push_back(std::move(mod));
|
||||
// Null pointers do not get stored. (Shouldn't happen, but just in case.)
|
||||
if(mod != nullptr) {
|
||||
priorities_[mod->priority()].push_back(std::move(mod));
|
||||
}
|
||||
}
|
||||
|
||||
/** Removes the top element from the queue */
|
||||
|
@ -76,14 +78,14 @@ modification * modification_queue::top() const
|
|||
namespace {
|
||||
|
||||
/** A function used to parse modification arguments */
|
||||
using mod_parser = std::function<std::unique_ptr<modification>(std::string_view)>;
|
||||
using mod_parser = std::function<std::unique_ptr<modification>(const std::string&)>;
|
||||
|
||||
/** A map of all registered mod parsers
|
||||
*
|
||||
* The mapping is between the modification name and the parser function pointer
|
||||
* An example of an entry would be "TC" -> &parse_TC_mod
|
||||
*/
|
||||
std::map<std::string, mod_parser, std::less<>> mod_parsers;
|
||||
std::map<std::string, mod_parser> mod_parsers;
|
||||
|
||||
/** Decodes a single modification using an appropriate mod_parser
|
||||
*
|
||||
|
@ -94,22 +96,22 @@ std::map<std::string, mod_parser, std::less<>> mod_parsers;
|
|||
*/
|
||||
std::unique_ptr<modification> decode_modification(const std::string& encoded_mod)
|
||||
{
|
||||
const std::vector<std::string> split = utils::parenthetical_split(encoded_mod);
|
||||
std::vector<std::string> split = utils::parenthetical_split(encoded_mod);
|
||||
|
||||
if(split.size() != 2) {
|
||||
ERR_DP << "error parsing image modifications: " << encoded_mod;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::string& mod_type = split[0];
|
||||
const std::string& args = split[1];
|
||||
std::string mod_type = split[0];
|
||||
std::string args = split[1];
|
||||
|
||||
if(const auto parser = mod_parsers.find(mod_type); parser != mod_parsers.end()) {
|
||||
return std::invoke(parser->second, args);
|
||||
} else {
|
||||
if(mod_parsers.find(mod_type) == mod_parsers.end()) {
|
||||
ERR_DP << "unknown image function in path: " << mod_type;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return mod_parsers[mod_type](args);
|
||||
}
|
||||
|
||||
} // end anon namespace
|
||||
|
@ -603,14 +605,14 @@ struct parse_mod_registration
|
|||
* @param args_var The name for the string argument provided
|
||||
*/
|
||||
#define REGISTER_MOD_PARSER(type, args_var) \
|
||||
static std::unique_ptr<modification> parse_##type##_mod(std::string_view); \
|
||||
static std::unique_ptr<modification> parse_##type##_mod(const std::string&); \
|
||||
static parse_mod_registration parse_##type##_mod_registration_aux(#type, &parse_##type##_mod); \
|
||||
static std::unique_ptr<modification> parse_##type##_mod(std::string_view args_var) \
|
||||
static std::unique_ptr<modification> parse_##type##_mod(const std::string& args_var) \
|
||||
|
||||
// Color-range-based recoloring
|
||||
REGISTER_MOD_PARSER(TC, args)
|
||||
{
|
||||
const auto params = utils::split_view(args,',');
|
||||
std::vector<std::string> params = utils::split(args,',');
|
||||
|
||||
if(params.size() < 2) {
|
||||
ERR_DP << "too few arguments passed to the ~TC() function";
|
||||
|
@ -618,9 +620,9 @@ REGISTER_MOD_PARSER(TC, args)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const int side_n = utils::from_chars<int>(params[0]).value_or(-1);
|
||||
const int side_n = lexical_cast_default<int>(params[0], -1);
|
||||
if(side_n < 1) {
|
||||
ERR_DP << "Invalid side (" << params[0] << ") passed to the ~TC() function";
|
||||
ERR_DP << "Invalid side (" << side_n << ") passed to the ~TC() function";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -653,7 +655,7 @@ REGISTER_MOD_PARSER(TC, args)
|
|||
// Team-color-based color range selection and recoloring
|
||||
REGISTER_MOD_PARSER(RC, args)
|
||||
{
|
||||
const auto recolor_params = utils::split_view(args,'>');
|
||||
const std::vector<std::string> recolor_params = utils::split(args,'>');
|
||||
|
||||
if(recolor_params.size() <= 1) {
|
||||
return nullptr;
|
||||
|
@ -682,7 +684,7 @@ REGISTER_MOD_PARSER(RC, args)
|
|||
// Palette switch
|
||||
REGISTER_MOD_PARSER(PAL, args)
|
||||
{
|
||||
const auto remap_params = utils::split_view(args,'>');
|
||||
const std::vector<std::string> remap_params = utils::split(args,'>');
|
||||
|
||||
if(remap_params.size() < 2) {
|
||||
ERR_DP << "not enough arguments passed to the ~PAL() function: " << args;
|
||||
|
@ -723,23 +725,28 @@ REGISTER_MOD_PARSER(FL, args)
|
|||
// Rotations
|
||||
REGISTER_MOD_PARSER(ROTATE, args)
|
||||
{
|
||||
const auto slice_params = utils::split_view(args, ',', utils::STRIP_SPACES);
|
||||
const std::vector<std::string>& slice_params = utils::split(args, ',', utils::STRIP_SPACES);
|
||||
const std::size_t s = slice_params.size();
|
||||
|
||||
switch(slice_params.size()) {
|
||||
switch(s) {
|
||||
case 0:
|
||||
return std::make_unique<rotate_modification>();
|
||||
break;
|
||||
case 1:
|
||||
return std::make_unique<rotate_modification>(
|
||||
utils::from_chars<int>(slice_params[0]).value_or(0));
|
||||
lexical_cast_default<int>(slice_params[0]));
|
||||
break;
|
||||
case 2:
|
||||
return std::make_unique<rotate_modification>(
|
||||
utils::from_chars<int>(slice_params[0]).value_or(0),
|
||||
utils::from_chars<int>(slice_params[1]).value_or(0));
|
||||
lexical_cast_default<int>(slice_params[0]),
|
||||
lexical_cast_default<int>(slice_params[1]));
|
||||
break;
|
||||
case 3:
|
||||
return std::make_unique<rotate_modification>(
|
||||
utils::from_chars<int>(slice_params[0]).value_or(0),
|
||||
utils::from_chars<int>(slice_params[1]).value_or(0),
|
||||
utils::from_chars<int>(slice_params[2]).value_or(0));
|
||||
lexical_cast_default<int>(slice_params[0]),
|
||||
lexical_cast_default<int>(slice_params[1]),
|
||||
lexical_cast_default<int>(slice_params[2]));
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -756,35 +763,28 @@ REGISTER_MOD_PARSER(CROP_TRANSPARENCY, )
|
|||
return std::make_unique<crop_transparency_modification>();
|
||||
}
|
||||
|
||||
// TODO: should this be made a more general util function?
|
||||
bool in_range(int val, int min, int max)
|
||||
{
|
||||
return min <= val && val <= max;
|
||||
}
|
||||
|
||||
// Black and white
|
||||
REGISTER_MOD_PARSER(BW, args)
|
||||
{
|
||||
const auto params = utils::split_view(args, ',');
|
||||
const std::vector<std::string>& params = utils::split(args, ',');
|
||||
|
||||
if(params.size() != 1) {
|
||||
ERR_DP << "~BW() requires exactly one argument";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO: maybe get this directly as uint8_t?
|
||||
const auto threshold = utils::from_chars<int>(params[0]);
|
||||
if(!threshold) {
|
||||
try {
|
||||
int threshold = std::stoi(params[0]);
|
||||
if(threshold < 0 || threshold > 255) {
|
||||
ERR_DP << "~BW() argument out of range 0 - 255";
|
||||
return nullptr;
|
||||
} else {
|
||||
return std::make_unique<bw_modification>(threshold);
|
||||
}
|
||||
} catch (const std::invalid_argument&) {
|
||||
ERR_DP << "unsupported argument in ~BW() function";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(!in_range(*threshold, 0, 255)) {
|
||||
ERR_DP << "~BW() argument out of range 0 - 255";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_unique<bw_modification>(*threshold);
|
||||
}
|
||||
|
||||
// Sepia
|
||||
|
@ -796,42 +796,51 @@ REGISTER_MOD_PARSER(SEPIA, )
|
|||
// Negative
|
||||
REGISTER_MOD_PARSER(NEG, args)
|
||||
{
|
||||
const auto params = utils::split_view(args, ',');
|
||||
const std::vector<std::string>& params = utils::split(args, ',');
|
||||
|
||||
switch(params.size()) {
|
||||
case 0:
|
||||
// apparently -1 may be a magic number but this is the threshold
|
||||
// value required to fully invert a channel
|
||||
return std::make_unique<negative_modification>(-1, -1, -1);
|
||||
|
||||
case 1: {
|
||||
const auto threshold = utils::from_chars<int>(params[0]);
|
||||
|
||||
if(threshold && in_range(*threshold, -1, 255)) {
|
||||
return std::make_unique<negative_modification>(*threshold, *threshold, *threshold);
|
||||
} else {
|
||||
ERR_DP << "unsupported argument value in ~NEG() function";
|
||||
switch (params.size()) {
|
||||
case 0:
|
||||
// apparently -1 may be a magic number
|
||||
// but this is the threshold value required
|
||||
// to fully invert a channel
|
||||
return std::make_unique<negative_modification>(-1, -1, -1);
|
||||
break;
|
||||
case 1:
|
||||
try {
|
||||
int threshold = std::stoi(params[0]);
|
||||
if(threshold < -1 || threshold > 255) {
|
||||
ERR_DP << "unsupported argument value in ~NEG() function";
|
||||
return nullptr;
|
||||
} else {
|
||||
return std::make_unique<negative_modification>(threshold, threshold, threshold);
|
||||
}
|
||||
} catch (const std::invalid_argument&) {
|
||||
ERR_DP << "unsupported argument value in ~NEG() function";
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
try {
|
||||
int thresholdRed = std::stoi(params[0]);
|
||||
int thresholdGreen = std::stoi(params[1]);
|
||||
int thresholdBlue = std::stoi(params[2]);
|
||||
if(thresholdRed < -1 || thresholdRed > 255 || thresholdGreen < -1 || thresholdGreen > 255 || thresholdBlue < -1 || thresholdBlue > 255) {
|
||||
ERR_DP << "unsupported argument value in ~NEG() function";
|
||||
return nullptr;
|
||||
} else {
|
||||
return std::make_unique<negative_modification>(thresholdRed, thresholdGreen, thresholdBlue);
|
||||
}
|
||||
} catch (const std::invalid_argument&) {
|
||||
ERR_DP << "unsupported argument value in ~NEG() function";
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERR_DP << "~NEG() requires 0, 1 or 3 arguments";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
case 3: {
|
||||
const auto thR = utils::from_chars<int>(params[0]);
|
||||
const auto thG = utils::from_chars<int>(params[1]);
|
||||
const auto thB = utils::from_chars<int>(params[2]);
|
||||
|
||||
if(thR && thG && thB && in_range(*thR, -1, 255) && in_range(*thG, -1, 255) && in_range(*thB, -1, 255)) {
|
||||
return std::make_unique<negative_modification>(*thR, *thG, *thB);
|
||||
} else {
|
||||
ERR_DP << "unsupported argument value in ~NEG() function";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
ERR_DP << "~NEG() requires 0, 1 or 3 arguments";
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Plot Alpha
|
||||
|
@ -879,7 +888,7 @@ REGISTER_MOD_PARSER(CHAN, args)
|
|||
// Color-shift
|
||||
REGISTER_MOD_PARSER(CS, args)
|
||||
{
|
||||
const auto factors = utils::split_view(args, ',');
|
||||
std::vector<std::string> const factors = utils::split(args, ',');
|
||||
const std::size_t s = factors.size();
|
||||
|
||||
if(s == 0) {
|
||||
|
@ -889,13 +898,13 @@ REGISTER_MOD_PARSER(CS, args)
|
|||
|
||||
int r = 0, g = 0, b = 0;
|
||||
|
||||
r = utils::from_chars<int>(factors[0]).value_or(0);
|
||||
r = lexical_cast_default<int>(factors[0]);
|
||||
|
||||
if(s > 1 ) {
|
||||
g = utils::from_chars<int>(factors[0]).value_or(0);
|
||||
g = lexical_cast_default<int>(factors[1]);
|
||||
}
|
||||
if(s > 2 ) {
|
||||
b = utils::from_chars<int>(factors[0]).value_or(0);
|
||||
b = lexical_cast_default<int>(factors[2]);
|
||||
}
|
||||
|
||||
return std::make_unique<cs_modification>(r, g , b);
|
||||
|
@ -904,7 +913,7 @@ REGISTER_MOD_PARSER(CS, args)
|
|||
// Color blending
|
||||
REGISTER_MOD_PARSER(BLEND, args)
|
||||
{
|
||||
const auto params = utils::split_view(args, ',');
|
||||
const std::vector<std::string>& params = utils::split(args, ',');
|
||||
|
||||
if(params.size() != 4) {
|
||||
ERR_DP << "~BLEND() requires exactly 4 arguments";
|
||||
|
@ -912,29 +921,29 @@ REGISTER_MOD_PARSER(BLEND, args)
|
|||
}
|
||||
|
||||
float opacity = 0.0f;
|
||||
const std::string_view& opacity_str = params[3];
|
||||
const std::string_view::size_type p100_pos = opacity_str.find('%');
|
||||
const std::string& opacity_str = params[3];
|
||||
const std::string::size_type p100_pos = opacity_str.find('%');
|
||||
|
||||
if(p100_pos == std::string::npos)
|
||||
opacity = lexical_cast_default<float>(opacity_str);
|
||||
else {
|
||||
// make multiplier
|
||||
const std::string_view parsed_field = opacity_str.substr(0, p100_pos);
|
||||
const std::string& parsed_field = opacity_str.substr(0, p100_pos);
|
||||
opacity = lexical_cast_default<float>(parsed_field);
|
||||
opacity /= 100.0f;
|
||||
}
|
||||
|
||||
return std::make_unique<blend_modification>(
|
||||
utils::from_chars<int>(params[0]).value_or(0),
|
||||
utils::from_chars<int>(params[1]).value_or(0),
|
||||
utils::from_chars<int>(params[2]).value_or(0),
|
||||
lexical_cast_default<int>(params[0]),
|
||||
lexical_cast_default<int>(params[1]),
|
||||
lexical_cast_default<int>(params[2]),
|
||||
opacity);
|
||||
}
|
||||
|
||||
// Crop/slice
|
||||
REGISTER_MOD_PARSER(CROP, args)
|
||||
{
|
||||
const auto slice_params = utils::split_view(args, ',', utils::STRIP_SPACES);
|
||||
const std::vector<std::string>& slice_params = utils::split(args, ',', utils::STRIP_SPACES);
|
||||
const std::size_t s = slice_params.size();
|
||||
|
||||
if(s == 0 || (s == 1 && slice_params[0].empty())) {
|
||||
|
@ -944,16 +953,16 @@ REGISTER_MOD_PARSER(CROP, args)
|
|||
|
||||
SDL_Rect slice_rect { 0, 0, 0, 0 };
|
||||
|
||||
slice_rect.x = utils::from_chars<int16_t>(slice_params[0]).value_or(0);
|
||||
slice_rect.x = lexical_cast_default<int16_t, const std::string&>(slice_params[0]);
|
||||
|
||||
if(s > 1) {
|
||||
slice_rect.y = utils::from_chars<int16_t>(slice_params[1]).value_or(0);
|
||||
slice_rect.y = lexical_cast_default<int16_t, const std::string&>(slice_params[1]);
|
||||
}
|
||||
if(s > 2) {
|
||||
slice_rect.w = utils::from_chars<uint16_t>(slice_params[2]).value_or(0);
|
||||
slice_rect.w = lexical_cast_default<uint16_t, const std::string&>(slice_params[2]);
|
||||
}
|
||||
if(s > 3) {
|
||||
slice_rect.h = utils::from_chars<uint16_t>(slice_params[3]).value_or(0);
|
||||
slice_rect.h = lexical_cast_default<uint16_t, const std::string&>(slice_params[3]);
|
||||
}
|
||||
|
||||
return std::make_unique<crop_modification>(slice_rect);
|
||||
|
@ -986,8 +995,8 @@ REGISTER_MOD_PARSER(BLIT, args)
|
|||
int x = 0, y = 0;
|
||||
|
||||
if(s == 3) {
|
||||
x = utils::from_chars<int>(param[1]).value_or(0);
|
||||
y = utils::from_chars<int>(param[2]).value_or(0);
|
||||
x = lexical_cast_default<int>(param[1]);
|
||||
y = lexical_cast_default<int>(param[2]);
|
||||
}
|
||||
|
||||
const image::locator img(param[0]);
|
||||
|
@ -1014,8 +1023,8 @@ REGISTER_MOD_PARSER(MASK, args)
|
|||
int x = 0, y = 0;
|
||||
|
||||
if(s == 3) {
|
||||
x = utils::from_chars<int>(param[1]).value_or(0);
|
||||
y = utils::from_chars<int>(param[2]).value_or(0);
|
||||
x = lexical_cast_default<int>(param[1]);
|
||||
y = lexical_cast_default<int>(param[2]);
|
||||
}
|
||||
|
||||
if(x < 0 || y < 0) {
|
||||
|
@ -1041,16 +1050,17 @@ REGISTER_MOD_PARSER(L, args)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
surface surf = get_surface(std::string{args}); // FIXME: string_view for image::locator::value
|
||||
surface surf = get_surface(args);
|
||||
|
||||
return std::make_unique<light_modification>(surf);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
/** Common helper function to parse scaling IPF inputs. */
|
||||
std::optional<point> parse_scale_args(std::string_view args)
|
||||
std::optional<point> parse_scale_args(const std::string& args)
|
||||
{
|
||||
const auto scale_params = utils::split_view(args, ',', utils::STRIP_SPACES);
|
||||
const std::vector<std::string>& scale_params = utils::split(args, ',', utils::STRIP_SPACES);
|
||||
const std::size_t s = scale_params.size();
|
||||
|
||||
if(s == 0 || (s == 1 && scale_params[0].empty())) {
|
||||
|
@ -1058,10 +1068,10 @@ std::optional<point> parse_scale_args(std::string_view args)
|
|||
}
|
||||
|
||||
point size{0, 0};
|
||||
size.x = utils::from_chars<int>(scale_params[0]).value_or(0);
|
||||
size.x = lexical_cast_default<int, const std::string&>(scale_params[0]);
|
||||
|
||||
if(s > 1) {
|
||||
size.y = utils::from_chars<int>(scale_params[1]).value_or(0);
|
||||
size.y = lexical_cast_default<int, const std::string&>(scale_params[1]);
|
||||
}
|
||||
|
||||
return size;
|
||||
|
@ -1117,7 +1127,7 @@ REGISTER_MOD_PARSER(SCALE_INTO_SHARP, args)
|
|||
// xBRZ
|
||||
REGISTER_MOD_PARSER(XBRZ, args)
|
||||
{
|
||||
int z = utils::from_chars<int>(args).value_or(0);
|
||||
int z = lexical_cast_default<int, const std::string &>(args);
|
||||
if(z < 1 || z > 5) {
|
||||
z = 5; //only values 2 - 5 are permitted for xbrz scaling factors.
|
||||
}
|
||||
|
@ -1130,7 +1140,7 @@ REGISTER_MOD_PARSER(XBRZ, args)
|
|||
// Gaussian-like blur
|
||||
REGISTER_MOD_PARSER(BL, args)
|
||||
{
|
||||
const int depth = std::max<int>(0, utils::from_chars<int>(args).value_or(0));
|
||||
const int depth = std::max<int>(0, lexical_cast_default<int>(args));
|
||||
return std::make_unique<bl_modification>(depth);
|
||||
}
|
||||
|
||||
|
@ -1140,11 +1150,11 @@ REGISTER_MOD_PARSER(O, args)
|
|||
const std::string::size_type p100_pos = args.find('%');
|
||||
float num = 0.0f;
|
||||
if(p100_pos == std::string::npos) {
|
||||
num = lexical_cast_default<float, std::string_view>(args);
|
||||
num = lexical_cast_default<float,const std::string&>(args);
|
||||
} else {
|
||||
// make multiplier
|
||||
const std::string_view parsed_field = args.substr(0, p100_pos);
|
||||
num = lexical_cast_default<float, std::string_view>(parsed_field);
|
||||
const std::string parsed_field = args.substr(0, p100_pos);
|
||||
num = lexical_cast_default<float,const std::string&>(parsed_field);
|
||||
num /= 100.0f;
|
||||
}
|
||||
|
||||
|
@ -1158,22 +1168,22 @@ REGISTER_MOD_PARSER(O, args)
|
|||
// Red component color-shift
|
||||
REGISTER_MOD_PARSER(R, args)
|
||||
{
|
||||
const int r = utils::from_chars<int>(args).value_or(0);
|
||||
return std::make_unique<cs_modification>(r, 0, 0);
|
||||
const int r = lexical_cast_default<int>(args);
|
||||
return std::make_unique<cs_modification>(r,0,0);
|
||||
}
|
||||
|
||||
// Green component color-shift
|
||||
REGISTER_MOD_PARSER(G, args)
|
||||
{
|
||||
const int g = utils::from_chars<int>(args).value_or(0);
|
||||
return std::make_unique<cs_modification>(0, g, 0);
|
||||
const int g = lexical_cast_default<int>(args);
|
||||
return std::make_unique<cs_modification>(0,g,0);
|
||||
}
|
||||
|
||||
// Blue component color-shift
|
||||
REGISTER_MOD_PARSER(B, args)
|
||||
{
|
||||
const int b = utils::from_chars<int>(args).value_or(0);
|
||||
return std::make_unique<cs_modification>(0, 0, b);
|
||||
const int b = lexical_cast_default<int>(args);
|
||||
return std::make_unique<cs_modification>(0,0,b);
|
||||
}
|
||||
|
||||
REGISTER_MOD_PARSER(NOP, )
|
||||
|
@ -1198,10 +1208,10 @@ REGISTER_MOD_PARSER(RIGHT, )
|
|||
REGISTER_MOD_PARSER(BG, args)
|
||||
{
|
||||
int c[4] { 0, 0, 0, SDL_ALPHA_OPAQUE };
|
||||
const auto factors = utils::split_view(args, ',');
|
||||
std::vector<std::string> factors = utils::split(args, ',');
|
||||
|
||||
for(int i = 0; i < std::min<int>(factors.size(), 4); ++i) {
|
||||
c[i] = utils::from_chars<int>(factors[i]).value_or(0);
|
||||
c[i] = lexical_cast_default<int>(factors[i]);
|
||||
}
|
||||
|
||||
return std::make_unique<background_modification>(color_t(c[0], c[1], c[2], c[3]));
|
||||
|
@ -1210,7 +1220,7 @@ REGISTER_MOD_PARSER(BG, args)
|
|||
// Channel swap
|
||||
REGISTER_MOD_PARSER(SWAP, args)
|
||||
{
|
||||
const auto params = utils::split_view(args, ',', utils::STRIP_SPACES);
|
||||
std::vector<std::string> params = utils::split(args, ',', utils::STRIP_SPACES);
|
||||
|
||||
// accept 3 arguments (rgb) or 4 (rgba)
|
||||
if(params.size() != 3 && params.size() != 4) {
|
||||
|
|
|
@ -355,7 +355,7 @@ static int intf_name_generator(lua_State *L)
|
|||
if(lua_istable(L, 2)) {
|
||||
input = lua_check<std::vector<std::string>>(L, 2);
|
||||
} else {
|
||||
input = utils::parenthetical_split(luaW_checktstring(L, 2).str(), ',');
|
||||
input = utils::parenthetical_split(luaW_checktstring(L, 2), ',');
|
||||
}
|
||||
int chain_sz = luaL_optinteger(L, 3, 2);
|
||||
int max_len = luaL_optinteger(L, 4, 12);
|
||||
|
|
|
@ -99,15 +99,6 @@ std::set<std::string> split_set(std::string_view s, char sep, const int flags)
|
|||
return res;
|
||||
}
|
||||
|
||||
std::vector<std::string_view> split_view(std::string_view s, const char sep, const int flags)
|
||||
{
|
||||
std::vector<std::string_view> res;
|
||||
split_foreach(s, sep, flags, [&](std::string_view item) {
|
||||
res.push_back(item);
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<std::string> square_parenthetical_split(const std::string& val,
|
||||
const char separator, const std::string& left,
|
||||
const std::string& right,const int flags)
|
||||
|
@ -308,16 +299,19 @@ std::map<std::string, std::string> map_split(
|
|||
return res;
|
||||
}
|
||||
|
||||
std::vector<std::string> parenthetical_split(std::string_view val,
|
||||
const char separator, std::string_view left,
|
||||
std::string_view right,const int flags)
|
||||
std::vector<std::string> parenthetical_split(const std::string& val,
|
||||
const char separator, const std::string& left,
|
||||
const std::string& right,const int flags)
|
||||
{
|
||||
std::vector< std::string > res;
|
||||
std::vector<char> part;
|
||||
bool in_parenthesis = false;
|
||||
|
||||
std::string_view::const_iterator i1 = val.begin();
|
||||
std::string_view::const_iterator i2;
|
||||
std::string lp=left;
|
||||
std::string rp=right;
|
||||
|
||||
std::string::const_iterator i1 = val.begin();
|
||||
std::string::const_iterator i2;
|
||||
if (flags & STRIP_SPACES) {
|
||||
while (i1 != val.end() && portable_isspace(*i1))
|
||||
++i1;
|
||||
|
@ -361,8 +355,8 @@ std::vector<std::string> parenthetical_split(std::string_view val,
|
|||
continue;
|
||||
}
|
||||
bool found=false;
|
||||
for(std::size_t i=0; i < left.size(); i++){
|
||||
if (*i2 == left[i]){
|
||||
for(std::size_t i=0; i < lp.size(); i++){
|
||||
if (*i2 == lp[i]){
|
||||
if (!separator && part.empty()){
|
||||
std::string new_val(i1, i2);
|
||||
if (flags & STRIP_SPACES)
|
||||
|
@ -373,7 +367,7 @@ std::vector<std::string> parenthetical_split(std::string_view val,
|
|||
}else{
|
||||
++i2;
|
||||
}
|
||||
part.push_back(right[i]);
|
||||
part.push_back(rp[i]);
|
||||
found=true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -94,12 +94,12 @@ void split_foreach(std::string_view s, char sep, const int flags, const F& f)
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Splits a (comma-)separated string into a vector of pieces. */
|
||||
std::vector<std::string> split(std::string_view val, const char c = ',', const int flags = REMOVE_EMPTY | STRIP_SPACES);
|
||||
std::set<std::string> split_set(std::string_view val, const char c = ',', const int flags = REMOVE_EMPTY | STRIP_SPACES);
|
||||
|
||||
std::vector<std::string_view> split_view(std::string_view val, const char c = ',', const int flags = REMOVE_EMPTY | STRIP_SPACES);
|
||||
|
||||
/**
|
||||
* This function is identical to split(), except it does not split when it otherwise would if the
|
||||
* previous character was identical to the parameter 'quote' (i.e. it does not split quoted commas).
|
||||
|
@ -149,10 +149,10 @@ std::map<std::string, std::string> map_split(
|
|||
* RETURNS: {"a", "b", "c", "d", "e", "f{g}", "h"}
|
||||
*/
|
||||
std::vector< std::string > parenthetical_split(
|
||||
std::string_view val,
|
||||
const std::string& val,
|
||||
const char separator = 0,
|
||||
std::string_view left = "(",
|
||||
std::string_view right = ")",
|
||||
const std::string& left = "(",
|
||||
const std::string& right = ")",
|
||||
const int flags = REMOVE_EMPTY | STRIP_SPACES);
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2024
|
||||
Part of the Battle for Wesnoth Project https://www.wesnoth.org/
|
||||
|
||||
This program 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; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#include <charconv>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
namespace utils
|
||||
{
|
||||
template<typename T>
|
||||
std::optional<T> from_chars(std::string_view str, int base = 10)
|
||||
{
|
||||
static_assert(std::is_integral_v<T>, "Float support for charconv incomplete on current build requirements");
|
||||
T result {};
|
||||
const auto [_, ec] = std::from_chars(str.data(), str.data() + str.size(), result, base);
|
||||
return ec == std::errc{} ? std::make_optional(result) : std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace utils
|
Loading…
Add table
Reference in a new issue