Improve format specifiers for message boxes

coverity_scan^2
MiroslavR 9 years ago
parent 6f376bd499
commit f6f3f71db5

@ -85,7 +85,7 @@ add_component_dir (esmterrain
) )
add_component_dir (misc add_component_dir (misc
utf8stream stringops resourcehelpers rng utf8stream stringops resourcehelpers rng messageformatparser
) )
IF(NOT WIN32 AND NOT APPLE) IF(NOT WIN32 AND NOT APPLE)

@ -140,30 +140,9 @@ namespace Compiler
if (mState==MessageState || mState==MessageCommaState) if (mState==MessageState || mState==MessageCommaState)
{ {
std::string arguments; GetArgumentsFromMessageFormat processor;
processor.process(name);
for (std::size_t i=0; i<name.size(); ++i) std::string arguments = processor.getArguments();
{
if (name[i]=='%')
{
++i;
if (i<name.size())
{
if (name[i]=='G' || name[i]=='g')
{
arguments += "l";
}
else if (name[i]=='S' || name[i]=='s')
{
arguments += 'S';
}
else if (name[i]=='.' || name[i]=='f')
{
arguments += 'f';
}
}
}
}
if (!arguments.empty()) if (!arguments.empty())
{ {
@ -577,4 +556,23 @@ namespace Compiler
mName.clear(); mName.clear();
mExplicit.clear(); mExplicit.clear();
} }
void GetArgumentsFromMessageFormat::visitedPlaceholder(Placeholder placeholder, char /*padding*/, int /*width*/, int /*precision*/)
{
switch (placeholder)
{
case StringPlaceholder:
mArguments += 'S';
break;
case IntegerPlaceholder:
mArguments += 'l';
break;
case FloatPlaceholder:
mArguments += 'f';
break;
default:
break;
}
}
} }

@ -2,8 +2,10 @@
#define COMPILER_LINEPARSER_H_INCLUDED #define COMPILER_LINEPARSER_H_INCLUDED
#include <vector> #include <vector>
#include <string>
#include <components/interpreter/types.hpp> #include <components/interpreter/types.hpp>
#include <components/misc/messageformatparser.hpp>
#include "parser.hpp" #include "parser.hpp"
#include "exprparser.hpp" #include "exprparser.hpp"
@ -74,6 +76,24 @@ namespace Compiler
void reset(); void reset();
///< Reset parser to clean state. ///< Reset parser to clean state.
}; };
class GetArgumentsFromMessageFormat : public ::Misc::MessageFormatParser
{
private:
std::string mArguments;
protected:
virtual void visitedPlaceholder(Placeholder placeholder, char padding, int width, int precision);
virtual void visitedCharacter(char c) {}
public:
virtual void process(const std::string& message)
{
mArguments.clear();
::Misc::MessageFormatParser::process(message);
}
std::string getArguments() const { return mArguments; }
};
} }
#endif #endif

@ -13,67 +13,89 @@
#include "defines.hpp" #include "defines.hpp"
#include <components/misc/rng.hpp> #include <components/misc/rng.hpp>
#include <components/misc/messageformatparser.hpp>
namespace Interpreter namespace Interpreter
{ {
inline std::string formatMessage (const std::string& message, Runtime& runtime) class RuntimeMessageFormatter : public Misc::MessageFormatParser
{ {
std::string formattedMessage; private:
std::string mFormattedMessage;
for (std::size_t i=0; i<message.size(); ++i) Runtime& mRuntime;
{
char c = message[i];
if (c!='%') protected:
formattedMessage += c; virtual void visitedPlaceholder(Placeholder placeholder, char padding, int width, int precision)
else
{ {
++i; std::ostringstream out;
if (i<message.size()) out.fill(padding);
if (width != -1)
out.width(width);
if (precision != -1)
out.precision(precision);
switch (placeholder)
{ {
c = message[i]; case StringPlaceholder:
if (c=='S' || c=='s')
{
int index = runtime[0].mInteger;
runtime.pop();
formattedMessage += runtime.getStringLiteral (index);
}
else if (c=='g' || c=='G')
{
Type_Integer value = runtime[0].mInteger;
runtime.pop();
std::ostringstream out;
out << value;
formattedMessage += out.str();
}
else if (c=='f' || c=='F' || c=='.')
{
while (c!='f' && i+1<message.size())
{ {
++i; int index = mRuntime[0].mInteger;
c = message[i]; mRuntime.pop();
out << mRuntime.getStringLiteral(index);
mFormattedMessage += out.str();
} }
break;
case IntegerPlaceholder:
{
Type_Integer value = mRuntime[0].mInteger;
mRuntime.pop();
out << value;
mFormattedMessage += out.str();
}
break;
case FloatPlaceholder:
{
float value = mRuntime[0].mFloat;
mRuntime.pop();
float value = runtime[0].mFloat; out << std::fixed << value;
runtime.pop(); mFormattedMessage += out.str();
}
std::ostringstream out; break;
out << value; default:
formattedMessage += out.str(); break;
}
else if (c=='%')
formattedMessage += "%";
else
{
formattedMessage += "%";
formattedMessage += c;
}
} }
} }
}
virtual void visitedCharacter(char c)
{
mFormattedMessage += c;
}
public:
RuntimeMessageFormatter(Runtime& runtime)
: mRuntime(runtime)
{
}
virtual void process(const std::string& message)
{
mFormattedMessage.clear();
MessageFormatParser::process(message);
}
std::string getFormattedMessage() const
{
return mFormattedMessage;
}
};
inline std::string formatMessage (const std::string& message, Runtime& runtime)
{
RuntimeMessageFormatter formatter(runtime);
formatter.process(message);
std::string formattedMessage = formatter.getFormattedMessage();
formattedMessage = fixDefinesMsgBox(formattedMessage, runtime.getContext()); formattedMessage = fixDefinesMsgBox(formattedMessage, runtime.getContext());
return formattedMessage; return formattedMessage;
} }

@ -0,0 +1,68 @@
#include "messageformatparser.hpp"
namespace Misc
{
void MessageFormatParser::process(const std::string& m)
{
for (unsigned int i = 0; i < m.size(); ++i)
{
if (m[i] == '%')
{
if (++i < m.size())
{
if (m[i] == '%')
visitedCharacter('%');
else
{
char pad = ' ';
if (m[i] == '0' || m[i] == ' ')
{
pad = m[i];
++i;
}
int width = 0;
bool widthSet = false;
while (i < m.size() && m[i] >= '0' && m[i] <= '9')
{
width = width * 10 + (m[i] - '0');
widthSet = true;
++i;
}
if (i < m.size())
{
int precision = 0;
bool precisionSet = false;
if (m[i] == '.')
{
while (++i < m.size() && m[i] >= '0' && m[i] <= '9')
{
precision = precision * 10 + (m[i] - '0');
precisionSet = true;
}
}
if (i < m.size())
{
width = (widthSet) ? width : -1;
precision = (precisionSet) ? precision : -1;
if (m[i] == 'S' || m[i] == 's')
visitedPlaceholder(StringPlaceholder, pad, width, precision);
else if (m[i] == 'g' || m[i] == 'G')
visitedPlaceholder(IntegerPlaceholder, pad, width, precision);
else if (m[i] == 'f' || m[i] == 'F')
visitedPlaceholder(FloatPlaceholder, pad, width, precision);
}
}
}
}
}
else
{
visitedCharacter(m[i]);
}
}
}
}

@ -0,0 +1,26 @@
#ifndef OPENMW_COMPONENTS_MISC_MESSAGEFORMATPARSER_H
#define OPENMW_COMPONENTS_MISC_MESSAGEFORMATPARSER_H
#include <string>
namespace Misc
{
class MessageFormatParser
{
protected:
enum Placeholder
{
StringPlaceholder,
IntegerPlaceholder,
FloatPlaceholder
};
virtual void visitedPlaceholder(Placeholder placeholder, char padding, int width, int precision) = 0;
virtual void visitedCharacter(char c) = 0;
public:
virtual void process(const std::string& message);
};
}
#endif
Loading…
Cancel
Save